Skip to content

Commit

Permalink
fuzz: extend fuzzers coverage (#1952)
Browse files Browse the repository at this point in the history
  • Loading branch information
IvanNardi authored Apr 25, 2023
1 parent de693cb commit 40b6d5a
Show file tree
Hide file tree
Showing 15 changed files with 107 additions and 38 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@
/fuzz/fuzz_libinjection
/fuzz/fuzz_tls_certificate
/fuzz/fuzz_gcrypt_light
/fuzz/fuzz_ndpi_reader_payload_analyzer
/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 @@ -92,6 +93,7 @@
/fuzz/fuzz_ds_ahocorasick_seed_corpus.zip
/fuzz/fuzz_libinjection_seed_corpus.zip
/fuzz/fuzz_tls_certificate_seed_corpus.zip
/fuzz/fuzz_ndpi_reader_payload_analyzer_seed_corpus.zip
/fuzz/fuzz_*.dict
/influxdb/Makefile
/install-sh
Expand Down
4 changes: 2 additions & 2 deletions fuzz/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,8 @@ fuzz_ndpi_reader_alloc_fail_LINK=$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAG
$(LIBTOOLFLAGS) --mode=link $(CXX) @NDPI_CFLAGS@ $(AM_CXXFLAGS) $(CXXFLAGS) \
$(fuzz_ndpi_reader_alloc_fail_LDFLAGS) @NDPI_LDFLAGS@ $(LDFLAGS) -o $@

fuzz_ndpi_reader_payload_analyzer_SOURCES = fuzz_ndpi_reader.c ../example/reader_util.c
fuzz_ndpi_reader_payload_analyzer_CFLAGS = -I../example/ @NDPI_CFLAGS@ $(CXXFLAGS) -DENABLE_PAYLOAD_ANALYZER
fuzz_ndpi_reader_payload_analyzer_SOURCES = fuzz_ndpi_reader.c fuzz_common_code.c ../example/reader_util.c
fuzz_ndpi_reader_payload_analyzer_CFLAGS = -I../example/ @NDPI_CFLAGS@ $(CXXFLAGS) -DENABLE_MEM_ALLOC_FAILURES -DENABLE_PAYLOAD_ANALYZER
fuzz_ndpi_reader_payload_analyzer_LDADD = ../src/lib/libndpi.a $(ADDITIONAL_LIBS)
fuzz_ndpi_reader_payload_analyzer_LDFLAGS = $(PCAP_LIB) $(LIBS)
if HAS_FUZZLDFLAGS
Expand Down
2 changes: 2 additions & 0 deletions fuzz/fuzz_alg_hw_rsi_outliers_da.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,8 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
ndpi_data_entropy(a);
ndpi_reset_data_analysis(a);

ndpi_hw_reset(&hw);

/* Data ratio */
if (num_values > 1)
ndpi_data_ratio2str(ndpi_data_ratio(values[0], values[1]));
Expand Down
3 changes: 3 additions & 0 deletions fuzz/fuzz_alg_ses_des.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,5 +45,8 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
ndpi_des_add_value(&d, value, &forecast, &confidence_band);
}

ndpi_ses_reset(&s);
ndpi_des_reset(&d);

