Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fuzz: add a new fuzzer to test TLS certificates #1901

Merged
merged 1 commit into from
Mar 20, 2023
Merged
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
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@
/fuzz/fuzz_ds_ptree
/fuzz/fuzz_ds_ahocorasick
/fuzz/fuzz_libinjection
/fuzz/fuzz_tls_certificate
/fuzz/fuzz_ndpi_reader_alloc_fail_seed_corpus.zip
/fuzz/fuzz_ndpi_reader_seed_corpus.zip
/fuzz/fuzz_quic_get_crypto_data_seed_corpus.zip
Expand All @@ -89,6 +90,7 @@
/fuzz/fuzz_ds_ptree_seed_corpus.zip
/fuzz/fuzz_ds_ahocorasick_seed_corpus.zip
/fuzz/fuzz_libinjection_seed_corpus.zip
/fuzz/fuzz_tls_certificate_seed_corpus.zip
/fuzz/fuzz_*.dict
/influxdb/Makefile
/install-sh
Expand Down
23 changes: 20 additions & 3 deletions fuzz/Makefile.am
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
bin_PROGRAMS = fuzz_process_packet fuzz_ndpi_reader fuzz_ndpi_reader_alloc_fail fuzz_quic_get_crypto_data fuzz_config fuzz_community_id fuzz_serialization
bin_PROGRAMS = fuzz_process_packet fuzz_ndpi_reader fuzz_ndpi_reader_alloc_fail fuzz_quic_get_crypto_data fuzz_config fuzz_community_id fuzz_serialization fuzz_tls_certificate
#Alghoritms
bin_PROGRAMS += fuzz_alg_bins fuzz_alg_hll fuzz_alg_hw_rsi_outliers_da fuzz_alg_jitter fuzz_alg_ses_des fuzz_alg_crc32_md5 fuzz_alg_bytestream
#Data structures
Expand Down Expand Up @@ -292,7 +292,18 @@ fuzz_libinjection_LINK=$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CXX) @NDPI_CFLAGS@ $(AM_CXXFLAGS) $(CXXFLAGS) \
$(fuzz_libinjection_LDFLAGS) @NDPI_LDFLAGS@ $(LDFLAGS) -o $@


fuzz_tls_certificate_SOURCES = fuzz_tls_certificate.c fuzz_common_code.c
fuzz_tls_certificate_CFLAGS = @NDPI_CFLAGS@ $(CXXFLAGS)
fuzz_tls_certificate_LDADD = ../src/lib/libndpi.a $(ADDITIONAL_LIBS)
fuzz_tls_certificate_LDFLAGS = $(LIBS)
if HAS_FUZZLDFLAGS
fuzz_tls_certificate_CFLAGS += $(LIB_FUZZING_ENGINE)
fuzz_tls_certificate_LDFLAGS += $(LIB_FUZZING_ENGINE)
endif
# force usage of CXX for linker
fuzz_tls_certificate_LINK=$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CXX) @NDPI_CFLAGS@ $(AM_CXXFLAGS) $(CXXFLAGS) \
$(fuzz_tls_certificate_LDFLAGS) @NDPI_LDFLAGS@ $(LDFLAGS) -o $@

