aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorToni Uhlig <matzeton@googlemail.com>2021-04-26 18:17:11 +0200
committerToni Uhlig <matzeton@googlemail.com>2021-04-26 18:17:11 +0200
commitcec61ed81c32603e316adc468e243b7ed15cde01 (patch)
tree45f4b1adea7e4ceece56a0ea4d35c7d4f5582471
parent87ad2b58dc4f9355ba6c3a728b8aedb0a0c86516 (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.in5
-rw-r--r--example/reader_util.c10
-rw-r--r--src/include/ndpi_typedefs.h9
-rw-r--r--src/lib/ndpi_utils.c7
-rw-r--r--src/lib/protocols/tls.c96
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 */