return 0;
}
5 changes: 1 addition & 4 deletions fuzz/fuzz_common_code.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,19 +38,16 @@ void fuzz_init_detection_module(struct ndpi_detection_module_struct **ndpi_info_
{
ndpi_init_prefs prefs = ndpi_enable_ja3_plus;
NDPI_PROTOCOL_BITMASK all;
NDPI_PROTOCOL_BITMASK debug_bitmask;

if(*ndpi_info_mod == NULL) {
*ndpi_info_mod = ndpi_init_detection_module(prefs);
NDPI_BITMASK_SET_ALL(all);
ndpi_set_protocol_detection_bitmask2(*ndpi_info_mod, &all);

#if 0
NDPI_PROTOCOL_BITMASK debug_bitmask;

NDPI_BITMASK_SET_ALL(debug_bitmask);
ndpi_set_log_level(*ndpi_info_mod, 4);
ndpi_set_debug_bitmask(*ndpi_info_mod, debug_bitmask);
#endif

ndpi_load_protocols_file(*ndpi_info_mod, "protos.txt");
ndpi_load_categories_file(*ndpi_info_mod, "categories.txt", NULL);
Expand Down
51 changes: 47 additions & 4 deletions fuzz/fuzz_config.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "ndpi_api.h"
#include "ndpi_classify.h"
#include "fuzz_common_code.h"

#include <stdint.h>
Expand All @@ -25,17 +26,19 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
struct ndpi_flow_input_info input_info;
ndpi_proto p, p2;
char out[128];
char log_ts[32];


if(fuzzed_data.remaining_bytes() < 4 + /* ndpi_init_detection_module() */
NDPI_MAX_SUPPORTED_PROTOCOLS + NDPI_MAX_NUM_CUSTOM_PROTOCOLS +
1 + /* TLS cert expire */
6 + /* files */
((NDPI_LRUCACHE_MAX + 1) * 5) + /* LRU caches */
2 + 1 + 5 + /* ndpi_set_detection_preferences() */
2 + 1 + 4 + /* ndpi_set_detection_preferences() */
7 + /* Opportunistic tls */
2 + /* Pid */
2 + /* Category */
1 + /* Tunnel */
1 + /* Bool value */
2 + /* input_info */
21 /* Min real data: ip length + 1 byte of L4 header */)
Expand Down Expand Up @@ -82,6 +85,9 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
ndpi_get_lru_cache_ttl(ndpi_info_mod, static_cast<lru_cache_type>(i), &num);
}

/* TODO: stub for geo stuff */
ndpi_load_geoip(ndpi_info_mod, NULL, NULL);

if(fuzzed_data.ConsumeBool())
ndpi_set_detection_preferences(ndpi_info_mod, ndpi_pref_direction_detect_disable,
fuzzed_data.ConsumeBool());
Expand All @@ -90,7 +96,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
0 /* unused */);
if(fuzzed_data.ConsumeBool())
ndpi_set_detection_preferences(ndpi_info_mod, ndpi_pref_max_packets_to_process,
fuzzed_data.ConsumeIntegralInRange(0, (1 << 24)));
fuzzed_data.ConsumeIntegralInRange(0, (1 << 16)));

ndpi_set_opportunistic_tls(ndpi_info_mod, NDPI_PROTOCOL_MAIL_SMTP, fuzzed_data.ConsumeBool());
ndpi_get_opportunistic_tls(ndpi_info_mod, NDPI_PROTOCOL_MAIL_SMTP);
Expand Down Expand Up @@ -121,7 +127,6 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
}
ndpi_set_proto_breed(ndpi_info_mod, pid, NDPI_PROTOCOL_SAFE);
ndpi_set_proto_category(ndpi_info_mod, pid, NDPI_PROTOCOL_CATEGORY_MEDIA);
ndpi_is_subprotocol_informative(ndpi_info_mod, pid);