# required for Google oss-fuzz
# see https://github.com/google/oss-fuzz/tree/master/projects/ndpi
Expand Down Expand Up @@ -389,8 +400,12 @@ files_corpus_fuzz_libinjection := $(wildcard corpus/fuzz_libinjection/*)
fuzz_libinjection_seed_corpus.zip: $(files_corpus_fuzz_libinjection)
zip -j fuzz_libinjection_seed_corpus.zip $(files_corpus_fuzz_libinjection)

files_corpus_fuzz_tls_certificate := $(wildcard corpus/fuzz_tls_certificate/*)

fuzz_tls_certificate_seed_corpus.zip: $(files_corpus_fuzz_tls_certificate)
zip -j fuzz_tls_certificate_seed_corpus.zip $(files_corpus_fuzz_tls_certificate)

corpus: fuzz_ndpi_reader_seed_corpus.zip fuzz_ndpi_reader_alloc_fail_seed_corpus.zip fuzz_quic_get_crypto_data_seed_corpus.zip fuzz_config_seed_corpus.zip fuzz_ds_patricia_seed_corpus.zip fuzz_ds_ahocorasick_seed_corpus.zip fuzz_alg_ses_des_seed_corpus.zip fuzz_alg_hw_rsi_outliers_da_seed_corpus.zip fuzz_alg_bins_seed_corpus.zip fuzz_alg_hll_seed_corpus.zip fuzz_alg_jitter_seed_corpus.zip fuzz_ds_libcache_seed_corpus.zip fuzz_community_id_seed_corpus.zip fuzz_ds_tree_seed_corpus.zip fuzz_serialization_seed_corpus.zip fuzz_ds_ptree_seed_corpus.zip fuzz_alg_crc32_md5_seed_corpus.zip fuzz_alg_bytestream_seed_corpus.zip fuzz_libinjection_seed_corpus.zip
corpus: fuzz_ndpi_reader_seed_corpus.zip fuzz_ndpi_reader_alloc_fail_seed_corpus.zip fuzz_quic_get_crypto_data_seed_corpus.zip fuzz_config_seed_corpus.zip fuzz_ds_patricia_seed_corpus.zip fuzz_ds_ahocorasick_seed_corpus.zip fuzz_alg_ses_des_seed_corpus.zip fuzz_alg_hw_rsi_outliers_da_seed_corpus.zip fuzz_alg_bins_seed_corpus.zip fuzz_alg_hll_seed_corpus.zip fuzz_alg_jitter_seed_corpus.zip fuzz_ds_libcache_seed_corpus.zip fuzz_community_id_seed_corpus.zip fuzz_ds_tree_seed_corpus.zip fuzz_serialization_seed_corpus.zip fuzz_ds_ptree_seed_corpus.zip fuzz_alg_crc32_md5_seed_corpus.zip fuzz_alg_bytestream_seed_corpus.zip fuzz_libinjection_seed_corpus.zip fuzz_tls_certificate_seed_corpus.zip

#Create dictionaries exactly as expected by oss-fuzz.
#This way, if we need to change/update/add something,
Expand All @@ -399,6 +414,7 @@ dictionaries:
cp dictionary.dict fuzz_ndpi_reader.dict
cp dictionary.dict fuzz_ndpi_reader_alloc_fail.dict
cp dictionary.dict fuzz_process_packet.dict
cp dictionary_tls_certificate.dict fuzz_tls_certificate.dict

distdir:
find . -type d | xargs -I'{}' mkdir -p '$(distdir)/{}'
Expand All @@ -413,6 +429,7 @@ distdir:
-o -path './corpus/fuzz_serialization/*' \
-o -path './corpus/fuzz_community_id/*' \
-o -path './corpus/fuzz_libinjection/*' \
-o -path './corpus/fuzz_tls_certificate/*' \
-o -path './corpus/fuzz_alg_ses_des/*' \
-o -path './corpus/fuzz_alg_bins/*' \
-o -path './corpus/fuzz_alg_hll/*' \
Expand Down
Binary file added fuzz/corpus/fuzz_tls_certificate/1
Binary file not shown.
Binary file added fuzz/corpus/fuzz_tls_certificate/2
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
�H�
Binary file added fuzz/corpus/fuzz_tls_certificate/3
Binary file not shown.
Binary file added fuzz/corpus/fuzz_tls_certificate/4
Binary file not shown.
Binary file added fuzz/corpus/fuzz_tls_certificate/5
Binary file not shown.
Binary file added fuzz/corpus/fuzz_tls_certificate/6
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
��0���0
Binary file added fuzz/corpus/fuzz_tls_certificate/7
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
H
Binary file added fuzz/corpus/fuzz_tls_certificate/8
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
�H�,
Binary file added fuzz/corpus/fuzz_tls_certificate/9
Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
0��0���00�
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
H�
8 changes: 8 additions & 0 deletions fuzz/dictionary_tls_certificate.dict
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
"\x55\x04\x03"
"\x55\x04\x06"
"\x55\x04\x07"
"\x55\x04\x08"
"\x55\x04\x0A"
"\x55\x04\x0B"
"\x30\x1E\x17"
"\x55\x1D\x11"
47 changes: 47 additions & 0 deletions fuzz/fuzz_tls_certificate.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
#define NDPI_LIB_COMPILATION

#include "ndpi_api.h"
#include "fuzz_common_code.h"

#include <stdint.h>
#include <stdio.h>

extern void processCertificateElements(struct ndpi_detection_module_struct *ndpi_struct,
struct ndpi_flow_struct *flow,
u_int16_t p_offset, u_int16_t certificate_len);
struct ndpi_tcphdr tcph;
struct ndpi_iphdr iph;
struct ndpi_ipv6hdr iphv6;

struct ndpi_detection_module_struct *ndpi_struct = NULL;
struct ndpi_flow_struct *ndpi_flow = NULL;

int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
struct ndpi_packet_struct *packet;
int is_ipv6;

if (ndpi_struct == NULL) {
fuzz_init_detection_module(&ndpi_struct);
ndpi_flow = ndpi_calloc(1, sizeof(struct ndpi_flow_struct));
}

if(size == 0)
return -1;

packet = &ndpi_struct->packet;
packet->payload = data;
packet->payload_packet_len = size;
is_ipv6 = data[size - 1] % 5 ? 1 : 0; /* "Random" ipv4 vs ipv6 */
packet->iphv6 = is_ipv6 ? &iphv6 : NULL;
packet->iph = is_ipv6 ? NULL : &iph;
packet->tcp = &tcph;

memset(ndpi_flow, 0, sizeof(struct ndpi_flow_struct));
strcpy(ndpi_flow->host_server_name, "doh.opendns.com");
ndpi_flow->detected_protocol_stack[0] = NDPI_PROTOCOL_TLS;

processCertificateElements(ndpi_struct, ndpi_flow, 0, size);
ndpi_free_flow_data(ndpi_flow);

return 0;
}
19 changes: 12 additions & 7 deletions src/lib/protocols/tls.c
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,7 @@ static int extractRDNSequence(struct ndpi_packet_struct *packet,
char *rdnSeqBuf, u_int *rdnSeqBuf_offset,
u_int rdnSeqBuf_len,
const char *label) {
u_int8_t str_len = packet->payload[offset+4], is_printable = 1;
u_int8_t str_len, is_printable = 1;
char *str;
u_int len;

Expand All @@ -258,6 +258,10 @@ static int extractRDNSequence(struct ndpi_packet_struct *packet,
#endif
return -1;
}
if((offset+4) >= packet->payload_packet_len)
return(-1);

str_len = packet->payload[offset+4];

// packet is truncated... further inspection is not needed
if((offset+4+str_len) >= packet->payload_packet_len)
Expand Down Expand Up @@ -356,9 +360,9 @@ static void checkTLSSubprotocol(struct ndpi_detection_module_struct *ndpi_struct
/* **************************************** */

/* See https://blog.catchpoint.com/2017/05/12/dissecting-tls-using-wireshark/ */
static void processCertificateElements(struct ndpi_detection_module_struct *ndpi_struct,
struct ndpi_flow_struct *flow,
u_int16_t p_offset, u_int16_t certificate_len) {
void processCertificateElements(struct ndpi_detection_module_struct *ndpi_struct,
struct ndpi_flow_struct *flow,
u_int16_t p_offset, u_int16_t certificate_len) {
struct ndpi_packet_struct *packet = &ndpi_struct->packet;
u_int16_t num_found = 0, i;
char buffer[64] = { '\0' }, rdnSeqBuf[2048];
Expand Down Expand Up @@ -427,7 +431,6 @@ static void processCertificateElements(struct ndpi_detection_module_struct *ndpi
#endif
} else if((packet->payload[i] == 0x30) && (packet->payload[i+1] == 0x1e) && (packet->payload[i+2] == 0x17)) {
/* Certificate Validity */
u_int8_t len = packet->payload[i+3];
u_int offset = i+4;

if(num_found == 0) {
Expand All @@ -450,8 +453,10 @@ static void processCertificateElements(struct ndpi_detection_module_struct *ndpi
rdn_len = 0; /* Reset buffer */
}

if((offset+len) < packet->payload_packet_len) {
if(i + 3 < certificate_len &&
(offset+packet->payload[i+3]) < packet->payload_packet_len) {
char utcDate[32];
u_int8_t len = packet->payload[i+3];

#ifdef DEBUG_TLS
u_int j;
Expand Down Expand Up @@ -568,7 +573,7 @@ static void processCertificateElements(struct ndpi_detection_module_struct *ndpi
i += 3 /* skip the initial patten 55 1D 11 */;

/* skip the first type, 0x04 == BIT STRING, and jump to it's length */
if(packet->payload[i] == 0x04) i++; else i += 4; /* 4 bytes, with the last byte set to 04 */
if(i < packet->payload_packet_len && packet->payload[i] == 0x04) i++; else i += 4; /* 4 bytes, with the last byte set to 04 */

if(i < packet->payload_packet_len) {
i += (packet->payload[i] & 0x80) ? (packet->payload[i] & 0x7F) : 0; /* skip BIT STRING length */
Expand Down