aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuca Deri <deri@ntop.org>2021-04-26 10:17:29 +0200
committerLuca Deri <deri@ntop.org>2021-04-26 10:17:29 +0200
commit4a09707e4868cecb62cd8b115ea5eaf1cfa4f835 (patch)
treed7f2242326c2cb678284428f19e9e79a6557ad79
parenta04efb7ce76b796ec73decc1ec18827b51b0cb32 (diff)
Added flow risk to wireshark dissection
-rw-r--r--example/ndpiReader.c10
-rw-r--r--example/reader_util.c24
-rw-r--r--example/reader_util.h53
-rw-r--r--src/include/ndpi_typedefs.h3
-rw-r--r--wireshark/ndpi.lua69
5 files changed, 122 insertions, 37 deletions
diff --git a/example/ndpiReader.c b/example/ndpiReader.c
index 00d62ffef..3a88c0aab 100644
--- a/example/ndpiReader.c
+++ b/example/ndpiReader.c
@@ -172,10 +172,12 @@ struct receiver {
struct receiver *receivers = NULL, *topReceivers = NULL;
+#define WIRESHARK_NTOP_MAGIC 0x19680924
struct ndpi_packet_trailer {
- u_int32_t magic; /* 0x19682017 */
+ u_int32_t magic; /* WIRESHARK_NTOP_MAGIC */
u_int16_t master_protocol /* e.g. HTTP */, app_protocol /* e.g. FaceBook */;
+ ndpi_risk flow_risk;
char name[16];
};
@@ -3217,6 +3219,7 @@ static void ndpi_process_packet(u_char *args,
const struct pcap_pkthdr *header,
const u_char *packet) {
struct ndpi_proto p;
+ ndpi_risk flow_risk;
u_int16_t thread_id = *((u_int16_t*)args);
/* allocate an exact size buffer to check overflows */
@@ -3226,7 +3229,7 @@ static void ndpi_process_packet(u_char *args,
return ;
}
memcpy(packet_checked, packet, header->caplen);
- p = ndpi_workflow_process_packet(ndpi_thread_info[thread_id].workflow, header, packet_checked, csv_fp);
+ p = ndpi_workflow_process_packet(ndpi_thread_info[thread_id].workflow, header, packet_checked, &flow_risk, csv_fp);
if(!pcap_start.tv_sec) pcap_start.tv_sec = header->ts.tv_sec, pcap_start.tv_usec = header->ts.tv_usec;
pcap_end.tv_sec = header->ts.tv_sec, pcap_end.tv_usec = header->ts.tv_usec;
@@ -3281,7 +3284,8 @@ static void ndpi_process_packet(u_char *args,
trailer = (struct ndpi_packet_trailer*)&extcap_buf[h.caplen];
memcpy(extcap_buf, packet, h.caplen);
memset(trailer, 0, sizeof(struct ndpi_packet_trailer));
- trailer->magic = htonl(0x19680924);
+ trailer->magic = htonl(WIRESHARK_NTOP_MAGIC);
+ trailer->flow_risk = htonl(flow_risk);
trailer->master_protocol = htons(p.master_protocol), trailer->app_protocol = htons(p.app_protocol);
ndpi_protocol2name(ndpi_thread_info[thread_id].workflow->ndpi_struct, p, trailer->name, sizeof(trailer->name));
crc = (uint32_t*)&extcap_buf[h.caplen+sizeof(struct ndpi_packet_trailer)];
diff --git a/example/reader_util.c b/example/reader_util.c
index 0e6cd8e97..b95168e8d 100644
--- a/example/reader_util.c
+++ b/example/reader_util.c
@@ -1306,8 +1306,9 @@ static struct ndpi_proto packet_processing(struct ndpi_workflow * workflow,
u_int16_t ipsize, u_int16_t rawsize,
const struct pcap_pkthdr *header,
const u_char *packet,
- pkt_timeval when,
- FILE * csv_fp) {
+ pkt_timeval when,
+ ndpi_risk *flow_risk,
+ FILE * csv_fp) {
struct ndpi_id_struct *src, *dst;
struct ndpi_flow_info *flow = NULL;
struct ndpi_flow_struct *ndpi_flow = NULL;
@@ -1539,6 +1540,18 @@ static struct ndpi_proto packet_processing(struct ndpi_workflow * workflow,
}
}
+#if 0
+ if(flow->risk != 0) {
+ FILE *r = fopen("/tmp/e", "a");
+
+ if(r) {
+ fprintf(r, "->>> %u [%08X]\n", flow->risk, flow->risk);
+ fclose(r);
+ }
+ }
+#endif
+
+ *flow_risk = flow->risk;
return(flow->detected_protocol);
}
@@ -1567,6 +1580,7 @@ int ndpi_is_datalink_supported(int datalink_type)
struct ndpi_proto ndpi_workflow_process_packet(struct ndpi_workflow * workflow,
const struct pcap_pkthdr *header,
const u_char *packet,
+ ndpi_risk *flow_risk,
FILE * csv_fp) {
/*
* Declare pointers to packet headers
@@ -1615,6 +1629,8 @@ struct ndpi_proto ndpi_workflow_process_packet(struct ndpi_workflow * workflow,
/* counters */
u_int8_t vlan_packet = 0;
+ *flow_risk = 0 /* NDPI_NO_RISK */;
+
/* Increment raw packet counter */
workflow->stats.raw_packet_count++;
@@ -1638,7 +1654,6 @@ struct ndpi_proto ndpi_workflow_process_packet(struct ndpi_workflow * workflow,
datalink_type = (int)pcap_datalink(workflow->pcap_handle);
#endif
-
datalink_check:
// 20 for min iph and 8 for min UDP
if(header->caplen < eth_offset + 28)
@@ -1730,7 +1745,6 @@ struct ndpi_proto ndpi_workflow_process_packet(struct ndpi_workflow * workflow,
if(header->caplen < (eth_offset + radio_len + sizeof(struct ndpi_wifi_header)))
return(nproto);
-
/* Calculate 802.11 header length (variable) */
wifi = (struct ndpi_wifi_header*)( packet + eth_offset + radio_len);
fc = wifi->fc;
@@ -2030,7 +2044,7 @@ struct ndpi_proto ndpi_workflow_process_packet(struct ndpi_workflow * workflow,
return(packet_processing(workflow, time_ms, vlan_id, tunnel_type, iph, iph6,
ip_offset, header->caplen - ip_offset,
header->caplen, header, packet, header->ts,
- csv_fp));
+ flow_risk, csv_fp));
}
/* ********************************************************** */
diff --git a/example/reader_util.h b/example/reader_util.h
index 5ec8b558c..c54d68aa4 100644
--- a/example/reader_util.h
+++ b/example/reader_util.h
@@ -94,38 +94,38 @@ extern int dpdk_port_deinit(int port);
// inner hash table (ja3 -> security state)
typedef struct ndpi_ja3_info {
- char * ja3;
- ndpi_cipher_weakness unsafe_cipher;
- UT_hash_handle hh;
+ char * ja3;
+ ndpi_cipher_weakness unsafe_cipher;
+ UT_hash_handle hh;
} ndpi_ja3_info;
// external hash table (host ip -> <ip string, hash table ja3c, hash table ja3s>)
// used to aggregate ja3 fingerprints by hosts
typedef struct ndpi_host_ja3_fingerprints {
- u_int32_t ip;
- char *ip_string;
- char *dns_name;
- ndpi_ja3_info *host_client_info_hasht;
- ndpi_ja3_info *host_server_info_hasht;
+ u_int32_t ip;
+ char *ip_string;
+ char *dns_name;
+ ndpi_ja3_info *host_client_info_hasht;
+ ndpi_ja3_info *host_server_info_hasht;
- UT_hash_handle hh;
+ UT_hash_handle hh;
} ndpi_host_ja3_fingerprints;
//inner hash table
typedef struct ndpi_ip_dns{
- u_int32_t ip;
- char *ip_string;
- char *dns_name; //server name if any;
- UT_hash_handle hh;
+ u_int32_t ip;
+ char *ip_string;
+ char *dns_name; //server name if any;
+ UT_hash_handle hh;
} ndpi_ip_dns;
//hash table ja3 -> <host, ip, security>, used to aggregate host by ja3 fingerprints
typedef struct ndpi_ja3_fingerprints_host{
- char *ja3; //key
- ndpi_cipher_weakness unsafe_cipher;
- ndpi_ip_dns *ipToDNS_ht;
- UT_hash_handle hh;
+ char *ja3; //key
+ ndpi_cipher_weakness unsafe_cipher;
+ ndpi_ip_dns *ipToDNS_ht;
+ UT_hash_handle hh;
} ndpi_ja3_fingerprints_host;
struct flow_metrics {
@@ -294,14 +294,14 @@ typedef struct ndpi_workflow {
void **ndpi_flows_root;
struct ndpi_detection_module_struct *ndpi_struct;
u_int32_t num_allocated_flows;
- } ndpi_workflow_t;
+} ndpi_workflow_t;
/* TODO: remove wrappers parameters and use ndpi global, when their initialization will be fixed... */
struct ndpi_workflow * ndpi_workflow_init(const struct ndpi_workflow_prefs * prefs, pcap_t * pcap_handle);
- /* workflow main free function */
+/* workflow main free function */
void ndpi_workflow_free(struct ndpi_workflow * workflow);
@@ -316,7 +316,8 @@ void ndpi_free_flow_info_half(struct ndpi_flow_info *flow);
struct ndpi_proto ndpi_workflow_process_packet(struct ndpi_workflow * workflow,
const struct pcap_pkthdr *header,
const u_char *packet,
- FILE * csv_fp);
+ ndpi_risk *flow_risk,
+ FILE * csv_fp);
int ndpi_is_datalink_supported(int datalink_type);
@@ -334,7 +335,7 @@ static inline void ndpi_workflow_set_flow_giveup_callback(struct ndpi_workflow *
workflow->__flow_giveup_udata = udata;
}
- /* compare two nodes in workflow */
+/* compare two nodes in workflow */
int ndpi_workflow_node_cmp(const void *a, const void *b);
void process_ndpi_collected_info(struct ndpi_workflow * workflow, struct ndpi_flow_info *flow, FILE * csv_fp);
u_int32_t ethernet_crc32(const void* data, size_t n_bytes);
@@ -346,13 +347,13 @@ float ndpi_flow_get_byte_count_entropy(const uint32_t byte_count[256], unsigned
extern int nDPI_LogLevel;
#ifdef NDPI_ENABLE_DEBUG_MESSAGES
- #define LOG(log_level, args...) \
- { \
- if(log_level <= nDPI_LogLevel) \
- printf(args); \
+#define LOG(log_level, args...) \
+ { \
+ if(log_level <= nDPI_LogLevel) \
+ printf(args); \
}
#else
- #define LOG(...) {}
+#define LOG(...) {}
#endif
#endif
diff --git a/src/include/ndpi_typedefs.h b/src/include/ndpi_typedefs.h
index 5fc4ca06e..54a5caaf6 100644
--- a/src/include/ndpi_typedefs.h
+++ b/src/include/ndpi_typedefs.h
@@ -62,9 +62,10 @@ typedef enum {
/*
NOTE
When the typedef below is modified don't forget to update
+ - nDPI/wireshark/ndpi.lua
- ndpi_risk2str (in ndpi_utils.c)
- https://github.com/ntop/ntopng/blob/dev/scripts/lua/modules/flow_risk_utils.lua
- - ndpi_risk_enum (in python/ndpi.py)
+ - ndpi_risk_enum (in python/ndpi.py)
*/
typedef enum {
NDPI_NO_RISK = 0,
diff --git a/wireshark/ndpi.lua b/wireshark/ndpi.lua
index 51e0cb388..b594c5697 100644
--- a/wireshark/ndpi.lua
+++ b/wireshark/ndpi.lua
@@ -26,6 +26,8 @@ local ndpi_fds = ndpi_proto.fields
ndpi_fds.network_protocol = ProtoField.new("nDPI Network Protocol", "ndpi.protocol.network", ftypes.UINT8, nil, base.DEC)
ndpi_fds.application_protocol = ProtoField.new("nDPI Application Protocol", "ndpi.protocol.application", ftypes.UINT8, nil, base.DEC)
ndpi_fds.name = ProtoField.new("nDPI Protocol Name", "ndpi.protocol.name", ftypes.STRING)
+ndpi_fds.flow_risk = ProtoField.new("nDPI Flow Risk", "ndpi.flow_risk", ftypes.UINT32, nil, base.DEC)
+ndpi_fds.flow_risk_str = ProtoField.new("nDPI Flow Risk String", "ndpi.flow_risk_str", ftypes.STRING)
local ntop_proto = Proto("ntop", "ntop Extensions")
ntop_proto.fields = {}
@@ -886,6 +888,65 @@ function latency_dissector(tvb, pinfo, tree)
end
end
+
+function bit(p)
+ return 2 ^ (p - 1) -- 1-based indexing
+end
+
+function hasbit(x, p)
+ return x % (p + p) >= p
+end
+
+local ndpi_risks = {
+ ['0'] = "No Risk",
+ ['1'] = "XSS attack",
+ ['2'] = "SQL injection",
+ ['3'] = "RCE injection",
+ ['4'] = "Binary application transfer",
+ ['5'] = "Known protocol on non standard port",
+ ['6'] = "Self-signed Certificate",
+ ['7'] = "Obsolete TLS version (< 1.1)",
+ ['8'] = "Weak TLS cipher",
+ ['9'] = "TLS Expired Certificate",
+ ['10'] = "TLS Certificate Mismatch",
+ ['11'] = "HTTP Suspicious User-Agent",
+ ['12'] = "HTTP Numeric IP Address",
+ ['13'] = "HTTP Suspicious URL",
+ ['14'] = "HTTP Suspicious Header",
+ ['15'] = "TLS (probably) not carrying HTTPS",
+ ['16'] = "Suspicious DGA domain name",
+ ['17'] = "Malformed packet",
+ ['18'] = "SSH Obsolete Client Version/Cipher",
+ ['19'] = "SSH Obsolete Server Version/Cipher",
+ ['20'] = "SMB Insecure Version",
+ ['21'] = "TLS Suspicious ESNI Usage",
+ ['22'] = "Unsafe Protocol",
+ ['23'] = "Suspicious DNS traffic",
+ ['24'] = "SNI TLS extension was missing",
+ ['25'] = "HTTP suspicious content",
+ ['26'] = "Risky ASN",
+ ['27'] = "Risky domain name",
+ ['28'] = "Possibly Malicious JA3 Fingerprint",
+ ['29'] = "Possibly Malicious SSL Certificate SHA1 Fingerprint",
+ ['30'] = "Desktop/File Sharing Session",
+ ['31'] = ""
+}
+
+function map_ndpi_risk(r)
+ local ret = ""
+
+ if(r ~= 0) then
+ for i=0,31 do
+ if(hasbit(r, bit(i))) then
+ ret = ret.."["..ndpi_risks[(i-1)..""].."]"
+ end
+ end
+ end
+
+ return(ret)
+end
+
+
-- the dissector function callback
function ndpi_proto.dissector(tvb, pinfo, tree)
-- Wireshark dissects the packet twice. We ignore the first
@@ -918,14 +979,18 @@ function ndpi_proto.dissector(tvb, pinfo, tree)
local ndpi_subtree = tree:add(ndpi_proto, tvb(), "nDPI Protocol")
local network_protocol = tonumber(elems[2]..elems[3], 16) -- 16 = HEX
local application_protocol = tonumber(elems[4]..elems[5], 16) -- 16 = HEX
+ local str_risk = elems[6]..elems[7]..elems[8]..elems[9]
+ local flow_risk = tonumber(str_risk, 16) -- 16 = HEX
local name = ""
- for i=6,21 do
+ for i=10,25 do
name = name .. string.char(tonumber(elems[i], 16))
end
ndpi_subtree:add(ndpi_fds.network_protocol, network_protocol)
ndpi_subtree:add(ndpi_fds.application_protocol, application_protocol)
+ ndpi_subtree:add(ndpi_fds.flow_risk, flow_risk)
+ ndpi_subtree:add(ndpi_fds.flow_risk_str, map_ndpi_risk(flow_risk))
ndpi_subtree:add(ndpi_fds.name, name)
if(application_protocol ~= 0) then
@@ -954,7 +1019,7 @@ function ndpi_proto.dissector(tvb, pinfo, tree)
for k,v in pairsByValues(ndpi_flows, asc) do
if(k ~= flowkey) then
- table.remove(ndpi_flows, k)
+ ndpi_flows[k] = nil -- Remove entry
num_ndpi_flows = num_ndpi_flows + 1
if(num_ndpi_flows == (2*max_num_entries)) then
break