aboutsummaryrefslogtreecommitdiff
path: root/src/lib/protocols/http.c
diff options
context:
space:
mode:
authorLuca Deri <deri@ntop.org>2021-01-06 12:25:32 +0100
committerLuca Deri <deri@ntop.org>2021-01-06 12:25:32 +0100
commitcd21f0d31647444d93536bed2516ddc175e09b25 (patch)
tree078a9279b8177b949c834331758829a90aa33e23 /src/lib/protocols/http.c
parent1b524f553886bdd37aea4a3e04e00d9949f979e7 (diff)
Added check for invalid HTTP content
Diffstat (limited to 'src/lib/protocols/http.c')
-rw-r--r--src/lib/protocols/http.c221
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;
}