/* Custom category configuration */
cat = fuzzed_data.ConsumeIntegralInRange(static_cast<int>(NDPI_PROTOCOL_CATEGORY_CUSTOM_1),
Expand All @@ -131,20 +136,27 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
ndpi_category_get_name(ndpi_info_mod, static_cast<ndpi_protocol_category_t>(cat));
ndpi_get_category_id(ndpi_info_mod, catname);

ndpi_tunnel2str(static_cast<ndpi_packet_tunnel>(fuzzed_data.ConsumeIntegralInRange(static_cast<int>(ndpi_no_tunnel),
static_cast<int>(ndpi_gre_tunnel + 1)))); /* + 1 to trigger invalid value */

ndpi_get_num_supported_protocols(ndpi_info_mod);
ndpi_get_proto_defaults(ndpi_info_mod);
ndpi_get_ndpi_num_custom_protocols(ndpi_info_mod);
ndpi_get_ndpi_num_supported_protocols(ndpi_info_mod);

ndpi_self_check_host_match(stderr);

/* Basic code to try testing this "config" */
bool_value = fuzzed_data.ConsumeBool();
input_info.in_pkt_dir = !!fuzzed_data.ConsumeBool();
input_info.in_pkt_dir = fuzzed_data.ConsumeIntegralInRange(0,2);
input_info.seen_flow_beginning = !!fuzzed_data.ConsumeBool();
memset(&flow, 0, sizeof(flow));
std::vector<uint8_t>pkt = fuzzed_data.ConsumeRemainingBytes<uint8_t>();
assert(pkt.size() >= 21); /* To be sure check on fuzzed_data.remaining_bytes() at the beginning is right */

ndpi_detection_process_packet(ndpi_info_mod, &flow, pkt.data(), pkt.size(), 0, &input_info);
p = ndpi_detection_giveup(ndpi_info_mod, &flow, 1, &protocol_was_guessed);

assert(p.master_protocol == ndpi_get_flow_masterprotocol(ndpi_info_mod, &flow));
assert(p.app_protocol == ndpi_get_flow_appprotocol(ndpi_info_mod, &flow));
assert(p.category == ndpi_get_flow_category(ndpi_info_mod, &flow));
Expand All @@ -154,17 +166,38 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
ndpi_get_flow_risk_info(&flow, out, sizeof(out), 1);
ndpi_get_flow_ndpi_proto(ndpi_info_mod, &flow, &p2);
ndpi_is_proto(p, NDPI_PROTOCOL_TLS);
ndpi_http_method2str(flow.http.method);
ndpi_get_l4_proto_name(ndpi_get_l4_proto_info(ndpi_info_mod, p.app_protocol));
ndpi_is_subprotocol_informative(ndpi_info_mod, p.app_protocol);
ndpi_get_http_method(ndpi_info_mod, &flow);
ndpi_get_http_url(ndpi_info_mod, &flow);
ndpi_get_http_content_type(ndpi_info_mod, &flow);
ndpi_check_for_email_address(ndpi_info_mod, 0);
/* ndpi_guess_undetected_protocol() is a "strange" function. Try fuzzing it, here */
if(!ndpi_is_protocol_detected(ndpi_info_mod, p)) {
ndpi_guess_undetected_protocol(ndpi_info_mod, bool_value ? &flow : NULL,
flow.l4_proto);
if(!flow.is_ipv6) {
/* Another "strange" function (ipv4 only): fuzz it here, for lack of a better alternative */
ndpi_find_ipv4_category_userdata(ndpi_info_mod, flow.c_address.v4);

ndpi_search_tcp_or_udp_raw(ndpi_info_mod, NULL, 0, ntohl(flow.c_address.v4), ntohl(flow.s_address.v4));
}
/* Another "strange" function: fuzz it here, for lack of a better alternative */
ndpi_search_tcp_or_udp(ndpi_info_mod, &flow);
}
if(!flow.is_ipv6) {
ndpi_network_ptree_match(ndpi_info_mod, (struct in_addr *)&flow.c_address.v4);

ndpi_risk_params params[] = { { NDPI_PARAM_HOSTNAME, flow.host_server_name},
{ NDPI_PARAM_ISSUER_DN, flow.host_server_name},
{ NDPI_PARAM_HOST_IPV4, &flow.c_address.v4} };
ndpi_check_flow_risk_exceptions(ndpi_info_mod, 3, params);
}
/* TODO: stub for geo stuff */
ndpi_get_geoip_asn(ndpi_info_mod, NULL, NULL);
ndpi_get_geoip_country_continent(ndpi_info_mod, NULL, NULL, 0, NULL, 0);

ndpi_free_flow_data(&flow);

/* Get some final stats */
Expand All @@ -180,6 +213,16 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
ndpi_get_api_version();
ndpi_get_gcrypt_version();

ndpi_get_ndpi_detection_module_size();
ndpi_detection_get_sizeof_ndpi_flow_struct();
ndpi_detection_get_sizeof_ndpi_flow_tcp_struct();
ndpi_detection_get_sizeof_ndpi_flow_udp_struct();

ndpi_get_tot_allocated_memory();
ndpi_log_timestamp(log_ts, sizeof(log_ts));

ndpi_free_geoip(ndpi_info_mod);

ndpi_exit_detection_module(ndpi_info_mod);

return 0;
Expand Down
18 changes: 16 additions & 2 deletions fuzz/fuzz_libinjection.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
char *query;
char fingerprint[8];
struct libinjection_sqli_state state;

/* No memory allocations involved */

Expand All @@ -15,11 +15,25 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
memcpy(query, data, size);
query[size] = '\0';

libinjection_sqli(query, strlen(query), fingerprint);

libinjection_sqli_init(&state, query, strlen(query), 0); /* Default: FLAG_QUOTE_NONE | FLAG_SQL_ANSI */
libinjection_is_sqli(&state);
libinjection_sqli_init(&state, query, strlen(query), FLAG_QUOTE_SINGLE | FLAG_SQL_ANSI);
libinjection_is_sqli(&state);
libinjection_sqli_init(&state, query, strlen(query), FLAG_QUOTE_DOUBLE | FLAG_SQL_ANSI);
libinjection_is_sqli(&state);
libinjection_sqli_init(&state, query, strlen(query), FLAG_QUOTE_NONE | FLAG_SQL_MYSQL);
libinjection_is_sqli(&state);
libinjection_sqli_init(&state, query, strlen(query), FLAG_QUOTE_SINGLE | FLAG_SQL_MYSQL);
libinjection_is_sqli(&state);
libinjection_sqli_init(&state, query, strlen(query), FLAG_QUOTE_DOUBLE | FLAG_SQL_MYSQL);
libinjection_is_sqli(&state);

libinjection_xss(query, strlen(query));

free(query);

libinjection_version();

return 0;
}
2 changes: 1 addition & 1 deletion fuzz/fuzz_ndpi_reader.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ u_int8_t max_num_udp_dissected_pkts = 16 /* 8 is enough for most protocols, Sign
ndpi_init_prefs init_prefs = ndpi_track_flow_payload | ndpi_enable_ja3_plus;
int enable_malloc_bins = 1;
int malloc_size_stats = 0;
int max_malloc_bins = 0;
int max_malloc_bins = 14;
struct ndpi_bin malloc_bins; /* unused */

