aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/lib/protocols/ssl.c199
1 files changed, 125 insertions, 74 deletions
diff --git a/src/lib/protocols/ssl.c b/src/lib/protocols/ssl.c
index 5a0d03aec..493ee7cbc 100644
--- a/src/lib/protocols/ssl.c
+++ b/src/lib/protocols/ssl.c
@@ -341,7 +341,7 @@ static void stripCertificateTrailer(char *buffer, int buffer_len) {
/* https://engineering.salesforce.com/tls-fingerprinting-with-ja3-and-ja3s-247362855967 */
-#define JA3_STR_LEN 512
+#define JA3_STR_LEN 1024
#define MAX_NUM_JA3 128
struct ja3_info {
@@ -358,6 +358,7 @@ int getSSLcertificate(struct ndpi_detection_module_struct *ndpi_struct,
char *buffer, int buffer_len) {
struct ndpi_packet_struct *packet = &flow->packet;
struct ja3_info ja3;
+ u_int8_t invalid_ja3 = 0;
u_int16_t ssl_version = (packet->payload[1] << 8) + packet->payload[2], ja3_str_len;
char ja3_str[JA3_STR_LEN];
MD5_CTX ctx;
@@ -399,7 +400,7 @@ int getSSLcertificate(struct ndpi_detection_module_struct *ndpi_struct,
|| (handshake_protocol == 0xb) /* Server Hello and Certificate message types are interesting for us */) {
u_int num_found = 0;
u_int16_t ssl_version = ntohs(*((u_int16_t*)&packet->payload[9]));
-
+
ja3.ssl_version = ssl_version;
if(handshake_protocol == 0x02) {
@@ -510,7 +511,7 @@ int getSSLcertificate(struct ndpi_detection_module_struct *ndpi_struct,
#ifdef CERTIFICATE_DEBUG
printf("[JA3] Server: %s \n", ja3_str);
#endif
-
+
MD5Init(&ctx);
MD5Update(&ctx, (const unsigned char *)ja3_str, strlen(ja3_str));
MD5Final(md5_hash, &ctx);
@@ -522,7 +523,7 @@ int getSSLcertificate(struct ndpi_detection_module_struct *ndpi_struct,
#ifdef CERTIFICATE_DEBUG
printf("[JA3] Server: %s \n", flow->protos.stun_ssl.ssl.ja3_server);
#endif
-
+
return(1 /* Server Certificate */);
}
}
@@ -534,9 +535,9 @@ int getSSLcertificate(struct ndpi_detection_module_struct *ndpi_struct,
if(base_offset + 2 <= packet->payload_packet_len) {
u_int16_t session_id_len = packet->payload[base_offset];
u_int16_t ssl_version = ntohs(*((u_int16_t*)&packet->payload[9]));
-
+
ja3.ssl_version = ssl_version;
-
+
if((session_id_len+base_offset+2) <= total_len) {
u_int16_t cypher_len = packet->payload[session_id_len+base_offset+2] + (packet->payload[session_id_len+base_offset+1] << 8);
u_int16_t i, cypher_offset = base_offset + session_id_len + 3;
@@ -545,25 +546,38 @@ int getSSLcertificate(struct ndpi_detection_module_struct *ndpi_struct,
printf("SSL [client cypher_len: %u]\n", cypher_len);
#endif
- for(i=0; i<cypher_len;) {
- u_int16_t *id = (u_int16_t*)&packet->payload[cypher_offset+i];
-
+ if((cypher_offset+cypher_len) <= total_len) {
+ for(i=0; i<cypher_len;) {
+ u_int16_t *id = (u_int16_t*)&packet->payload[cypher_offset+i];
+
+#ifdef CERTIFICATE_DEBUG
+ printf("SSL [cypher suite: %u] [%u/%u]\n", ntohs(*id), i, cypher_len);
+#endif
+ if((*id == 0) || (packet->payload[cypher_offset+i] != packet->payload[cypher_offset+i+1])) {
+ /*
+ Skip GREASE [https://tools.ietf.org/id/draft-ietf-tls-grease-01.html]
+ https://engineering.salesforce.com/tls-fingerprinting-with-ja3-and-ja3s-247362855967
+ */
+
+ if(ja3.num_cipher < MAX_NUM_JA3)
+ ja3.cipher[ja3.num_cipher++] = ntohs(*id);
+ else {
+ invalid_ja3 = 1;
#ifdef CERTIFICATE_DEBUG
- printf("SSL [cypher suite: %u] [%u/%u]\n", ntohs(*id), i, cypher_len);
+ printf("SSL Invalid cypher %u\n", ja3.num_cipher);
#endif
- if((*id == 0) || (packet->payload[cypher_offset+i] != packet->payload[cypher_offset+i+1])) {
- /*
- Skip GREASE [https://tools.ietf.org/id/draft-ietf-tls-grease-01.html]
- https://engineering.salesforce.com/tls-fingerprinting-with-ja3-and-ja3s-247362855967
- */
+ }
+ }
- if(ja3.num_cipher < MAX_NUM_JA3)
- ja3.cipher[ja3.num_cipher++] = ntohs(*id);
+ i += 2;
}
-
- i += 2;
+ } else {
+ invalid_ja3 = 1;
+#ifdef CERTIFICATE_DEBUG
+ printf("SSL Invalid len %u vs %u\n", (cypher_offset+cypher_len), total_len);
+#endif
}
-
+
offset = base_offset + session_id_len + cypher_len + 2;
flow->l4.tcp.ssl_seen_client_cert = 1;
@@ -609,14 +623,20 @@ int getSSLcertificate(struct ndpi_detection_module_struct *ndpi_struct,
#ifdef CERTIFICATE_DEBUG
printf("SSL [extension_id: %u][extension_len: %u]\n", extension_id, extension_len);
#endif
-
+
if((extension_id == 0) || (packet->payload[extn_off] != packet->payload[extn_off+1])) {
/* Skip GREASE */
-
+
if(ja3.num_ssl_extension < MAX_NUM_JA3)
ja3.ssl_extension[ja3.num_ssl_extension++] = extension_id;
+ else {
+ invalid_ja3 = 1;
+#ifdef CERTIFICATE_DEBUG
+ printf("SSL Invalid extensions %u\n", ja3.num_ssl_extension);
+#endif
+ }
}
-
+
if(extension_id == 0 /* server name */) {
u_int16_t len;
@@ -638,39 +658,64 @@ int getSSLcertificate(struct ndpi_detection_module_struct *ndpi_struct,
printf("SSL [EllipticCurve: len=%u]\n", extension_len);
#endif
- for(i=0; i<extension_len-2;) {
- u_int16_t s_group = ntohs(*((u_int16_t*)&packet->payload[s_offset+i]));
-
+ if((s_offset+extension_len-1) < total_len) {
+ for(i=0; i<extension_len-2;) {
+ u_int16_t s_group = ntohs(*((u_int16_t*)&packet->payload[s_offset+i]));
+
+#ifdef CERTIFICATE_DEBUG
+ printf("SSL [EllipticCurve: %u]\n", s_group);
+#endif
+ if((s_group == 0) || (packet->payload[s_offset+i] != packet->payload[s_offset+i+1])) {
+ /* Skip GREASE */
+ if(ja3.num_elliptic_curve < MAX_NUM_JA3)
+ ja3.elliptic_curve[ja3.num_elliptic_curve++] = s_group;
+ else {
+ invalid_ja3 = 1;
#ifdef CERTIFICATE_DEBUG
- printf("SSL [EllipticCurve: %u]\n", s_group);
+ printf("SSL Invalid num elliptic %u\n", ja3.num_elliptic_curve);
#endif
- if((s_group == 0) || (packet->payload[s_offset+i] != packet->payload[s_offset+i+1])) {
- /* Skip GREASE */
- if(ja3.num_elliptic_curve < MAX_NUM_JA3)
- ja3.elliptic_curve[ja3.num_elliptic_curve++] = s_group;
+ }
+ }
+
+ i += 2;
}
-
- i += 2;
- }
+ } else {
+ invalid_ja3 = 1;
+#ifdef CERTIFICATE_DEBUG
+ printf("SSL Invalid len %u vs %u\n", (s_offset+extension_len-1), total_len);
+#endif
+ }
} else if(extension_id == 11 /* ec_point_formats groups */) {
u_int16_t i, s_offset = offset+extension_offset + 1;
#ifdef CERTIFICATE_DEBUG
printf("SSL [EllipticCurveFormat: len=%u]\n", extension_len);
#endif
-
- for(i=0; i<extension_len-1;i++) {
- u_int8_t s_group = packet->payload[s_offset+i];
-
+ if((s_offset+extension_len) < total_len) {
+ for(i=0; i<extension_len-1;i++) {
+ u_int8_t s_group = packet->payload[s_offset+i];
+
#ifdef CERTIFICATE_DEBUG
- printf("SSL [EllipticCurveFormat: %u]\n", s_group);
+ printf("SSL [EllipticCurveFormat: %u]\n", s_group);
+#endif
+
+ if(ja3.num_elliptic_curve_point_format < MAX_NUM_JA3)
+ ja3.elliptic_curve_point_format[ja3.num_elliptic_curve_point_format++] = s_group;
+ else {
+ invalid_ja3 = 1;
+#ifdef CERTIFICATE_DEBUG
+ printf("SSL Invalid num elliptic %u\n", ja3.num_elliptic_curve_point_format);
+#endif
+ }
+ }
+ } else {
+ invalid_ja3 = 1;
+#ifdef CERTIFICATE_DEBUG
+ printf("SSL Invalid len %u vs %u\n", s_offset+extension_len, total_len);
#endif
-
- if(ja3.num_elliptic_curve_point_format < MAX_NUM_JA3)
- ja3.elliptic_curve_point_format[ja3.num_elliptic_curve_point_format++] = s_group;
}
}
-
+
extension_offset += extension_len;
#ifdef CERTIFICATE_DEBUG
@@ -678,45 +723,51 @@ int getSSLcertificate(struct ndpi_detection_module_struct *ndpi_struct,
#endif
} /* while */
- ja3_str_len = snprintf(ja3_str, sizeof(ja3_str), "%u,", ja3.ssl_version);
-
- for(i=0; i<ja3.num_cipher; i++)
- ja3_str_len += snprintf(&ja3_str[ja3_str_len], sizeof(ja3_str)-ja3_str_len, "%s%u", (i > 0) ? "-" : "", ja3.cipher[i]);
-
- ja3_str_len += snprintf(&ja3_str[ja3_str_len], sizeof(ja3_str)-ja3_str_len, ",");
-
- /* ********** */
-
- for(i=0; i<ja3.num_ssl_extension; i++)
- ja3_str_len += snprintf(&ja3_str[ja3_str_len], sizeof(ja3_str)-ja3_str_len, "%s%u", (i > 0) ? "-" : "", ja3.ssl_extension[i]);
-
- ja3_str_len += snprintf(&ja3_str[ja3_str_len], sizeof(ja3_str)-ja3_str_len, ",");
-
- /* ********** */
-
- for(i=0; i<ja3.num_elliptic_curve; i++)
- ja3_str_len += snprintf(&ja3_str[ja3_str_len], sizeof(ja3_str)-ja3_str_len, "%s%u", (i > 0) ? "-" : "", ja3.elliptic_curve[i]);
-
- ja3_str_len += snprintf(&ja3_str[ja3_str_len], sizeof(ja3_str)-ja3_str_len, ",");
-
- for(i=0; i<ja3.num_elliptic_curve_point_format; i++)
- ja3_str_len += snprintf(&ja3_str[ja3_str_len], sizeof(ja3_str)-ja3_str_len, "%s%u", (i > 0) ? "-" : "", ja3.elliptic_curve_point_format[i]);
+ if(!invalid_ja3) {
+ ja3_str_len = snprintf(ja3_str, sizeof(ja3_str), "%u,", ja3.ssl_version);
+
+ for(i=0; i<ja3.num_cipher; i++)
+ ja3_str_len += snprintf(&ja3_str[ja3_str_len], sizeof(ja3_str)-ja3_str_len, "%s%u",
+ (i > 0) ? "-" : "", ja3.cipher[i]);
+
+ ja3_str_len += snprintf(&ja3_str[ja3_str_len], sizeof(ja3_str)-ja3_str_len, ",");
+
+ /* ********** */
+
+ for(i=0; i<ja3.num_ssl_extension; i++)
+ ja3_str_len += snprintf(&ja3_str[ja3_str_len], sizeof(ja3_str)-ja3_str_len, "%s%u",
+ (i > 0) ? "-" : "", ja3.ssl_extension[i]);
+
+ ja3_str_len += snprintf(&ja3_str[ja3_str_len], sizeof(ja3_str)-ja3_str_len, ",");
+
+ /* ********** */
+
+ for(i=0; i<ja3.num_elliptic_curve; i++)
+ ja3_str_len += snprintf(&ja3_str[ja3_str_len], sizeof(ja3_str)-ja3_str_len, "%s%u",
+ (i > 0) ? "-" : "", ja3.elliptic_curve[i]);
+
+ ja3_str_len += snprintf(&ja3_str[ja3_str_len], sizeof(ja3_str)-ja3_str_len, ",");
+
+ for(i=0; i<ja3.num_elliptic_curve_point_format; i++)
+ ja3_str_len += snprintf(&ja3_str[ja3_str_len], sizeof(ja3_str)-ja3_str_len, "%s%u",
+ (i > 0) ? "-" : "", ja3.elliptic_curve_point_format[i]);
#ifdef CERTIFICATE_DEBUG
- printf("[JA3] Client: %s \n", ja3_str);
+ printf("[JA3] Client: %s \n", ja3_str);
#endif
- MD5Init(&ctx);
- MD5Update(&ctx, (const unsigned char *)ja3_str, strlen(ja3_str));
- MD5Final(md5_hash, &ctx);
+ MD5Init(&ctx);
+ MD5Update(&ctx, (const unsigned char *)ja3_str, strlen(ja3_str));
+ MD5Final(md5_hash, &ctx);
- for(i=0, j=0; i<16; i++)
- j += snprintf(&flow->protos.stun_ssl.ssl.ja3_client[j],
- sizeof(flow->protos.stun_ssl.ssl.ja3_client)-j, "%02x", md5_hash[i]);
+ for(i=0, j=0; i<16; i++)
+ j += snprintf(&flow->protos.stun_ssl.ssl.ja3_client[j],
+ sizeof(flow->protos.stun_ssl.ssl.ja3_client)-j, "%02x", md5_hash[i]);
#ifdef CERTIFICATE_DEBUG
- printf("[JA3] Client: %s \n", flow->protos.stun_ssl.ssl.ja3_client);
+ printf("[JA3] Client: %s \n", flow->protos.stun_ssl.ssl.ja3_client);
#endif
+ }
return(2 /* Client Certificate */);
}