Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/include/ndpi_private.h
Original file line number Diff line number Diff line change
Expand Up @@ -488,6 +488,7 @@ struct ndpi_detection_module_struct {
u_int16_t max_payload_track_len;

ndpi_str_hash *public_domain_suffixes, *ja4_custom_protos, *ndpifp_custom_protos;
ndpi_tls_cert_hash_match_dynamic *dynamic_tls_cert_hash_list;
struct ndpi_address_cache *address_cache;
struct {
ndpi_filter *cache, *cache_shadow;
Expand Down
6 changes: 6 additions & 0 deletions src/include/ndpi_typedefs.h
Original file line number Diff line number Diff line change
Expand Up @@ -1578,6 +1578,12 @@ typedef struct {
char alpn[MAX_JA_STRLEN];
} ndpi_tls_server_info;

typedef struct ndpi_tls_cert_hash_match_dynamic {
char *cert_hash;
u_int16_t protocol_id;
struct ndpi_tls_cert_hash_match_dynamic *next;
} ndpi_tls_cert_hash_match_dynamic;

struct ndpi_flow_struct {
u_int16_t detected_protocol_stack[NDPI_PROTOCOL_SIZE];
struct ndpi_proto_stack protocol_stack;
Expand Down
57 changes: 56 additions & 1 deletion src/lib/ndpi_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -3682,7 +3682,34 @@ static int ndpi_add_ndpifp_subprotocol(struct ndpi_detection_module_struct *ndpi

return(ndpi_hash_add_entry(&ndpi_str->ndpifp_custom_protos, ndpifp, ndpifp_len, protocol_id, NULL));
}
static int ndpi_add_tls_cert_hash_subprotocol(struct ndpi_detection_module_struct *ndpi_str,
char *cert_hash,
u_int16_t protocol_id) {
ndpi_tls_cert_hash_match_dynamic *new_rule;

if(!cert_hash || cert_hash[0] == '\0') {
NDPI_LOG_ERR(ndpi_str, "Empty TLS cert hash\n");
return(-1);
}

new_rule = (ndpi_tls_cert_hash_match_dynamic *)ndpi_malloc(sizeof(*new_rule));
if(new_rule == NULL) {
NDPI_LOG_ERR(ndpi_str, "Memory allocation failure for TLS cert hash\n");
return(-2);
}

new_rule->cert_hash = ndpi_strdup(cert_hash);
if(new_rule->cert_hash == NULL) {
ndpi_free(new_rule);
NDPI_LOG_ERR(ndpi_str, "Memory allocation failure for TLS cert hash\n");
return(-2);
}
new_rule->protocol_id = protocol_id;
new_rule->next = ndpi_str->dynamic_tls_cert_hash_list;
ndpi_str->dynamic_tls_cert_hash_list = new_rule;

return(0);
}
/* ******************************************* */

static int ndpi_add_http_url_subprotocol(struct ndpi_detection_module_struct *ndpi_str,
Expand Down Expand Up @@ -4198,6 +4225,7 @@ struct ndpi_detection_module_struct *ndpi_init_detection_module(struct ndpi_glob
ndpi_str->malicious_sha1_hashmap = NULL; /* Initialized on demand */
ndpi_str->ja4_custom_protos = NULL; /* Initialized on demand */
ndpi_str->ndpifp_custom_protos = NULL; /* Initialized on demand */
ndpi_str->dynamic_tls_cert_hash_list = NULL; /* Initialized on demand */
ndpi_str->http_url_hashmap = NULL; /* Initialized on demand */

ndpi_str->trusted_issuer_dn = NULL; /* Initialized on demand */
Expand Down Expand Up @@ -5257,6 +5285,17 @@ void ndpi_exit_detection_module(struct ndpi_detection_module_struct *ndpi_str) {
if(ndpi_str->ndpifp_custom_protos)
ndpi_hash_free(&ndpi_str->ndpifp_custom_protos);

if(ndpi_str->dynamic_tls_cert_hash_list) {
ndpi_tls_cert_hash_match_dynamic *rule = ndpi_str->dynamic_tls_cert_hash_list;

while(rule != NULL) {
ndpi_tls_cert_hash_match_dynamic *next = rule->next;
if(rule->cert_hash)
ndpi_free(rule->cert_hash);
ndpi_free(rule);
rule = next;
}
}
if(ndpi_str->http_url_hashmap)
ndpi_hash_free(&ndpi_str->http_url_hashmap);

Expand Down Expand Up @@ -5727,7 +5766,7 @@ static int ndpi_handle_rule(struct ndpi_detection_module_struct *ndpi_str,
while((elem = strsep(&rule, ",")) != NULL) {
char *attr = elem, *value = NULL;
ndpi_port_range range;
int is_tcp = 0, is_udp = 0, is_ip = 0, is_ja4 = 0, is_ndpifp = 0, is_httpurl = 0;;
int is_tcp = 0, is_udp = 0, is_ip = 0, is_ja4 = 0, is_ndpifp = 0, is_httpurl = 0, is_tls_cert_hash = 0;;
u_int8_t is_ipv6_ip = 0;

if(strncmp(attr, "tcp:", 4) == 0)
Expand Down Expand Up @@ -5790,7 +5829,17 @@ static int ndpi_handle_rule(struct ndpi_detection_module_struct *ndpi_str,
is_ndpifp = 1, value = &attr[7];
} else if(strncmp(attr, "url:", 4) == 0) {
is_httpurl = 1, value = &attr[4];
} else if(strncmp(attr, "tls_cert_hash:", 14) == 0) {
is_tls_cert_hash = 1, value = &attr[14];
if (value[0] == '"') {
value++;
if (value[0] != '\0') {
size_t len=strlen(value);
if(len > 0 && value[len-1] == '"')
value[len-1] = '\0'; /* remove trailing " */
}
}
}

if(is_tcp || is_udp) {
u_int p_low, p_high;
Expand Down Expand Up @@ -5841,6 +5890,11 @@ static int ndpi_handle_rule(struct ndpi_detection_module_struct *ndpi_str,

if(rc != 0)
return(rc);
} else if(is_tls_cert_hash) {
int rc = ndpi_add_tls_cert_hash_subprotocol(ndpi_str, value, subprotocol_id);

if(rc != 0)
return(rc);
} else {
int rc = ndpi_add_host_url_subprotocol(ndpi_str, value, subprotocol_id, category, breed, 0);

Expand All @@ -5851,6 +5905,7 @@ static int ndpi_handle_rule(struct ndpi_detection_module_struct *ndpi_str,

return(ret);
}


/* ******************************************************************** */

Expand Down
39 changes: 38 additions & 1 deletion src/lib/protocols/tls.c
Original file line number Diff line number Diff line change
Expand Up @@ -1095,6 +1095,8 @@ void processCertificateElements(struct ndpi_detection_module_struct *ndpi_struct
}
}
}


}

if(flow->protos.tls_quic.subjectDN && flow->protos.tls_quic.issuerDN
Expand Down Expand Up @@ -1285,10 +1287,45 @@ int processCertificate(struct ndpi_detection_module_struct *ndpi_struct,
if(rc1 == 0)
ndpi_set_risk(ndpi_struct, flow, NDPI_MALICIOUS_SHA1_CERTIFICATE, sha1_str);
}

if(flow->detected_protocol_stack[1] == NDPI_PROTOCOL_UNKNOWN &&
ndpi_struct->dynamic_tls_cert_hash_list != NULL) {

ndpi_tls_cert_hash_match_dynamic *rule = ndpi_struct->dynamic_tls_cert_hash_list;

while(rule != NULL) {
char rule_hash_no_colon[256];
int j = 0;
for(int i = 0; rule->cert_hash[i] != '\0' && j < (int)sizeof(rule_hash_no_colon)-1; i++) {
if(rule->cert_hash[i] != ':') {
rule_hash_no_colon[j++] = toupper((unsigned char)rule->cert_hash[i]);
}
}
rule_hash_no_colon[j] = '\0';


if(strcasecmp(sha1_str, rule_hash_no_colon) == 0) {
/* Hash match found */
ndpi_master_app_protocol proto;

ndpi_set_detected_protocol(ndpi_struct, flow, rule->protocol_id,
ndpi_get_master_proto(ndpi_struct, flow),
NDPI_CONFIDENCE_DPI);
proto.master_protocol = ndpi_get_master_proto(ndpi_struct, flow);
proto.app_protocol = rule->protocol_id;
flow->category = get_proto_category(ndpi_struct, proto);
flow->breed = get_proto_breed(ndpi_struct, proto);
ndpi_check_subprotocol_risk(ndpi_struct, flow, rule->protocol_id);
ndpi_unset_risk(ndpi_struct, flow, NDPI_NUMERIC_IP_HOST);
break;
}
rule = rule->next;
}
}
}

processCertificateElements(ndpi_struct, flow, certificates_offset, certificate_len);
}
}

certificates_offset += certificate_len;
}
Expand Down
1 change: 1 addition & 0 deletions test_protos_hash.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
nDPI_TestApp@tls_cert_hash:"da:39:a3:ee:5e:6b:4b:0d:32:55:bf:ef:95:60:18:90:af:d8:07:09"
24 changes: 24 additions & 0 deletions tls_test_cert/test_cert.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
-----BEGIN CERTIFICATE-----
MIIEAzCCAuugAwIBAgIUGpLRiLOOApm+pLR7eUZBQmXwd/AwDQYJKoZIhvcNAQEL
BQAwgZAxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQH
DA1TYW4gRnJhbmNpc2NvMR8wHQYDVQQKDBZuRFBJX1Rlc3RfT3JnYW5pemF0aW9u
MRAwDgYDVQQLDAdUZXN0aW5nMSEwHwYDVQQDDBhuRFBJX1Rlc3RBcHBfQ2VydGlm
aWNhdGUwHhcNMjYwNzI1MTAwNjQ2WhcNMjcwNzI1MTAwNjQ2WjCBkDELMAkGA1UE
BhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDVNhbiBGcmFuY2lz
Y28xHzAdBgNVBAoMFm5EUElfVGVzdF9Pcmdhbml6YXRpb24xEDAOBgNVBAsMB1Rl
c3RpbmcxITAfBgNVBAMMGG5EUElfVGVzdEFwcF9DZXJ0aWZpY2F0ZTCCASIwDQYJ
KoZIhvcNAQEBBQADggEPADCCAQoCggEBANbsezILR6MkDuSWPRKlNhGfy0ItXbw7
9S1F9NFevvckTwvyK7CtTNh4SeukgFqTnwIe5t0WMKg8I6DVUjSAP+BctMk7ZC0q
yfTSijMQ4DPjAFmj9DztZpMTwP/YfKaNIO4qTDknZ7LaOBVaIjdsL2++W9wFo6hq
zMAhfjcfvLp70oWGPz7i3dhvJ925ymbrrDXY2mpNmEhuAB5MtBIL6pxP389ygWyo
8QrnTzhErt3JDSq+N73bNeq1t/hwV7Ufg+SBNtURoT6vLpOgwbAi3w3zk3mgPoxO
iB6YoNhpi4Sqh0Dzbvf2UFVGClfzKsB40NsmGrjFs7XgFIoqIAv8H2sCAwEAAaNT
MFEwHQYDVR0OBBYEFOqbaHUFL/kbmDjQie14VJ7Uvf2hMB8GA1UdIwQYMBaAFOqb
aHUFL/kbmDjQie14VJ7Uvf2hMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEL
BQADggEBAEctiMs+zoaQ7LCk00geSCJFnFoeNYL/LFetksJRiCJkDC1Hy9PVtn86
axYNai2I+w1eEOdNjHR9E43Cl3bxwnQM064iekEdhGQmjfDYVXjdQtTt8Y0Gs/95
O/cnDVotmcfQdRzkNAlc5KEviy0YepKMajmBYRFwbg9Up6UGKjeHreZA0ebUx/BE
plCkBANCSPnBGLnTJD8YOkPORqlutAJtxDB5IWrjrlfjnX5h++mmS5B263C/TR4m
3BRnXMEhft056NDPDMzZI+fxGAn4xpMejd4ZfZd6l+YeYpxZyMn/4WuuyglnEDhp
ptU731ISG3+QJKG8+LHIlz78xx3GDxw=
-----END CERTIFICATE-----
28 changes: 28 additions & 0 deletions tls_test_cert/test_key.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDW7HsyC0ejJA7k
lj0SpTYRn8tCLV28O/UtRfTRXr73JE8L8iuwrUzYeEnrpIBak58CHubdFjCoPCOg
1VI0gD/gXLTJO2QtKsn00oozEOAz4wBZo/Q87WaTE8D/2HymjSDuKkw5J2ey2jgV
WiI3bC9vvlvcBaOoaszAIX43H7y6e9KFhj8+4t3Ybyfducpm66w12NpqTZhIbgAe
TLQSC+qcT9/PcoFsqPEK5084RK7dyQ0qvje92zXqtbf4cFe1H4PkgTbVEaE+ry6T
oMGwIt8N85N5oD6MTogemKDYaYuEqodA82739lBVRgpX8yrAeNDbJhq4xbO14BSK
KiAL/B9rAgMBAAECggEAAnHfNuME9hifaL9Cw5cIhevM6pxMgCsob1Ln5YfP4UzS
715aW+CkyqOXp6wP37flK6eBVct+UzOX7ijvDfTVhS5Yyh84VQEzGetZMhqDimOP
KfXg/d5vd8XWQLLMPDLHyJ3HjzDhD5pG4AtN71Z2Na2zKs4PngdU++yFnIfqZC6m
EMCnaVy+vG/FH072IOD7g9avBv3y765crOZnskscbzjsh8GGqbNYAM8WzoHQLaxg
/JXNtMcg5E92vLhoIdk5oicsxGNbppl+SqBxp3M0R0qjpYNybaeZ9aBdFgn9lxii
aZSZJoL7o1eKtabg3hipZaUnZtxMN7X5Kw2jyDw0PQKBgQDrQfz2J/01Ji/EGn/M
npAXgFUO+MWetWKVGdScj2d0GO7DHekoN4+CkQUthyY8y/30nXIRGnY+Y4JugpOi
JP7htK4oDOzGYS6MMT+kUMv1FnWhmbFH1JjaGElVOXy3lct+QYYRCX6tZXEsXYdK
74dLtYwcxOjcOuCdWltRPOPjXQKBgQDp34iK2ACU44XD4so9BZ2Mh26M4rABQY7Q
vmOgdM0TrEq0aWeNU1DR1g2H/Xuc/5LlZg0Jw+biFkX8TiaW6c1d5K/jJjDcQN2P
SOMqHUjtkufnLVYsbH8KfbMmZWFdmqmia8OmsXgZo7VB1tmU9wzSeg8SuRLmPlLH
tBSSwgzpZwKBgGXygpxpV+DgW3KvyRHy5J5KjpGeXIUaNU5Hk0sFGd/FrjH/lDpJ
WXdLQOMp3fgarkKCuBuRTAxdMviQvUlWnt1QXugcMb8F/hXigaHDIZ9jzDXrVFe8
WUCppZ24+8LStwxPeLmJU8vwWcrP/QEMK6UzVzRgYEiPeya1MT1TFa5BAoGBAJvR
Ypee8kRAko7AOx4M77sBQJZ9MeakVxKcxqPRLhE9aUhqMaPnLqGfi8RfDky7upM8
OtOWwe1ACcDgELXbcAhupQEiIMueK/+bAD6+5CflCLztZ8yRPNMwjHu4b/Z9ZSfh
xKj69JmgiNMk4jJtpw1UZVaEGCNuwphrUom04AVhAoGAWINTXulnmcjN9qNlgeQK
gx6tOjkLXms0E+Qzc5DoQQs10tqV7OCoqCyaAB1jG5qTSH8S90pymZyrYVWbwYZu
UeejMmWyz2LHbXsLNJhNNyhHXryjngDTMHQZdPAe4D0JVpaQneR89zC0fgjjxJqs
F4XdupKVcAoySZ97HvAjbaw=
-----END PRIVATE KEY-----
5 changes: 5 additions & 0 deletions tls_test_cert/test_protos.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Match by Common Name
nDPI_TestApp@tls_cert:"CN=nDPI_TestCert"

# Match by Organization
nDPI_TestOrg@tls_cert:"O=nDPI_Test_Org"

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As reported by @lucaderi here (#3099 (comment)) we want to match hash certificate.
So the rule (in protos.txt file) must be something like:
tls_cert_hash:da:39:a3:ee:5e:6b:4b:0d:32:55:bf:ef:95:60:18:90:af:d8:07:09@ProtoName.
No PEM/key stuff

Binary file added tls_test_cert/tls_cert_test.pcap
Binary file not shown.