diff options
author | Luca Deri <deri@ntop.org> | 2021-01-06 12:25:32 +0100 |
---|---|---|
committer | Luca Deri <deri@ntop.org> | 2021-01-06 12:25:32 +0100 |
commit | cd21f0d31647444d93536bed2516ddc175e09b25 (patch) | |
tree | 078a9279b8177b949c834331758829a90aa33e23 /src/lib/protocols/http.c | |
parent | 1b524f553886bdd37aea4a3e04e00d9949f979e7 (diff) |
Added check for invalid HTTP content
Diffstat (limited to 'src/lib/protocols/http.c')
-rw-r--r-- | src/lib/protocols/http.c | 221 |
1 files changed, 122 insertions, 99 deletions
diff --git a/src/lib/protocols/http.c b/src/lib/protocols/http.c index 3cfc0a394..63f68a0f4 100644 --- a/src/lib/protocols/http.c +++ b/src/lib/protocols/http.c @@ -98,6 +98,85 @@ static int ndpi_search_http_tcp_again(struct ndpi_detection_module_struct *ndpi_ /* *********************************************** */ +static int ndpi_http_is_print(char c) { + if(isprint(c) || (c == '\t') || (c == '\r') || (c == '\n')) + return(1); + else + return(0); +} + +/* *********************************************** */ + +static void ndpi_http_check_human_redeable_content(struct ndpi_detection_module_struct *ndpi_struct, + struct ndpi_flow_struct *flow, + const u_int8_t *content, u_int16_t content_len) { + if(content_len >= 4) { +#ifdef NDPI_ENABLE_DEBUG_MESSAGES + int i; + + printf(" [len: %u] [%02X %02X %02X %02X][%c%c%c%c]", len, + content[0], content[1], content[2], content[3], + content[0], content[1], content[2], content[3] + ); +#endif + + if(ndpi_http_is_print(content[0]) && ndpi_http_is_print(content[1]) + && ndpi_http_is_print(content[2]) && ndpi_http_is_print(content[3])) { + /* OK */ + } else { + /* Looks bad: last resort check if it's gzipped [1F 8B 08 00] */ + + if((content[0] == 0x1F) + && (content[1] == 0x8B) + && (content[2] == 0x08) + && (content[3] == 0x00)) { + /* Looks like compressed data */ + } else + NDPI_SET_BIT(flow->risk, NDPI_HTTP_SUSPICIOUS_CONTENT); + } + } +} + +/* *********************************************** */ + +static void ndpi_validate_http_content(struct ndpi_detection_module_struct *ndpi_struct, + struct ndpi_flow_struct *flow) { + struct ndpi_packet_struct *packet = &flow->packet; + const u_int8_t *double_ret = (const u_int8_t *)ndpi_strnstr((const char *)packet->payload, "\r\n\r\n", packet->payload_packet_len); + +#ifdef NDPI_ENABLE_DEBUG_MESSAGES + printf("==>>> [len: %u] ", packet->payload_packet_len); + printf("->> %s\n", (const char *)packet->content_line.ptr); +#endif + + if(double_ret) { + u_int len; + + len = packet->payload_packet_len - (double_ret - packet->payload); + + if(ndpi_strnstr((const char *)packet->content_line.ptr, "text/", packet->content_line.len) + || ndpi_strnstr((const char *)packet->content_line.ptr, "/json", packet->content_line.len) + || ndpi_strnstr((const char *)packet->content_line.ptr, "x-www-form-urlencoded", packet->content_line.len) + ) { + /* This is supposed to be a human-readeable text file */ + + packet->http_check_content = 1; + + if(len >= 8 /* 4 chars for \r\n\r\n and at least 4 charts for content guess */) { + double_ret += 4; + + ndpi_http_check_human_redeable_content(ndpi_struct, flow, double_ret, len); + } + } + +#ifdef NDPI_ENABLE_DEBUG_MESSAGES + printf("\n"); +#endif + } +} + +/* *********************************************** */ + /* https://www.freeformatter.com/mime-types-list.html */ static ndpi_protocol_category_t ndpi_http_check_content(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow) { @@ -113,47 +192,51 @@ static ndpi_protocol_category_t ndpi_http_check_content(struct ndpi_detection_mo if(strncasecmp(app, "mpeg", app_len_avail) == 0) { flow->guessed_category = flow->category = NDPI_PROTOCOL_CATEGORY_STREAMING; return(flow->category); - } else if(app_len_avail > 3) { - const char** cmp_mimes = NULL; - - switch(app[0]) { - case 'b': cmp_mimes = download_file_mimes_b; break; - case 'o': cmp_mimes = download_file_mimes_o; break; - case 'x': cmp_mimes = download_file_mimes_x; break; - } + } else { + if(app_len_avail > 3) { + const char** cmp_mimes = NULL; + + switch(app[0]) { + case 'b': cmp_mimes = download_file_mimes_b; break; + case 'o': cmp_mimes = download_file_mimes_o; break; + case 'x': cmp_mimes = download_file_mimes_x; break; + } - if(cmp_mimes != NULL) { - u_int8_t i; + if(cmp_mimes != NULL) { + u_int8_t i; - for(i = 0; cmp_mimes[i] != NULL; i++) { - if(strncasecmp(app, cmp_mimes[i], app_len_avail) == 0) { - flow->guessed_category = flow->category = NDPI_PROTOCOL_CATEGORY_DOWNLOAD_FT; - NDPI_LOG_INFO(ndpi_struct, "found executable HTTP transfer"); - break; + for(i = 0; cmp_mimes[i] != NULL; i++) { + if(strncasecmp(app, cmp_mimes[i], app_len_avail) == 0) { + flow->guessed_category = flow->category = NDPI_PROTOCOL_CATEGORY_DOWNLOAD_FT; + NDPI_LOG_INFO(ndpi_struct, "found executable HTTP transfer"); + break; + } } } - } - /* ***************************************** */ + /* ***************************************** */ - switch(app[0]) { - case 'e': cmp_mimes = binary_file_mimes_e; break; - case 'v': cmp_mimes = binary_file_mimes_v; break; - case 'x': cmp_mimes = binary_file_mimes_x; break; - } + switch(app[0]) { + case 'e': cmp_mimes = binary_file_mimes_e; break; + case 'v': cmp_mimes = binary_file_mimes_v; break; + case 'x': cmp_mimes = binary_file_mimes_x; break; + } - if(cmp_mimes != NULL) { - u_int8_t i; + if(cmp_mimes != NULL) { + u_int8_t i; - for(i = 0; cmp_mimes[i] != NULL; i++) { - if(strncasecmp(app, cmp_mimes[i], app_len_avail) == 0) { - flow->guessed_category = flow->category = NDPI_PROTOCOL_CATEGORY_DOWNLOAD_FT; - NDPI_SET_BIT(flow->risk, NDPI_BINARY_APPLICATION_TRANSFER); - NDPI_LOG_INFO(ndpi_struct, "found executable HTTP transfer"); - return(flow->category); + for(i = 0; cmp_mimes[i] != NULL; i++) { + if(strncasecmp(app, cmp_mimes[i], app_len_avail) == 0) { + flow->guessed_category = flow->category = NDPI_PROTOCOL_CATEGORY_DOWNLOAD_FT; + NDPI_SET_BIT(flow->risk, NDPI_BINARY_APPLICATION_TRANSFER); + NDPI_LOG_INFO(ndpi_struct, "found executable HTTP transfer"); + return(flow->category); + } } } } + + ndpi_validate_http_content(ndpi_struct, flow); } } @@ -171,7 +254,7 @@ static ndpi_protocol_category_t ndpi_http_check_content(struct ndpi_detection_mo for(int i = 0; binary_file_ext[i] != NULL; i++) { /* Use memcmp in case content-disposition contains binary data */ if(memcmp((const char*)&packet->content_disposition_line.ptr[attachment_len], - binary_file_ext[i], ATTACHMENT_LEN) == 0) { + binary_file_ext[i], ATTACHMENT_LEN) == 0) { flow->guessed_category = flow->category = NDPI_PROTOCOL_CATEGORY_DOWNLOAD_FT; NDPI_SET_BIT(flow->risk, NDPI_BINARY_APPLICATION_TRANSFER); NDPI_LOG_INFO(ndpi_struct, "found executable HTTP transfer"); @@ -557,7 +640,8 @@ static void check_content_type_and_change_protocol(struct ndpi_detection_module_ packet->content_line.len); flow->http.content_type[packet->content_line.len] = '\0'; - flow->guessed_category = flow->category = ndpi_http_check_content(ndpi_struct, flow);} + flow->guessed_category = flow->category = ndpi_http_check_content(ndpi_struct, flow); + } } if(flow->http_detected) { @@ -746,16 +830,6 @@ static void ndpi_check_http_header(struct ndpi_detection_module_struct *ndpi_str } } } - -/*************************************************************************************************/ - -static int ndpi_http_is_print(char c) { - if(isprint(c) || (c == '\t') || (c == '\r') || (c == '\n')) - return(1); - else - return(0); -} - /*************************************************************************************************/ static void ndpi_check_http_tcp(struct ndpi_detection_module_struct *ndpi_struct, @@ -765,6 +839,11 @@ static void ndpi_check_http_tcp(struct ndpi_detection_module_struct *ndpi_struct packet->packet_lines_parsed_complete = 0; + if(packet->http_check_content && (packet->payload_packet_len > 0)) { + ndpi_http_check_human_redeable_content(ndpi_struct, flow, packet->payload, packet->payload_packet_len); + packet->http_check_content = 0; /* One packet is enough */ + } + /* Check if we so far detected the protocol in the request or not. */ if((packet->payload_packet_len > 0) /* Needed in case of extra packet processing */ && (flow->l4.tcp.http_stage == 0)) { @@ -796,63 +875,7 @@ static void ndpi_check_http_tcp(struct ndpi_detection_module_struct *ndpi_struct ndpi_parse_packet_line_info(ndpi_struct, flow); check_content_type_and_change_protocol(ndpi_struct, flow); - - - { - const u_int8_t *double_ret = (const u_int8_t *)ndpi_strnstr((const char *)packet->payload, "\r\n\r\n", packet->payload_packet_len); - -#ifdef NDPI_ENABLE_DEBUG_MESSAGES - printf("==>>> [len: %u] ", packet->payload_packet_len); -#endif - - if(double_ret) { - u_int len; - - len = packet->payload_packet_len - (double_ret - packet->payload); - - if(len >= 8 /* 4 chars for \r\n\r\n and at least 4 charts for content guess */) { - double_ret += 4; - -#ifdef NDPI_ENABLE_DEBUG_MESSAGES - int i; - - for(i=0; i<packet->content_line.len; i++) - printf("%c", packet->content_line.ptr[i]); - - printf(" [len: %u] [%02X %02X %02X %02X][%c%c%c%c]", len, - double_ret[0], double_ret[1], double_ret[2], double_ret[3], - double_ret[0], double_ret[1], double_ret[2], double_ret[3] - ); -#endif - - if(ndpi_strnstr((const char *)packet->content_line.ptr, "text/", packet->content_line.len) - || ndpi_strnstr((const char *)packet->content_line.ptr, "/json", packet->content_line.len) - ) { - /* This is supposed to be a hunan-readeable text file */ - - if(ndpi_http_is_print(double_ret[0]) && ndpi_http_is_print(double_ret[1]) - && ndpi_http_is_print(double_ret[2]) && ndpi_http_is_print(double_ret[3])) { - /* OK */ - } else { - /* Looks bad: last resort check if it's gzipped [1F 8B 08 00] */ - - if((double_ret[0] == 0x1F) - && (double_ret[1] == 0x8B) - && (double_ret[2] == 0x08) - && (double_ret[3] == 0x00)) { - /* Looks like compressed data */ - } else - NDPI_SET_BIT(flow->risk, NDPI_HTTP_SUSPICIOUS_CONTENT); - } - } - } - -#ifdef NDPI_ENABLE_DEBUG_MESSAGES - printf("\n"); -#endif - } - } - + ndpi_validate_http_content(ndpi_struct, flow); return; } |