extern void ndpi_report_payload_stats(int print);
Expand Down
8 changes: 8 additions & 0 deletions src/include/ndpi_classify.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@

#include "ndpi_includes.h"

#ifdef __cplusplus
extern "C" {
#endif

/* constants */
#define NUM_PARAMETERS_SPLT_LOGREG 208
#define NUM_PARAMETERS_BD_LOGREG 464
Expand Down Expand Up @@ -89,4 +93,8 @@ u_int64_t ndpi_timeval_to_milliseconds(pkt_timeval ts);
u_int64_t ndpi_timeval_to_microseconds(pkt_timeval ts);
void ndpi_log_timestamp(char *log_ts, u_int32_t log_ts_len);

#ifdef __cplusplus
}
#endif

#endif /* NDPI_CLASSIFY_H */
2 changes: 1 addition & 1 deletion src/include/ndpi_main.h
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ extern "C" {
struct ndpi_flow_struct *flow);

extern u_int16_t ndpi_check_for_email_address(struct ndpi_detection_module_struct *ndpi_struct,
u_int16_t counter);
u_int16_t counter);

extern void ndpi_int_change_category(struct ndpi_detection_module_struct *ndpi_struct,
struct ndpi_flow_struct *flow,
Expand Down
3 changes: 3 additions & 0 deletions src/include/ndpi_protocols.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ ndpi_port_range* ndpi_build_default_ports(ndpi_port_range *ports,
u_int16_t portE);

/* TCP/UDP protocols */
#ifdef __cplusplus
extern "C"
#endif
u_int ndpi_search_tcp_or_udp_raw(struct ndpi_detection_module_struct *ndpi_struct,
struct ndpi_flow_struct *flow,
u_int8_t protocol,
Expand Down
7 changes: 5 additions & 2 deletions src/lib/ndpi_analyze.c
Original file line number Diff line number Diff line change
Expand Up @@ -1096,6 +1096,7 @@ int ndpi_hw_init(struct ndpi_hw_struct *hw,

if((hw->s = (double*)ndpi_calloc(hw->params.num_season_periods, sizeof(double))) == NULL) {
ndpi_free(hw->y);
hw->y = NULL;
return(-1);
}

Expand Down Expand Up @@ -1213,8 +1214,10 @@ void ndpi_hw_reset(struct ndpi_hw_struct *hw) {
hw->num_values = 0;
hw->u = hw->v = hw->sum_square_error = 0;

memset(&hw->y, 0, (hw->params.num_season_periods * sizeof(u_int64_t)));
memset(&hw->s, 0, (hw->params.num_season_periods * sizeof(double)));
if(hw->y)
memset(hw->y, 0, (hw->params.num_season_periods * sizeof(u_int64_t)));
if(hw->s)
memset(hw->s, 0, (hw->params.num_season_periods * sizeof(double)));
}

/* ********************************************************************************* */
Expand Down
6 changes: 4 additions & 2 deletions src/lib/ndpi_classify.c
Original file line number Diff line number Diff line change
Expand Up @@ -268,10 +268,12 @@ ndpi_merge_splt_arrays (const uint16_t *pkt_len, const pkt_timeval *pkt_time,
uint16_t *merged_lens, uint16_t *merged_times)
{
int s,r;
pkt_timeval ts_start = { 0, 0 }; /* initialize to avoid spurious warnings */
pkt_timeval ts_start;
pkt_timeval tmp, tmp_r;
pkt_timeval start_m;

ndpi_timer_clear(&ts_start);

if(r_idx + s_idx == 0) {
return ;
} else if(r_idx == 0) {
Expand Down Expand Up @@ -677,7 +679,7 @@ ndpi_timeval_to_microseconds(pkt_timeval ts)
{
u_int64_t sec = ts.tv_sec;
u_int64_t usec = ts.tv_usec;
return usec + sec * 1000 * 1000;;
return usec + sec * 1000 * 1000;
}

/* **************************************** */
Expand Down
12 changes: 8 additions & 4 deletions src/lib/ndpi_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -2287,7 +2287,7 @@ u_int16_t ndpi_network_ptree_match(struct ndpi_detection_module_struct *ndpi_str
ndpi_prefix_t prefix;
ndpi_patricia_node_t *node;

if(!ndpi_str->protocols_ptree)
if(!ndpi_str || !ndpi_str->protocols_ptree)
return(NDPI_PROTOCOL_UNKNOWN);

if(ndpi_str->ndpi_num_custom_protocols == 0) {
Expand Down Expand Up @@ -2318,7 +2318,7 @@ u_int16_t ndpi_network_port_ptree_match(struct ndpi_detection_module_struct *ndp
ndpi_prefix_t prefix;
ndpi_patricia_node_t *node;

if(!ndpi_str->protocols_ptree)
if(!ndpi_str || !ndpi_str->protocols_ptree)
return(NDPI_PROTOCOL_UNKNOWN);

if(ndpi_str->ndpi_num_custom_protocols == 0) {
Expand Down Expand Up @@ -7498,8 +7498,12 @@ void ndpi_parse_packet_line_info_any(struct ndpi_detection_module_struct *ndpi_s

u_int16_t ndpi_check_for_email_address(struct ndpi_detection_module_struct *ndpi_str,
u_int16_t counter) {
struct ndpi_packet_struct *packet = &ndpi_str->packet;
struct ndpi_packet_struct *packet;

if(!ndpi_str)
return(0);

packet = &ndpi_str->packet;
NDPI_LOG_DBG2(ndpi_str, "called ndpi_check_for_email_address\n");

if(packet->payload_packet_len > counter && ((packet->payload[counter] >= 'a' && packet->payload[counter] <= 'z') ||
Expand Down Expand Up @@ -8983,7 +8987,7 @@ const char *ndpi_get_l4_proto_name(ndpi_l4_proto_info proto) {

ndpi_l4_proto_info ndpi_get_l4_proto_info(struct ndpi_detection_module_struct *ndpi_struct,
u_int16_t ndpi_proto_id) {
if(ndpi_proto_id < ndpi_struct->ndpi_num_supported_protocols) {
if(ndpi_struct && ndpi_proto_id < ndpi_struct->ndpi_num_supported_protocols) {
u_int16_t idx = ndpi_struct->proto_defaults[ndpi_proto_id].protoIdx;
NDPI_SELECTION_BITMASK_PROTOCOL_SIZE bm = ndpi_struct->callback_buffer[idx].ndpi_selection_bitmask;

Expand Down
Loading

0 comments on commit 40b6d5a

Please sign in to comment.