diff options
author | Toni Uhlig <matzeton@googlemail.com> | 2021-04-26 18:17:11 +0200 |
---|---|---|
committer | Toni Uhlig <matzeton@googlemail.com> | 2021-04-26 18:17:11 +0200 |
commit | cec61ed81c32603e316adc468e243b7ed15cde01 (patch) | |
tree | 45f4b1adea7e4ceece56a0ea4d35c7d4f5582471 | |
parent | 87ad2b58dc4f9355ba6c3a728b8aedb0a0c86516 (diff) |
Check for common ALPNs and set a flow risk if not known.add/tls-check-common-alpn
* Increased risk bitmask to 64bit (instead of 32bit).
* Removed annoying "Unknown datalink" error message for fuzzers.
Signed-off-by: Toni Uhlig <matzeton@googlemail.com>
-rw-r--r-- | example/Makefile.in | 5 | ||||
-rw-r--r-- | example/reader_util.c | 10 | ||||
-rw-r--r-- | src/include/ndpi_typedefs.h | 9 | ||||
-rw-r--r-- | src/lib/ndpi_utils.c | 7 | ||||
-rw-r--r-- | src/lib/protocols/tls.c | 96 |
5 files changed, 109 insertions, 18 deletions
diff --git a/example/Makefile.in b/example/Makefile.in index ec44acbe3..e70bff36c 100644 --- a/example/Makefile.in +++ b/example/Makefile.in @@ -1,6 +1,7 @@ CC=@CC@ CXX=@CXX@ BUILD_MINGW=@BUILD_MINGW@ +BUILD_FUZZTARGETS=@BUILD_FUZZTARGETS@ SRCHOME=../src CFLAGS=-g -fPIC -DPIC -I$(SRCHOME)/include @PCAP_INC@ @CFLAGS@ LIBNDPI=$(SRCHOME)/lib/libndpi.a @@ -10,6 +11,10 @@ HEADERS=intrusion_detection.h reader_util.h $(SRCHOME)/include/ndpi_api.h \ OBJS=ndpiReader.o reader_util.o intrusion_detection.o PREFIX?=@prefix@ +ifneq ($(BUILD_FUZZTARGETS),) +CFLAGS += -DBUILD_FUZZTARGETS=1 +endif + ifneq ($(BUILD_MINGW),) all: @echo 'Examples disabled due to mingw build.' diff --git a/example/reader_util.c b/example/reader_util.c index b95168e8d..af58d8db5 100644 --- a/example/reader_util.c +++ b/example/reader_util.c @@ -1773,9 +1773,15 @@ struct ndpi_proto ndpi_workflow_process_packet(struct ndpi_workflow * workflow, break; default: - /* We shoudn't be here, because we already checked that this datalink is supported. - Should ndpi_is_datalink_supported() be updated? */ +#ifndef BUILD_FUZZTARGETS + /* + * We shoudn't be here, because we already checked that this datalink is supported. + * Should ndpi_is_datalink_supported() be updated? + * + * NOTE (toni): We get here quite often during fuzzing and it spams consoles and logfiles. ;) + */ printf("Unknown datalink %d\n", datalink_type); +#endif return(nproto); } diff --git a/src/include/ndpi_typedefs.h b/src/include/ndpi_typedefs.h index 54a5caaf6..c65d241ef 100644 --- a/src/include/ndpi_typedefs.h +++ b/src/include/ndpi_typedefs.h @@ -98,13 +98,14 @@ typedef enum { NDPI_RISKY_DOMAIN, NDPI_MALICIOUS_JA3, NDPI_MALICIOUS_SHA1_CERTIFICATE, - NDPI_DESKTOP_OR_FILE_SHARING_SESSION, - + NDPI_DESKTOP_OR_FILE_SHARING_SESSION, /* 30 */ + NDPI_TLS_UNCOMMON_ALPN, + /* Leave this as last member */ - NDPI_MAX_RISK /* must be <= 31 due to (**) */ + NDPI_MAX_RISK /* must be <= 63 due to (**) */ } ndpi_risk_enum; -typedef u_int32_t ndpi_risk; /* (**) */ +typedef u_int64_t ndpi_risk; /* (**) */ /* NDPI_VISIT */ typedef enum { diff --git a/src/lib/ndpi_utils.c b/src/lib/ndpi_utils.c index 262cb2d72..05e7b086b 100644 --- a/src/lib/ndpi_utils.c +++ b/src/lib/ndpi_utils.c @@ -1776,7 +1776,10 @@ const char* ndpi_risk2str(ndpi_risk_enum risk) { case NDPI_DESKTOP_OR_FILE_SHARING_SESSION: return("Desktop/File Sharing Session"); - + + case NDPI_TLS_UNCOMMON_ALPN: + return("Uncommon TLS ALPN"); + default: snprintf(buf, sizeof(buf), "%d", (int)risk); return(buf); @@ -2460,7 +2463,7 @@ int ndpi_hash_add_entry(ndpi_str_hash *h, char *key, u_int8_t key_len, u_int8_t /* ******************************************************************** */ void ndpi_set_risk(struct ndpi_flow_struct *flow, ndpi_risk_enum r) { - u_int32_t v = 1 << r; + ndpi_risk v = 1ull << r; // NDPI_SET_BIT(flow->risk, (u_int32_t)r); flow->risk |= v; diff --git a/src/lib/protocols/tls.c b/src/lib/protocols/tls.c index 035142f00..d970980ab 100644 --- a/src/lib/protocols/tls.c +++ b/src/lib/protocols/tls.c @@ -1010,6 +1010,73 @@ static void tlsInitExtraPacketProcessing(struct ndpi_detection_module_struct *nd /* **************************************** */ +static void tlsCheckUncommonALPN(struct ndpi_flow_struct *flow) +{ + /* see: https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml */ + static char const * const common_alpns[] = { + "http/0.9", "http/1.0", "http/1.1", + "spdy/1", "spdy/2", "spdy/3", "spdy/3.1", + "stun.turn", "stun.nat-discovery", + "h2", "h2c", "h2-16", "h2-15", "h2-14", + "webrtc", "c-webrtc", + "ftp", "imap", "pop3", "managesieve", "coap", + "xmpp-client", "xmpp-server", + "acme-tls/1", + "mqtt", "dot", "ntske/1", "sunrpc", + "h3", + "smb", + "irc", + + /* QUIC ALPNs */ + "h3-T051", "h3-T050", + "h3-32", "h3-30", "h3-29", "h3-28", "h3-27", "h3-24", "h3-22", + "hq-30", "hq-29", "hq-28", "hq-27", + "h3-fb-05", "h1q-fb", + "doq-i00" + }; + + /* + * If the ALPN list increases in size, iterating over all items for every incoming ALPN may + * have a performance impact. A hash map could solve this issue. + */ + + char * alpn_start = flow->protos.tls_quic_stun.tls_quic.alpn; + char * comma_or_nul = alpn_start; + do { + comma_or_nul = strchr(comma_or_nul, ','); + if (comma_or_nul == NULL) + { + comma_or_nul = alpn_start + strlen(alpn_start); + } + + int alpn_found = 0; + int alpn_len = comma_or_nul - alpn_start; + char const * const alpn = alpn_start; + for (size_t i = 0; i < sizeof(common_alpns)/sizeof(common_alpns[0]); ++i) + { + if (strlen(common_alpns[i]) == alpn_len && + strncmp(alpn, common_alpns[i], alpn_len) == 0) + { + alpn_found = 1; + break; + } + } + + if (alpn_found == 0) + { +#ifdef DEBUG_TLS + printf("TLS uncommon ALPN found: %.*s\n", alpn_len, alpn); +#endif + ndpi_set_risk(flow, NDPI_TLS_UNCOMMON_ALPN); + break; + } + + alpn_start = comma_or_nul + 1; + } while (*(comma_or_nul++) != '\0'); +} + +/* **************************************** */ + static void ndpi_int_tls_add_connection(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow, u_int32_t protocol) { #if DEBUG_TLS @@ -1179,19 +1246,25 @@ int processClientServerHello(struct ndpi_detection_module_struct *ndpi_struct, #endif if((alpn_str_len+alpn_len+1) < (sizeof(alpn_str)-1)) { - if(alpn_str_len > 0) { - alpn_str[alpn_str_len] = ','; - alpn_str_len++; - } + if(alpn_str_len > 0) { + alpn_str[alpn_str_len] = ','; + alpn_str_len++; + } - for(alpn_i=0; alpn_i<alpn_len; alpn_i++) - alpn_str[alpn_str_len+alpn_i] = packet->payload[s_offset+alpn_i]; + for(alpn_i=0; alpn_i<alpn_len; alpn_i++) + { + alpn_str[alpn_str_len+alpn_i] = packet->payload[s_offset+alpn_i]; + } - s_offset += alpn_len, alpn_str_len += alpn_len;; - } else - break; - } else + s_offset += alpn_len, alpn_str_len += alpn_len;; + } else { + ndpi_set_risk(flow, NDPI_TLS_UNCOMMON_ALPN); + break; + } + } else { + ndpi_set_risk(flow, NDPI_TLS_UNCOMMON_ALPN); break; + } } /* while */ alpn_str[alpn_str_len] = '\0'; @@ -1202,6 +1275,9 @@ int processClientServerHello(struct ndpi_detection_module_struct *ndpi_struct, if(flow->protos.tls_quic_stun.tls_quic.alpn == NULL) flow->protos.tls_quic_stun.tls_quic.alpn = ndpi_strdup(alpn_str); + if(flow->protos.tls_quic_stun.tls_quic.alpn != NULL) + tlsCheckUncommonALPN(flow); + snprintf(ja3.server.alpn, sizeof(ja3.server.alpn), "%s", alpn_str); /* Replace , with - as in JA3 */ |