aboutsummaryrefslogtreecommitdiff
path: root/src/lib/protocols/http.c
diff options
context:
space:
mode:
authorLuca Deri <deri@ntop.org>2022-05-30 00:31:52 +0200
committerLuca Deri <deri@ntop.org>2022-05-30 00:32:32 +0200
commitf25deeccb1ccbebd6346271828762fdd8326c32b (patch)
tree677c846f19b9b1468e6ec62637e77ae354fe0a24 /src/lib/protocols/http.c
parenta9d7cc4841ea098074b3dc0b42b7b6e73d4d8cd9 (diff)
Added RiskInfo string
Diffstat (limited to 'src/lib/protocols/http.c')
-rw-r--r--src/lib/protocols/http.c172
1 files changed, 119 insertions, 53 deletions
diff --git a/src/lib/protocols/http.c b/src/lib/protocols/http.c
index 257585512..4788a4e52 100644
--- a/src/lib/protocols/http.c
+++ b/src/lib/protocols/http.c
@@ -52,14 +52,15 @@ static void ndpi_search_http_tcp(struct ndpi_detection_module_struct *ndpi_struc
/* *********************************************** */
static void ndpi_set_binary_application_transfer(struct ndpi_detection_module_struct *ndpi_struct,
- struct ndpi_flow_struct *flow) {
+ struct ndpi_flow_struct *flow,
+ char *msg) {
/*
Check known exceptions
*/
if(ndpi_ends_with((char*)flow->host_server_name, ".windowsupdate.com"))
;
else
- ndpi_set_risk(ndpi_struct, flow, NDPI_BINARY_APPLICATION_TRANSFER);
+ ndpi_set_risk(ndpi_struct, flow, NDPI_BINARY_APPLICATION_TRANSFER, msg);
}
/* *********************************************** */
@@ -67,29 +68,30 @@ static void ndpi_set_binary_application_transfer(struct ndpi_detection_module_st
static void ndpi_analyze_content_signature(struct ndpi_detection_module_struct *ndpi_struct,
struct ndpi_flow_struct *flow) {
u_int8_t set_risk = 0;
+ const char *msg = NULL;
if((flow->initial_binary_bytes_len >= 2) && (flow->initial_binary_bytes[0] == 0x4D) && (flow->initial_binary_bytes[1] == 0x5A))
- set_risk = 1; /* Win executable */
+ set_risk = 1, msg = "Found Windows Exe"; /* 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'))
- set_risk = 1; /* Linux executable */
+ set_risk = 1, msg = "Found Linux Exe"; /* 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))
- set_risk = 1; /* Linux executable */
+ set_risk = 1, msg = "Found Linux Exe"; /* Linux executable */
else if((flow->initial_binary_bytes_len >= 3)
&& (flow->initial_binary_bytes[0] == '#')
&& (flow->initial_binary_bytes[1] == '!')
&& (flow->initial_binary_bytes[2] == '/'))
- set_risk = 1; /* Unix script (e.g. #!/bin/sh) */
+ set_risk = 1, msg = "Found Unix Script"; /* Unix script (e.g. #!/bin/sh) */
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)
- set_risk = 1; /* Dalvik Executable (Android) */
+ set_risk = 1, msg = "Found Android Exe"; /* Dalvik Executable (Android) */
}
if(set_risk)
- ndpi_set_binary_application_transfer(ndpi_struct, flow);
+ ndpi_set_binary_application_transfer(ndpi_struct, flow, (char*)msg);
}
/* *********************************************** */
@@ -148,8 +150,13 @@ static void ndpi_http_check_human_redeable_content(struct ndpi_detection_module_
&& (content[2] == 0x08)
&& (content[3] == 0x00)) {
/* Looks like compressed data */
- } else
- ndpi_set_risk(ndpi_struct, flow, NDPI_HTTP_SUSPICIOUS_CONTENT);
+ } else {
+ char str[32];
+
+ snprintf(str, sizeof(str), "Susp content %02X%02X%02X%02X",
+ content[0], content[1], content[2], content[3]);
+ ndpi_set_risk(ndpi_struct, flow, NDPI_HTTP_SUSPICIOUS_CONTENT, str);
+ }
}
}
}
@@ -197,7 +204,7 @@ static void ndpi_validate_http_content(struct ndpi_detection_module_struct *ndpi
https://corelight.com/blog/detecting-log4j-exploits-via-zeek-when-java-downloads-java
*/
- ndpi_set_risk(ndpi_struct, flow, NDPI_POSSIBLE_EXPLOIT);
+ ndpi_set_risk(ndpi_struct, flow, NDPI_POSSIBLE_EXPLOIT, "Suspicious Log4J");
}
}
@@ -258,8 +265,11 @@ static ndpi_protocol_category_t ndpi_http_check_content(struct ndpi_detection_mo
for(i = 0; cmp_mimes[i] != NULL; i++) {
if(strncasecmp(app, cmp_mimes[i], app_len_avail) == 0) {
+ char str[64];
+
+ snprintf(str, sizeof(str), "Found mime exe %s", cmp_mimes[i]);
flow->guessed_category = flow->category = NDPI_PROTOCOL_CATEGORY_DOWNLOAD_FT;
- ndpi_set_binary_application_transfer(ndpi_struct, flow);
+ ndpi_set_binary_application_transfer(ndpi_struct, flow, str);
NDPI_LOG_INFO(ndpi_struct, "Found executable HTTP transfer");
return(flow->category);
}
@@ -287,8 +297,11 @@ static ndpi_protocol_category_t ndpi_http_check_content(struct ndpi_detection_mo
/* Use memcmp in case content-disposition contains binary data */
if(memcmp(&packet->content_disposition_line.ptr[attachment_len],
binary_file_ext[i], ATTACHMENT_LEN) == 0) {
+ char str[64];
+
+ snprintf(str, sizeof(str), "Found file extn %s", binary_file_ext[i]);
flow->guessed_category = flow->category = NDPI_PROTOCOL_CATEGORY_DOWNLOAD_FT;
- ndpi_set_binary_application_transfer(ndpi_struct, flow);
+ ndpi_set_binary_application_transfer(ndpi_struct, flow, str);
NDPI_LOG_INFO(ndpi_struct, "found executable HTTP transfer");
return(flow->category);
}
@@ -414,7 +427,7 @@ static void ndpi_check_user_agent(struct ndpi_detection_module_struct *ndpi_stru
struct ndpi_flow_struct *flow,
char const *ua, size_t ua_len) {
char *double_slash;
-
+
if((!ua) || (ua[0] == '\0'))
return;
@@ -438,32 +451,42 @@ static void ndpi_check_user_agent(struct ndpi_detection_module_struct *ndpi_stru
}
}
- if (i == ua_len)
- {
+ if (i == ua_len) {
float upper_case_ratio = (float)upper_case_count / (float)ua_len;
- if (upper_case_ratio >= 0.2f)
- {
- ndpi_set_risk(ndpi_struct, flow, NDPI_HTTP_SUSPICIOUS_USER_AGENT);
+
+ if (upper_case_ratio >= 0.2f) {
+ char str[64];
+
+ snprintf(str, sizeof(str), "UA %s", ua);
+ ndpi_set_risk(ndpi_struct, flow, NDPI_HTTP_SUSPICIOUS_USER_AGENT, str);
}
}
}
if((!strncmp(ua, "<?", 2))
|| strchr(ua, '$')
- )
- ndpi_set_risk(ndpi_struct, flow, NDPI_HTTP_SUSPICIOUS_USER_AGENT);
+ ) {
+ char str[64];
+
+ snprintf(str, sizeof(str), "UA %s", ua);
+ ndpi_set_risk(ndpi_struct, flow, NDPI_HTTP_SUSPICIOUS_USER_AGENT, str);
+ }
if((double_slash = strstr(ua, "://")) != NULL) {
if(double_slash != ua) /* We're not at the beginning of the user agent */{
if((double_slash[-1] != 'p') /* http:// */
- && (double_slash[-1] != 's') /* https:// */)
- ndpi_set_risk(ndpi_struct, flow, NDPI_HTTP_SUSPICIOUS_USER_AGENT);
+ && (double_slash[-1] != 's') /* https:// */) {
+ char str[64];
+
+ snprintf(str, sizeof(str), "UA %s", ua);
+ ndpi_set_risk(ndpi_struct, flow, NDPI_HTTP_SUSPICIOUS_USER_AGENT, str);
+ }
}
}
-
+
/* no else */
if(!strncmp(ua, "jndi:ldap://", 12)) /* Log4J */ {
- ndpi_set_risk(ndpi_struct, flow, NDPI_POSSIBLE_EXPLOIT);
+ ndpi_set_risk(ndpi_struct, flow, NDPI_POSSIBLE_EXPLOIT, "Suspicious Log4J");
} else if(
(ua_len < 4) /* Too short */
|| (ua_len > 256) /* Too long */
@@ -471,7 +494,7 @@ static void ndpi_check_user_agent(struct ndpi_detection_module_struct *ndpi_stru
|| strchr(ua, '{')
|| strchr(ua, '}')
) {
- ndpi_set_risk(ndpi_struct, flow, NDPI_HTTP_SUSPICIOUS_USER_AGENT);
+ ndpi_set_risk(ndpi_struct, flow, NDPI_HTTP_SUSPICIOUS_USER_AGENT, "Suspicious Log4J");
}
/*
@@ -484,7 +507,11 @@ static void ndpi_check_user_agent(struct ndpi_detection_module_struct *ndpi_stru
|| ndpi_strncasestr(ua, "Crawler", ua_len)
|| ndpi_strncasestr(ua, "Bot", ua_len) /* bot/robot */
) {
- ndpi_set_risk(ndpi_struct, flow, NDPI_HTTP_CRAWLER_BOT);
+ char str[64];
+
+ snprintf(str, sizeof(str), "UA %s", ua);
+
+ ndpi_set_risk(ndpi_struct, flow, NDPI_HTTP_CRAWLER_BOT, str);
}
}
@@ -579,8 +606,12 @@ static void ndpi_check_numeric_ip(struct ndpi_detection_module_struct *ndpi_stru
double_dot[0] = '\0';
ip_addr.s_addr = inet_addr(buf);
- if(strcmp(inet_ntoa(ip_addr), buf) == 0)
- ndpi_set_risk(ndpi_struct, flow, NDPI_HTTP_NUMERIC_IP_HOST);
+ if(strcmp(inet_ntoa(ip_addr), buf) == 0) {
+ char str[64];
+
+ snprintf(str, sizeof(str), "Found host %s", buf);
+ ndpi_set_risk(ndpi_struct, flow, NDPI_HTTP_NUMERIC_IP_HOST, str);
+ }
}
/* ************************************************************* */
@@ -651,7 +682,7 @@ static void check_content_type_and_change_protocol(struct ndpi_detection_module_
|| (flow->http.method == NDPI_HTTP_METHOD_RPC_OUT_DATA)) {
ndpi_set_detected_protocol(ndpi_struct, flow, NDPI_PROTOCOL_RPC, flow->detected_protocol_stack[0], NDPI_CONFIDENCE_DPI);
check_content_type_and_change_protocol(ndpi_struct, flow);
- }
+ }
}
if(packet->server_line.ptr != NULL && (packet->server_line.len > 7)) {
@@ -681,16 +712,19 @@ static void check_content_type_and_change_protocol(struct ndpi_detection_module_
if(strlen(flow->host_server_name) > 0) {
ndpi_check_dga_name(ndpi_struct, flow, flow->host_server_name, 1);
-
+
if(ndpi_is_valid_hostname(flow->host_server_name,
strlen(flow->host_server_name)) == 0) {
- ndpi_set_risk(ndpi_struct, flow, NDPI_INVALID_CHARACTERS);
-
+ char str[64];
+
+ snprintf(str, sizeof(str), "Invalid host %s", flow->host_server_name);
+ ndpi_set_risk(ndpi_struct, flow, NDPI_INVALID_CHARACTERS, str);
+
/* This looks like an attack */
- ndpi_set_risk(ndpi_struct, flow, NDPI_POSSIBLE_EXPLOIT);
+ ndpi_set_risk(ndpi_struct, flow, NDPI_POSSIBLE_EXPLOIT, NULL);
}
}
-
+
if(packet->forwarded_line.ptr) {
if(flow->http.nat_ip == NULL) {
len = packet->forwarded_line.len;
@@ -766,7 +800,8 @@ static void check_content_type_and_change_protocol(struct ndpi_detection_module_
"Basic", packet->authorization_line.len)
|| ndpi_strncasestr((const char*)packet->authorization_line.ptr,
"Digest", packet->authorization_line.len)) {
- ndpi_set_risk(ndpi_struct, flow, NDPI_CLEAR_TEXT_CREDENTIALS);
+ ndpi_set_risk(ndpi_struct, flow, NDPI_CLEAR_TEXT_CREDENTIALS,
+ "Found credentials in HTTP Auth Line");
}
}
@@ -942,55 +977,82 @@ static void ndpi_check_http_header(struct ndpi_detection_module_struct *ndpi_str
switch(packet->line[i].ptr[0]){
case 'A':
if(is_a_suspicious_header(suspicious_http_header_keys_A, packet->line[i])) {
- ndpi_set_risk(ndpi_struct, flow, NDPI_HTTP_SUSPICIOUS_HEADER);
+ char str[64];
+
+ snprintf(str, sizeof(str), "Found %s", packet->line[i].ptr);
+ ndpi_set_risk(ndpi_struct, flow, NDPI_HTTP_SUSPICIOUS_HEADER, str);
return;
}
break;
case 'C':
if(is_a_suspicious_header(suspicious_http_header_keys_C, packet->line[i])) {
- ndpi_set_risk(ndpi_struct, flow, NDPI_HTTP_SUSPICIOUS_HEADER);
+ char str[64];
+
+ snprintf(str, sizeof(str), "Found %s", packet->line[i].ptr);
+ ndpi_set_risk(ndpi_struct, flow, NDPI_HTTP_SUSPICIOUS_HEADER, str);
return;
}
break;
case 'M':
if(is_a_suspicious_header(suspicious_http_header_keys_M, packet->line[i])) {
- ndpi_set_risk(ndpi_struct, flow, NDPI_HTTP_SUSPICIOUS_HEADER);
+ char str[64];
+
+ snprintf(str, sizeof(str), "Found %s", packet->line[i].ptr);
+ ndpi_set_risk(ndpi_struct, flow, NDPI_HTTP_SUSPICIOUS_HEADER, str);
return;
}
break;
case 'O':
if(is_a_suspicious_header(suspicious_http_header_keys_O, packet->line[i])) {
- ndpi_set_risk(ndpi_struct, flow, NDPI_HTTP_SUSPICIOUS_HEADER);
+ char str[64];
+
+ snprintf(str, sizeof(str), "Found %s", packet->line[i].ptr);
+ ndpi_set_risk(ndpi_struct, flow, NDPI_HTTP_SUSPICIOUS_HEADER, str);
return;
}
break;
case 'R':
if(is_a_suspicious_header(suspicious_http_header_keys_R, packet->line[i])) {
- ndpi_set_risk(ndpi_struct, flow, NDPI_HTTP_SUSPICIOUS_HEADER);
+ char str[64];
+
+ snprintf(str, sizeof(str), "Found %s", packet->line[i].ptr);
+ ndpi_set_risk(ndpi_struct, flow, NDPI_HTTP_SUSPICIOUS_HEADER, str);
return;
}
break;
case 'S':
if(is_a_suspicious_header(suspicious_http_header_keys_S, packet->line[i])) {
- ndpi_set_risk(ndpi_struct, flow, NDPI_HTTP_SUSPICIOUS_HEADER);
+ char str[64];
+
+ snprintf(str, sizeof(str), "Found %s", packet->line[i].ptr);
+ ndpi_set_risk(ndpi_struct, flow, NDPI_HTTP_SUSPICIOUS_HEADER, str);
return;
}
break;
case 'T':
if(is_a_suspicious_header(suspicious_http_header_keys_T, packet->line[i])) {
- ndpi_set_risk(ndpi_struct, flow, NDPI_HTTP_SUSPICIOUS_HEADER);
+ char str[64];
+
+ snprintf(str, sizeof(str), "Found %s", packet->line[i].ptr);
+ ndpi_set_risk(ndpi_struct, flow, NDPI_HTTP_SUSPICIOUS_HEADER, str);
return;
}
break;
case 'U':
if(is_a_suspicious_header(suspicious_http_header_keys_U, packet->line[i])) {
- ndpi_set_risk(ndpi_struct, flow, NDPI_HTTP_SUSPICIOUS_HEADER);
+ char str[64];
+
+ snprintf(str, sizeof(str), "Found %s", packet->line[i].ptr);
+ ndpi_set_risk(ndpi_struct, flow, NDPI_HTTP_SUSPICIOUS_HEADER, str);
return;
}
break;
case 'X':
if(is_a_suspicious_header(suspicious_http_header_keys_X, packet->line[i])) {
- ndpi_set_risk(ndpi_struct, flow, NDPI_HTTP_SUSPICIOUS_HEADER);
+ char str[64];
+
+ snprintf(str, sizeof(str), "Found %s", packet->line[i].ptr);
+ ndpi_set_risk(ndpi_struct, flow, NDPI_HTTP_SUSPICIOUS_HEADER, str);
return;
}
@@ -998,6 +1060,7 @@ static void ndpi_check_http_header(struct ndpi_detection_module_struct *ndpi_str
}
}
}
+
/*************************************************************************************************/
static void ndpi_check_http_tcp(struct ndpi_detection_module_struct *ndpi_struct,
@@ -1036,25 +1099,28 @@ static void ndpi_check_http_tcp(struct ndpi_detection_module_struct *ndpi_struct
buf[3] = '\0';
flow->http.response_status_code = atoi(buf);
-
+
/* https://en.wikipedia.org/wiki/List_of_HTTP_status_codes */
if((flow->http.response_status_code < 100) || (flow->http.response_status_code > 509))
flow->http.response_status_code = 0; /* Out of range */
else if(flow->http.response_status_code >= 400) {
+ char ec[48];
+
if(flow->http.url != NULL) {
/* Let's check for Wordpress */
char *slash = strchr(flow->http.url, '/');
-
+
if(
((flow->http.method == NDPI_HTTP_METHOD_POST) && (strncmp(slash, "/wp-admin/", 10) == 0))
- || ((flow->http.method == NDPI_HTTP_METHOD_GET) && (strncmp(slash, "/wp-content/uploads/", 20) == 0))
+ || ((flow->http.method == NDPI_HTTP_METHOD_GET) && (strncmp(slash, "/wp-content/uploads/", 20) == 0))
) {
/* Example of popular exploits https://www.wordfence.com/blog/2022/05/millions-of-attacks-target-tatsu-builder-plugin/ */
- ndpi_set_risk(ndpi_struct, flow, NDPI_POSSIBLE_EXPLOIT);
+ ndpi_set_risk(ndpi_struct, flow, NDPI_POSSIBLE_EXPLOIT, "Possible Wordpress Exploit");
}
}
-
- ndpi_set_risk(ndpi_struct, flow, NDPI_ERROR_CODE_DETECTED);
+
+ snprintf(ec, sizeof(ec), "HTTP Error Code %u", flow->http.response_status_code);
+ ndpi_set_risk(ndpi_struct, flow, NDPI_ERROR_CODE_DETECTED, ec);
}
}
@@ -1158,7 +1224,7 @@ static void ndpi_check_http_tcp(struct ndpi_detection_module_struct *ndpi_struct
packet->http_method.ptr = packet->line[0].ptr;
packet->http_method.len = filename_start - 1;
-
+
/* Encode the direction of the packet in the stage, so we will know when we need to look for the response packet. */
flow->l4.tcp.http_stage = packet->packet_direction + 1; // packet_direction 0: stage 1, packet_direction 1: stage 2
return;
@@ -1341,7 +1407,7 @@ static void ndpi_search_http_tcp(struct ndpi_detection_module_struct *ndpi_struc
ndpi_http_method ndpi_get_http_method(struct ndpi_detection_module_struct *ndpi_struct,
struct ndpi_flow_struct *flow) {
if(!flow) {
- ndpi_set_risk(ndpi_struct, flow, NDPI_MALFORMED_PACKET);
+ ndpi_set_risk(ndpi_struct, flow, NDPI_MALFORMED_PACKET, (char*)"Unknown HTTP Method");
return(NDPI_HTTP_METHOD_UNKNOWN);
} else
return(flow->http.method);