From 9f5e5b90e5f460a9038f5e7ec2d8672049f861c1 Mon Sep 17 00:00:00 2001 From: "Oleg A. Arkhangelsky" Date: Tue, 29 Oct 2019 21:11:31 +0300 Subject: Don't leak memory in live capture mode --- example/ndpiReader.c | 1 + example/reader_util.c | 10 ++++++++-- example/reader_util.h | 1 + 3 files changed, 10 insertions(+), 2 deletions(-) (limited to 'example') diff --git a/example/ndpiReader.c b/example/ndpiReader.c index a5481d342..5efa7bdc8 100644 --- a/example/ndpiReader.c +++ b/example/ndpiReader.c @@ -1784,6 +1784,7 @@ static void node_idle_scan_walker(const void *node, ndpi_VISIT which, int depth, undetected_flows_deleted = 1; ndpi_free_flow_info_half(flow); + ndpi_free_flow_data_analysis(flow); ndpi_thread_info[thread_id].workflow->stats.ndpi_flow_count--; /* adding to a queue (we can't delete it from the tree inline ) */ diff --git a/example/reader_util.c b/example/reader_util.c index 6cb150d87..be150ecf8 100644 --- a/example/reader_util.c +++ b/example/reader_util.c @@ -457,6 +457,14 @@ void ndpi_flow_info_freer(void *node) { ndpi_free_flow_info_half(flow); + ndpi_free_flow_data_analysis(flow); + + ndpi_free(flow); +} + +/* ***************************************************** */ + +void ndpi_free_flow_data_analysis(struct ndpi_flow_info *flow) { if(flow->iat_c_to_s) ndpi_free_data_analysis(flow->iat_c_to_s); if(flow->iat_s_to_c) ndpi_free_data_analysis(flow->iat_s_to_c); @@ -464,8 +472,6 @@ void ndpi_flow_info_freer(void *node) { if(flow->pktlen_s_to_c) ndpi_free_data_analysis(flow->pktlen_s_to_c); if(flow->iat_flow) ndpi_free_data_analysis(flow->iat_flow); - - ndpi_free(flow); } /* ***************************************************** */ diff --git a/example/reader_util.h b/example/reader_util.h index 3374f993f..9165ee1e6 100644 --- a/example/reader_util.h +++ b/example/reader_util.h @@ -299,6 +299,7 @@ int ndpi_workflow_node_cmp(const void *a, const void *b); void process_ndpi_collected_info(struct ndpi_workflow * workflow, struct ndpi_flow_info *flow); u_int32_t ethernet_crc32(const void* data, size_t n_bytes); void ndpi_flow_info_freer(void *node); +void ndpi_free_flow_data_analysis(struct ndpi_flow_info *flow); const char* print_cipher_id(u_int32_t cipher); float ndpi_flow_get_byte_count_entropy(const uint32_t byte_count[256], unsigned int num_bytes); -- cgit v1.2.3 From cfcbfe1e8fe3f98476ca464f36e7efd106637dc3 Mon Sep 17 00:00:00 2001 From: "Oleg A. Arkhangelsky" Date: Tue, 29 Oct 2019 21:20:56 +0300 Subject: Align CSV header with actual row data --- example/ndpiReader.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'example') diff --git a/example/ndpiReader.c b/example/ndpiReader.c index a5481d342..f44781d39 100644 --- a/example/ndpiReader.c +++ b/example/ndpiReader.c @@ -602,7 +602,7 @@ void printCSVHeader() { /* Flow info */ fprintf(csv_fp, "client_info,server_info,"); fprintf(csv_fp, "tls_version,ja3c,tls_client_unsafe,"); - fprintf(csv_fp, "tls_server_info,ja3s,tls_server_unsafe,"); + fprintf(csv_fp, "ja3s,tls_server_unsafe,"); fprintf(csv_fp, "ssh_client_hassh,ssh_server_hassh"); fprintf(csv_fp, "\n"); } -- cgit v1.2.3 From dfd962a8bc09286e426d728d65ae37bf2f122257 Mon Sep 17 00:00:00 2001 From: "Oleg A. Arkhangelsky" Date: Tue, 29 Oct 2019 21:23:42 +0300 Subject: Change type Use double type instead of float when printing time for CSV file. Float type is too small for 64 bit int time so cast corrupts value. --- example/ndpiReader.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'example') diff --git a/example/ndpiReader.c b/example/ndpiReader.c index a5481d342..b8d914d08 100644 --- a/example/ndpiReader.c +++ b/example/ndpiReader.c @@ -1011,7 +1011,7 @@ static void printFlow(u_int16_t id, struct ndpi_flow_info *flow, u_int16_t threa if(csv_fp != NULL) { float data_ratio = ndpi_data_ratio(flow->src2dst_bytes, flow->dst2src_bytes); - float f = (float)flow->first_seen, l = (float)flow->last_seen; + double f = (double)flow->first_seen, l = (double)flow->last_seen; /* PLEASE KEEP IN SYNC WITH printCSVHeader() */ -- cgit v1.2.3 From a3a85106a1eb59bc87cafa06796ea404f450eda9 Mon Sep 17 00:00:00 2001 From: Luca Deri Date: Fri, 1 Nov 2019 23:05:11 +0100 Subject: Implemented SQL Injection and XSS attack detection --- example/ndpiReader.c | 23 +++++- src/include/ndpi_api.h | 2 + src/include/ndpi_typedefs.h | 6 ++ src/lib/ndpi_utils.c | 163 +++++++++++++++++++++++++++++++++++++--- tests/pcap/WebattackSQLinj.pcap | Bin 0 -> 31536 bytes tests/pcap/WebattackXSS.pcap | Bin 0 -> 4871156 bytes 6 files changed, 182 insertions(+), 12 deletions(-) create mode 100644 tests/pcap/WebattackSQLinj.pcap create mode 100644 tests/pcap/WebattackXSS.pcap (limited to 'example') diff --git a/example/ndpiReader.c b/example/ndpiReader.c index 268fea160..f70ebd785 100644 --- a/example/ndpiReader.c +++ b/example/ndpiReader.c @@ -998,6 +998,23 @@ static char* is_unsafe_cipher(ndpi_cipher_weakness c) { /* ********************************** */ +char* printUrlRisk(ndpi_url_risk risk) { + switch(risk) { + case ndpi_url_no_problem: + return(""); + break; + case ndpi_url_possible_xss: + return(" ** XSS **"); + break; + case ndpi_url_possible_sql_injection: + return(" ** SQL Injection **"); + break; + } + + return(""); +} +/* ********************************** */ + /** * @brief Print the flow */ @@ -1143,8 +1160,10 @@ static void printFlow(u_int16_t id, struct ndpi_flow_info *flow, u_int16_t threa } if(flow->http.url[0] != '\0') - fprintf(out, "[URL: %s][StatusCode: %u][ContentType: %s][UserAgent: %s]", - flow->http.url, flow->http.response_status_code, + fprintf(out, "[URL: %s%s][StatusCode: %u][ContentType: %s][UserAgent: %s]", + flow->http.url, + printUrlRisk(ndpi_validate_url(flow->http.url)), + flow->http.response_status_code, flow->http.content_type, flow->http.user_agent); if(flow->ssh_tls.ssl_version != 0) fprintf(out, "[%s]", ndpi_ssl_version2str(flow->ssh_tls.ssl_version, &known_tls)); diff --git a/src/include/ndpi_api.h b/src/include/ndpi_api.h index a1c33b36e..6228a6123 100644 --- a/src/include/ndpi_api.h +++ b/src/include/ndpi_api.h @@ -940,6 +940,8 @@ extern "C" { const char* ndpi_data_ratio2str(float ratio); void ndpi_data_print_window_values(struct ndpi_analyze_struct *s); /* debug */ + + ndpi_url_risk ndpi_validate_url(char *url); #ifdef __cplusplus } #endif diff --git a/src/include/ndpi_typedefs.h b/src/include/ndpi_typedefs.h index 04e439221..057fa2527 100644 --- a/src/include/ndpi_typedefs.h +++ b/src/include/ndpi_typedefs.h @@ -42,6 +42,12 @@ typedef enum { ndpi_l4_proto_tcp_and_udp, } ndpi_l4_proto_info; +typedef enum { + ndpi_url_no_problem = 0, + ndpi_url_possible_xss, + ndpi_url_possible_sql_injection + } ndpi_url_risk; + /* NDPI_VISIT */ typedef enum { ndpi_preorder, diff --git a/src/lib/ndpi_utils.c b/src/lib/ndpi_utils.c index f11f074cd..a8c73e67e 100644 --- a/src/lib/ndpi_utils.c +++ b/src/lib/ndpi_utils.c @@ -759,11 +759,11 @@ void ndpi_user_pwd_payload_copy(u_int8_t *dest, u_int dest_len, u_int offset, const u_int8_t *src, u_int src_len) { u_int i, j=0, k = dest_len-1; - + for(i=offset; (ihost_server_name[0] != '\0') ndpi_serialize_string_string(serializer, "hostname", (const char*)flow->host_server_name); - ndpi_serialize_string_string(serializer, "url", flow->http.url); + ndpi_serialize_string_string(serializer, "url", flow->http.url); ndpi_serialize_string_uint32(serializer, "code", flow->http.response_status_code); ndpi_serialize_string_string(serializer, "content_type", flow->http.content_type); ndpi_serialize_string_string(serializer, "user_agent", flow->http.user_agent); @@ -989,28 +989,28 @@ int ndpi_flow2json(struct ndpi_detection_module_struct *ndpi_struct, ndpi_serialize_string_string(serializer, "password", flow->protos.ftp_imap_pop_smtp.password); ndpi_serialize_end_of_block(serializer); break; - + case NDPI_PROTOCOL_MAIL_POP: ndpi_serialize_start_of_block(serializer, "pop"); ndpi_serialize_string_string(serializer, "user", flow->protos.ftp_imap_pop_smtp.username); ndpi_serialize_string_string(serializer, "password", flow->protos.ftp_imap_pop_smtp.password); ndpi_serialize_end_of_block(serializer); break; - + case NDPI_PROTOCOL_MAIL_SMTP: ndpi_serialize_start_of_block(serializer, "smtp"); ndpi_serialize_string_string(serializer, "user", flow->protos.ftp_imap_pop_smtp.username); ndpi_serialize_string_string(serializer, "password", flow->protos.ftp_imap_pop_smtp.password); ndpi_serialize_end_of_block(serializer); break; - + case NDPI_PROTOCOL_FTP_CONTROL: ndpi_serialize_start_of_block(serializer, "ftp"); ndpi_serialize_string_string(serializer, "user", flow->protos.ftp_imap_pop_smtp.username); ndpi_serialize_string_string(serializer, "password", flow->protos.ftp_imap_pop_smtp.password); ndpi_serialize_end_of_block(serializer); break; - + case NDPI_PROTOCOL_SSH: ndpi_serialize_start_of_block(serializer, "ssh"); ndpi_serialize_string_string(serializer, "client_signature", flow->protos.ssh.client_signature); @@ -1041,7 +1041,7 @@ int ndpi_flow2json(struct ndpi_detection_module_struct *ndpi_struct, ndpi_serialize_string_string(serializer, "issuer", flow->protos.stun_ssl.ssl.server_organization); if(before) { - strftime(notBefore, sizeof(notBefore), "%F %T", before); + strftime(notBefore, sizeof(notBefore), "%F %T", before); ndpi_serialize_string_string(serializer, "notbefore", notBefore); } @@ -1061,7 +1061,7 @@ int ndpi_flow2json(struct ndpi_detection_module_struct *ndpi_struct, ndpi_serialize_string_string(serializer, "fingerprint", buf); } - + ndpi_serialize_end_of_block(serializer); } } @@ -1072,3 +1072,146 @@ int ndpi_flow2json(struct ndpi_detection_module_struct *ndpi_struct, } /* ********************************** */ + +/* + /dv/vulnerabilities/xss_r/?name=%3Cscript%3Econsole.log%28%27JUL2D3WXHEGWRAFJE2PI7OS71Z4Z8RFUHXGNFLUFYVP6M3OL55%27%29%3Bconsole.log%28document.cookie%29%3B%3C%2Fscript%3E + /dv/vulnerabilities/sqli/?id=1%27+and+1%3D1+union+select+null%2C+table_name+from+information_schema.tables%23&Submit=Submit +*/ + +/* https://www.rosettacode.org/wiki/URL_decoding#C */ +static int ishex(int x) { + return(x >= '0' && x <= '9') || (x >= 'a' && x <= 'f') || (x >= 'A' && x <= 'F'); +} + +/* ********************************** */ + +static int ndpi_url_decode(const char *s, char *out) { + char *o; + const char *end = s + strlen(s); + int c; + + for(o = out; s <= end; o++) { + c = *s++; + if(c == '+') c = ' '; + else if(c == '%' && (!ishex(*s++)|| + !ishex(*s++)|| + !sscanf(s - 2, "%2x", &c))) + return(-1); + + if(out) *o = c; + } + + return(o - out); +} + +/* ********************************** */ + +/* #define URL_CHECK_DEBUG 1 */ + +static int find_occurrency(char *str, char *what) { + char *found = strstr(str, what); + u_int len; + +#ifdef URL_CHECK_DEBUG + printf("%s() [%s][%s]\n", __FUNCTION__, str, what); +#endif + + if(!found) return(0); + + len = strlen(what); + + if((found[len] != '\0') && (found[len] != ' ') + && ((found == str) || (found[-1] == ' '))) + return(1); + else + return(find_occurrency(&found[len], what)); +} + +/* ********************************** */ + +static int ndpi_check_tokens(char* query, char* keywords[]) { +#ifdef URL_CHECK_DEBUG + printf("%s() [%s]\n", __FUNCTION__, query); +#endif + + for(int i=0; keywords[i] != NULL; i++) { + if(find_occurrency(query, keywords[i]) > 0) + return(1); + } + + return(0); +} + +/* ********************************** */ + +static int ndpi_is_sql_injection(char* query) { + char* sql_keywords[] = { "select", "from", "where", "any", "all", "join", "inner", "left", "right", "full", + "table", "alter", "create", "delete", "union", "update", "drop", "group", "order", + "limit", "primary", "column", NULL }; + return(ndpi_check_tokens(query, sql_keywords)); +} + +/* ********************************** */ + +static int ndpi_is_xss_injection(char* query) { + char* js_keywords[] = { "