aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/include/ndpi_api.h.in4
-rw-r--r--src/include/ndpi_typedefs.h26
-rw-r--r--src/lib/ndpi_main.c94
-rw-r--r--src/lib/ndpi_utils.c31
-rw-r--r--src/lib/protocols/http.c72
5 files changed, 150 insertions, 77 deletions
diff --git a/src/include/ndpi_api.h.in b/src/include/ndpi_api.h.in
index 1ba0c1065..bed449f60 100644
--- a/src/include/ndpi_api.h.in
+++ b/src/include/ndpi_api.h.in
@@ -1029,10 +1029,12 @@ extern "C" {
void ndpi_data_print_window_values(struct ndpi_analyze_struct *s); /* debug */
- ndpi_url_risk ndpi_validate_url(char *url);
+ ndpi_risk ndpi_validate_url(char *url);
u_int8_t ndpi_is_protocol_detected(struct ndpi_detection_module_struct *ndpi_str,
ndpi_protocol proto);
+
+ const char* ndpi_risk2str(ndpi_risk risk);
#ifdef __cplusplus
}
#endif
diff --git a/src/include/ndpi_typedefs.h b/src/include/ndpi_typedefs.h
index ef3da7cc5..d1536c4da 100644
--- a/src/include/ndpi_typedefs.h
+++ b/src/include/ndpi_typedefs.h
@@ -51,11 +51,16 @@ typedef enum {
} ndpi_packet_tunnel;
typedef enum {
- ndpi_url_no_problem = 0,
- ndpi_url_possible_xss,
- ndpi_url_possible_sql_injection,
- ndpi_url_possible_rce_injection
-} ndpi_url_risk;
+ NDPI_NO_RISK = 0,
+ NDPI_URL_POSSIBLE_XSS,
+ NDPI_URL_POSSIBLE_SQL_INJECTION,
+ NDPI_URL_POSSIBLE_RCE_INJECTION,
+ NDPI_BINARY_APPLICATION_TRANSFER,
+ NDPI_KNOWN_PROTOCOL_ON_NON_STANDARD_PORT,
+
+ /* Leave this as last member */
+ NDPI_MAX_RISK
+} ndpi_risk;
/* NDPI_VISIT */
typedef enum {
@@ -941,6 +946,7 @@ typedef struct ndpi_proto_defaults {
u_int8_t can_have_a_subprotocol;
u_int16_t protoId, protoIdx;
u_int16_t master_tcp_protoId[2], master_udp_protoId[2]; /* The main protocols on which this sub-protocol sits on */
+ u_int16_t tcp_default_ports[MAX_DEFAULT_PORTS], udp_default_ports[MAX_DEFAULT_PORTS];
ndpi_protocol_breed_t protoBreed;
void (*func) (struct ndpi_detection_module_struct *, struct ndpi_flow_struct *flow);
} ndpi_proto_defaults_t;
@@ -1152,7 +1158,10 @@ struct ndpi_flow_struct {
struct ndpi_id_struct *server_id;
/* HTTP host or DNS query */
u_char host_server_name[240];
-
+ u_int8_t initial_binary_bytes[8], initial_binary_bytes_len;
+ u_int8_t risk_checked;
+ u_int16_t risk; /* Issues found with this flow [bitmask of ndpi_risk] */
+
/*
This structure below will not not stay inside the protos
structure below as HTTP is used by many subprotocols
@@ -1342,10 +1351,7 @@ struct ndpi_flow_struct {
/* NDPI_PROTOCOL_CSGO */
u_int8_t csgo_strid[18],csgo_state,csgo_s2;
u_int32_t csgo_id2;
-
- /* NDPI_PROTOCOL_1KXUN || NDPI_PROTOCOL_IQIYI */
- u_int16_t kxun_counter, iqiyi_counter;
-
+
/* internal structures to save functions calls */
struct ndpi_packet_struct packet;
struct ndpi_flow_struct *flow;
diff --git a/src/lib/ndpi_main.c b/src/lib/ndpi_main.c
index 6e2c30006..dcb34f2ad 100644
--- a/src/lib/ndpi_main.c
+++ b/src/lib/ndpi_main.c
@@ -339,6 +339,10 @@ void ndpi_set_proto_defaults(struct ndpi_detection_module_struct *ndpi_str, ndpi
if(tcpDefPorts[j].port_low != 0)
addDefaultPort(ndpi_str, &tcpDefPorts[j], &ndpi_str->proto_defaults[protoId], 0, &ndpi_str->tcpRoot,
__FUNCTION__, __LINE__);
+
+ /* No port range, just the lower port */
+ ndpi_str->proto_defaults[protoId].tcp_default_ports[j] = tcpDefPorts[j].port_low;
+ ndpi_str->proto_defaults[protoId].udp_default_ports[j] = udpDefPorts[j].port_low;
}
}
@@ -385,8 +389,7 @@ static void addDefaultPort(struct ndpi_detection_module_struct *ndpi_str, ndpi_p
}
node->proto = def, node->default_port = port, node->customUserProto = customUserProto;
- ret = (ndpi_default_ports_tree_node_t *) ndpi_tsearch(
- node, (void *) root, ndpi_default_ports_tree_node_t_cmp); /* Add it to the tree */
+ ret = (ndpi_default_ports_tree_node_t *) ndpi_tsearch(node, (void *) root, ndpi_default_ports_tree_node_t_cmp); /* Add it to the tree */
if(ret != node) {
NDPI_LOG_DBG(ndpi_str, "[NDPI] %s:%d found duplicate for port %u: overwriting it with new value\n", _func,
@@ -708,7 +711,7 @@ static void ndpi_init_protocol_defaults(struct ndpi_detection_module_struct *ndp
ndpi_build_default_ports(ports_b, 177, 0, 0, 0, 0) /* UDP */);
ndpi_set_proto_defaults(ndpi_str, NDPI_PROTOCOL_DANGEROUS, NDPI_PROTOCOL_SMBV1, 0 /* can_have_a_subprotocol */,
no_master, no_master, "SMBv1", NDPI_PROTOCOL_CATEGORY_SYSTEM_OS,
- ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_a, 445, 0, 0, 0, 0) /* TCP */,
ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
ndpi_set_proto_defaults(ndpi_str, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_SYSLOG, 0 /* can_have_a_subprotocol */,
no_master, no_master, "Syslog", NDPI_PROTOCOL_CATEGORY_SYSTEM_OS,
@@ -1220,7 +1223,7 @@ static void ndpi_init_protocol_defaults(struct ndpi_detection_module_struct *ndp
ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
ndpi_set_proto_defaults(ndpi_str, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_APPLE_PUSH,
0 /* can_have_a_subprotocol */, no_master, no_master, "ApplePush",
- NDPI_PROTOCOL_CATEGORY_CLOUD, ndpi_build_default_ports(ports_a, 1, 0, 0, 0, 0) /* TCP */,
+ NDPI_PROTOCOL_CATEGORY_CLOUD, ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
ndpi_set_proto_defaults(ndpi_str, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_DROPBOX, 0 /* can_have_a_subprotocol */,
no_master, no_master, "Dropbox", NDPI_PROTOCOL_CATEGORY_CLOUD,
@@ -3751,9 +3754,8 @@ void ndpi_connection_tracking(struct ndpi_detection_module_struct *ndpi_str, str
void check_ndpi_other_flow_func(struct ndpi_detection_module_struct *ndpi_str, struct ndpi_flow_struct *flow,
NDPI_SELECTION_BITMASK_PROTOCOL_SIZE *ndpi_selection_packet) {
- if(!flow) {
- return;
- }
+ if(!flow)
+ return;
void *func = NULL;
u_int32_t a;
@@ -4336,6 +4338,14 @@ static void ndpi_reset_packet_line_info(struct ndpi_packet_struct *packet) {
/* ********************************************************************************* */
+#if 0
+static u_int16_t ndpi_checK_flow_port(, u_int16_t sport, u_int16_t dport) {
+
+}
+#endif
+
+/* ********************************************************************************* */
+
ndpi_protocol ndpi_detection_process_packet(struct ndpi_detection_module_struct *ndpi_str,
struct ndpi_flow_struct *flow, const unsigned char *packet,
const unsigned short packetlen, const u_int64_t current_tick_l,
@@ -4569,6 +4579,48 @@ ndpi_protocol ndpi_detection_process_packet(struct ndpi_detection_module_struct
ret.app_protocol = flow->guessed_host_protocol_id;
}
+ if((!flow->risk_checked) && (ret.master_protocol != NDPI_PROTOCOL_UNKNOWN)) {
+ ndpi_default_ports_tree_node_t *found;
+ u_int16_t *default_ports, sport, dport;
+
+ if(flow->packet.udp)
+ found = ndpi_get_guessed_protocol_id(ndpi_str, IPPROTO_UDP,
+ sport = ntohs(flow->packet.udp->source),
+ dport = ntohs(flow->packet.udp->dest)),
+ default_ports = ndpi_str->proto_defaults[ret.master_protocol].udp_default_ports;
+ else if(flow->packet.tcp)
+ found = ndpi_get_guessed_protocol_id(ndpi_str, IPPROTO_TCP,
+ sport = ntohs(flow->packet.tcp->source),
+ dport = ntohs(flow->packet.tcp->dest)),
+ default_ports = ndpi_str->proto_defaults[ret.master_protocol].tcp_default_ports;
+ else
+ found = NULL, default_ports = NULL;
+
+ if(found
+ && (found->proto->protoId != NDPI_PROTOCOL_UNKNOWN)
+ && (found->proto->protoId != ret.master_protocol)) {
+ // printf("******** %u / %u\n", found->proto->protoId, ret.master_protocol);
+ NDPI_SET_BIT_16(flow->risk, NDPI_KNOWN_PROTOCOL_ON_NON_STANDARD_PORT);
+ } else if(default_ports && (default_ports[0] != 0)) {
+ u_int8_t found = 0, i;
+
+ for(i=0; (i<MAX_DEFAULT_PORTS) && (default_ports[i] != 0); i++) {
+ if((default_ports[i] == sport) || (default_ports[i] == dport)) {
+ found = 1;
+ break;
+ }
+ } /* for */
+
+ if(!found) {
+ // printf("******** Invalid default port\n");
+ NDPI_SET_BIT_16(flow->risk, NDPI_KNOWN_PROTOCOL_ON_NON_STANDARD_PORT);
+ }
+ }
+
+ flow->risk_checked = 1;
+ }
+
+
invalidate_ptr:
/*
Invalidate packet memory to avoid accessing the pointers below
@@ -4730,15 +4782,15 @@ void ndpi_parse_packet_line_info(struct ndpi_detection_module_struct *ndpi_str,
u_int32_t a;
struct ndpi_packet_struct *packet = &flow->packet;
+ if((packet->payload_packet_len < 3) || (packet->payload == NULL))
+ return;
+
if(packet->packet_lines_parsed_complete != 0)
return;
packet->packet_lines_parsed_complete = 1;
ndpi_reset_packet_line_info(packet);
- if((packet->payload_packet_len < 3) || (packet->payload == NULL))
- return;
-
packet->line[packet->parsed_lines].ptr = packet->payload;
packet->line[packet->parsed_lines].len = 0;
@@ -4746,10 +4798,24 @@ void ndpi_parse_packet_line_info(struct ndpi_detection_module_struct *ndpi_str,
if((a + 1) >= packet->payload_packet_len)
return; /* Return if only one byte remains (prevent invalid reads past end-of-buffer) */
- if(get_u_int16_t(packet->payload, a) ==
- ntohs(0x0d0a)) { /* If end of line char sequence CR+NL "\r\n", process line */
- packet->line[packet->parsed_lines].len = (u_int16_t)(
- ((unsigned long) &packet->payload[a]) - ((unsigned long) packet->line[packet->parsed_lines].ptr));
+ if(get_u_int16_t(packet->payload, a) == ntohs(0x0d0a)) {
+ /* If end of line char sequence CR+NL "\r\n", process line */
+
+ if(get_u_int16_t(packet->payload, a+2) == ntohs(0x0d0a)) {
+ /* \r\n\r\n */
+ int diff; /* No unsigned ! */
+ u_int32_t a1 = a + 4;
+
+ diff = ndpi_min(packet->payload_packet_len-a1, sizeof(flow->initial_binary_bytes));
+
+ if(diff > 0) {
+ memcpy(&flow->initial_binary_bytes, &packet->payload[a1], diff);
+ flow->initial_binary_bytes_len = diff;
+ }
+ }
+
+ packet->line[packet->parsed_lines].len =
+ (u_int16_t)(((unsigned long) &packet->payload[a]) - ((unsigned long) packet->line[packet->parsed_lines].ptr));
/* First line of a HTTP response parsing. Expected a "HTTP/1.? ???" */
if(packet->parsed_lines == 0 && packet->line[0].len >= NDPI_STATICSTRING_LEN("HTTP/1.X 200 ") &&
diff --git a/src/lib/ndpi_utils.c b/src/lib/ndpi_utils.c
index db5394eb0..4eec5d906 100644
--- a/src/lib/ndpi_utils.c
+++ b/src/lib/ndpi_utils.c
@@ -1332,9 +1332,9 @@ static int ndpi_is_rce_injection(char* query) {
/* ********************************** */
-ndpi_url_risk ndpi_validate_url(char *url) {
+ndpi_risk ndpi_validate_url(char *url) {
char *orig_str = NULL, *str = NULL, *question_mark = strchr(url, '?');
- ndpi_url_risk rc = ndpi_url_no_problem;
+ ndpi_risk rc = NDPI_NO_RISK;
if(question_mark) {
char *tmp;
@@ -1364,12 +1364,12 @@ ndpi_url_risk ndpi_validate_url(char *url) {
/* Valid string */
if(ndpi_is_xss_injection(decoded))
- rc = ndpi_url_possible_xss;
+ rc = NDPI_URL_POSSIBLE_XSS;
else if(ndpi_is_sql_injection(decoded))
- rc = ndpi_url_possible_sql_injection;
+ rc = NDPI_URL_POSSIBLE_SQL_INJECTION;
#ifdef HAVE_PCRE
else if(ndpi_is_rce_injection(decoded))
- rc = ndpi_url_possible_rce_injection;
+ rc = NDPI_URL_POSSIBLE_RCE_INJECTION;
#endif
#ifdef URL_CHECK_DEBUG
@@ -1379,7 +1379,7 @@ ndpi_url_risk ndpi_validate_url(char *url) {
ndpi_free(decoded);
- if(rc != ndpi_url_no_problem)
+ if(rc != NDPI_NO_RISK)
break;
}
@@ -1403,3 +1403,22 @@ u_int8_t ndpi_is_protocol_detected(struct ndpi_detection_module_struct *ndpi_str
else
return(0);
}
+
+/* ******************************************************************** */
+
+const char* ndpi_risk2str(ndpi_risk risk) {
+ switch(risk) {
+ case NDPI_URL_POSSIBLE_XSS:
+ return("XSS attack");
+ case NDPI_URL_POSSIBLE_SQL_INJECTION:
+ return("SQL injection");
+ case NDPI_URL_POSSIBLE_RCE_INJECTION:
+ return("RCE injection");
+ case NDPI_BINARY_APPLICATION_TRANSFER:
+ return("Binary application transfer");
+ case NDPI_KNOWN_PROTOCOL_ON_NON_STANDARD_PORT:
+ return("Known protocol on non standard port");
+ default:
+ return("");
+ }
+}
diff --git a/src/lib/protocols/http.c b/src/lib/protocols/http.c
index 00522cfb9..56ebdfdec 100644
--- a/src/lib/protocols/http.c
+++ b/src/lib/protocols/http.c
@@ -33,6 +33,25 @@ static void ndpi_search_http_tcp(struct ndpi_detection_module_struct *ndpi_struc
/* *********************************************** */
+static void ndpi_analyze_content_signature(struct ndpi_flow_struct *flow) {
+ if((flow->initial_binary_bytes_len >= 2) && (flow->initial_binary_bytes[0] == 0x4D) && (flow->initial_binary_bytes[1] == 0x5A))
+ NDPI_SET_BIT_16(flow->risk, NDPI_BINARY_APPLICATION_TRANSFER); /* Win executable */
+ else if((flow->initial_binary_bytes_len >= 4) && (flow->initial_binary_bytes[0] == 0x7F) && (flow->initial_binary_bytes[1] == 'E')
+ && (flow->initial_binary_bytes[2] == 'L') && (flow->initial_binary_bytes[3] == 'F'))
+ NDPI_SET_BIT_16(flow->risk, NDPI_BINARY_APPLICATION_TRANSFER); /* Linux executable */
+ else if((flow->initial_binary_bytes_len >= 4) && (flow->initial_binary_bytes[0] == 0xCF) && (flow->initial_binary_bytes[1] == 0xFA)
+ && (flow->initial_binary_bytes[2] == 0xED) && (flow->initial_binary_bytes[3] == 0xFE))
+ NDPI_SET_BIT_16(flow->risk, NDPI_BINARY_APPLICATION_TRANSFER); /* Linux executable */
+ else if(flow->initial_binary_bytes_len >= 8) {
+ u_int8_t exec_pattern[] = { 0x64, 0x65, 0x78, 0x0A, 0x30, 0x33, 0x35, 0x00 };
+
+ if(memcmp(flow->initial_binary_bytes, exec_pattern, 8) == 0)
+ NDPI_SET_BIT_16(flow->risk, NDPI_BINARY_APPLICATION_TRANSFER); /* Dalvik Executable (Android) */
+ }
+}
+
+/* *********************************************** */
+
static int ndpi_search_http_tcp_again(struct ndpi_detection_module_struct *ndpi_struct,
struct ndpi_flow_struct *flow) {
ndpi_search_http_tcp(ndpi_struct, flow);
@@ -41,8 +60,12 @@ static int ndpi_search_http_tcp_again(struct ndpi_detection_module_struct *ndpi_
printf("=> %s()\n", __FUNCTION__);
#endif
- if((flow->host_server_name[0] != '\0') && (flow->http.response_status_code != 0)) {
+ if((flow->host_server_name[0] != '\0')
+ && (flow->http.response_status_code != 0)
+ ) {
/* stop extra processing */
+
+ if(flow->initial_binary_bytes_len) ndpi_analyze_content_signature(flow);
flow->extra_packets_func = NULL; /* We're good now */
return(0);
}
@@ -612,7 +635,8 @@ static void ndpi_check_http_tcp(struct ndpi_detection_module_struct *ndpi_struct
"Found more than one line, we look further for the next packet...\n");
if(packet->line[0].len >= (9 + filename_start)
- && memcmp(&packet->line[0].ptr[packet->line[0].len - 9], " HTTP/1.", 8) == 0) { /* Request line complete. Ex. "GET / HTTP/1.1" */
+ && memcmp(&packet->line[0].ptr[packet->line[0].len - 9], " HTTP/1.", 8) == 0) {
+ /* Request line complete. Ex. "GET / HTTP/1.1" */
packet->http_url_name.ptr = &packet->payload[filename_start];
packet->http_url_name.len = packet->line[0].len - (filename_start + 9);
@@ -635,50 +659,6 @@ static void ndpi_check_http_tcp(struct ndpi_detection_module_struct *ndpi_struct
goto ookla_found;
}
-#if defined(NDPI_PROTOCOL_1KXUN) || defined(NDPI_PROTOCOL_IQIYI)
- /* check PPStream protocol or iQiyi service
- (iqiyi is delivered by ppstream) */
- // substring in url
- if(ndpi_strnstr((const char*) &packet->payload[filename_start], "iqiyi.com",
- (packet->payload_packet_len - filename_start)) != NULL) {
- if(flow->kxun_counter == 0) {
- flow->l4.tcp.ppstream_stage++;
- flow->iqiyi_counter++;
- check_content_type_and_change_protocol(ndpi_struct, flow); /* ***** CHECK ****** */
- return;
- }
- }
-
- // additional field in http payload
- x = 1;
- while((packet->line[x].len >= 4) && (packet->line[x+1].len >= 5) && (packet->line[x+2].len >= 10)) {
- if(packet->line[x].ptr && ((memcmp(packet->line[x].ptr, "qyid", 4)) == 0)
- && packet->line[x+1].ptr && ((memcmp(packet->line[x+1].ptr, "qypid", 5)) == 0)
- && packet->line[x+2].ptr && ((memcmp(packet->line[x+2].ptr, "qyplatform", 10)) == 0)
- ) {
- flow->l4.tcp.ppstream_stage++;
- flow->iqiyi_counter++;
- check_content_type_and_change_protocol(ndpi_struct, flow);
- return;
- }
- x++;
- }
-#endif
-
-#if defined(NDPI_PROTOCOL_1KXUN) || defined(NDPI_PROTOCOL_IQIYI)
- /* Check for 1kxun packet */
- int a;
- for (a = 0; a < packet->parsed_lines; a++) {
- if(packet->line[a].len >= 14 && (memcmp(packet->line[a].ptr, "Client-Source:", 14)) == 0) {
- if((memcmp(packet->line[a].ptr+15, "1kxun", 5)) == 0) {
- flow->kxun_counter++;
- check_content_type_and_change_protocol(ndpi_struct, flow);
- return;
- }
- }
- }
-#endif
-
if((packet->http_url_name.len > 7)
&& (!strncmp((const char*) packet->http_url_name.ptr, "http://", 7))) {
NDPI_LOG_INFO(ndpi_struct, "found HTTP_PROXY\n");