diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/include/ndpi_api.h.in | 4 | ||||
-rw-r--r-- | src/include/ndpi_typedefs.h | 26 | ||||
-rw-r--r-- | src/lib/ndpi_main.c | 94 | ||||
-rw-r--r-- | src/lib/ndpi_utils.c | 31 | ||||
-rw-r--r-- | src/lib/protocols/http.c | 72 |
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"); |