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: extend fuzzing coverage #2040

Merged
merged 1 commit into from
Jul 11, 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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@
/fuzz/fuzz_ds_libcache
/fuzz/fuzz_ds_tree
/fuzz/fuzz_ds_ptree
/fuzz/fuzz_ds_hash
/fuzz/fuzz_ds_ahocorasick
/fuzz/fuzz_libinjection
/fuzz/fuzz_tls_certificate
Expand Down
17 changes: 16 additions & 1 deletion fuzz/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ bin_PROGRAMS = fuzz_process_packet fuzz_ndpi_reader fuzz_ndpi_reader_alloc_fail
#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
bin_PROGRAMS += fuzz_ds_patricia fuzz_ds_ahocorasick fuzz_ds_libcache fuzz_ds_tree fuzz_ds_ptree
bin_PROGRAMS += fuzz_ds_patricia fuzz_ds_ahocorasick fuzz_ds_libcache fuzz_ds_tree fuzz_ds_ptree fuzz_ds_hash
#Third party
bin_PROGRAMS += fuzz_libinjection
#Internal crypto
Expand Down Expand Up @@ -294,6 +294,21 @@ fuzz_ds_ptree_LINK=$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CXX) @NDPI_CFLAGS@ $(AM_CXXFLAGS) $(CXXFLAGS) \
$(fuzz_ds_ptree_LDFLAGS) @NDPI_LDFLAGS@ $(LDFLAGS) -o $@

fuzz_ds_hash_SOURCES = fuzz_ds_hash.cpp fuzz_common_code.c
fuzz_ds_hash_CXXFLAGS = @NDPI_CFLAGS@ $(CXXFLAGS) -DENABLE_MEM_ALLOC_FAILURES
fuzz_ds_hash_CFLAGS = @NDPI_CFLAGS@ $(CXXFLAGS)
fuzz_ds_hash_LDADD = ../src/lib/libndpi.a $(ADDITIONAL_LIBS)
fuzz_ds_hash_LDFLAGS = $(LIBS)
if HAS_FUZZLDFLAGS
fuzz_ds_hash_CXXFLAGS += $(LIB_FUZZING_ENGINE)
fuzz_ds_hash_CFLAGS += $(LIB_FUZZING_ENGINE)
fuzz_ds_hash_LDFLAGS += $(LIB_FUZZING_ENGINE)
endif
# force usage of CXX for linker
fuzz_ds_hash_LINK=$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CXX) @NDPI_CFLAGS@ $(AM_CXXFLAGS) $(CXXFLAGS) \
$(fuzz_ds_hash_LDFLAGS) @NDPI_LDFLAGS@ $(LDFLAGS) -o $@

fuzz_libinjection_SOURCES = fuzz_libinjection.c
fuzz_libinjection_CFLAGS = @NDPI_CFLAGS@ $(CXXFLAGS)
fuzz_libinjection_LDADD = ../src/lib/libndpi.a $(ADDITIONAL_LIBS)
Expand Down
10 changes: 8 additions & 2 deletions fuzz/fuzz_alg_hw_rsi_outliers_da.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,12 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
u_int8_t additive_seeasonal;
double alpha, beta, gamma, forecast, confidence_band;
float significance;
u_int32_t *values;
u_int32_t *values, predict_periods;
u_int32_t prediction;
bool *outliers;

/* Use the same (integral) dataset to peform: RSI, Data analysis, HW and outliers */
/* Use the same (integral) dataset to peform: RSI, Data analysis, HW, outliers
and linear regression */

/* Just to have some data */
if(fuzzed_data.remaining_bytes() < 1024)
Expand Down Expand Up @@ -57,6 +59,9 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
max_series_len = fuzzed_data.ConsumeIntegral<u_int16_t>();
a = ndpi_alloc_data_analysis(max_series_len);

/* Init Linear Regression */
predict_periods = fuzzed_data.ConsumeIntegral<u_int8_t>();

/* Calculate! */
for (i = 0; i < num_values; i++) {
if (rc_hw == 0)
Expand All @@ -66,6 +71,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
ndpi_data_add_value(a, values[i]);
}
ndpi_find_outliers(values, outliers, num_values);
ndpi_predict_linear(values, num_values, predict_periods, &prediction);

/* Data analysis stuff */
ndpi_data_average(a);
Expand Down
31 changes: 28 additions & 3 deletions fuzz/fuzz_config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
6 + /* files */
((NDPI_LRUCACHE_MAX + 1) * 5) + /* LRU caches */
2 + 1 + 4 + /* ndpi_set_detection_preferences() */
1 + 3 + 1 + /* Monitoring */
1 + 3 + 1 + 3 + /* Monitoring */
7 + /* Opportunistic tls */
2 + /* Pid */
2 + /* Category */
Expand All @@ -50,6 +50,8 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {

ndpi_info_mod = ndpi_init_detection_module(fuzzed_data.ConsumeIntegral<u_int32_t>());

set_ndpi_debug_function(ndpi_info_mod, NULL);

NDPI_BITMASK_RESET(enabled_bitmask);
for(i = 0; i < NDPI_MAX_SUPPORTED_PROTOCOLS + NDPI_MAX_NUM_CUSTOM_PROTOCOLS ; i++) {
if(fuzzed_data.ConsumeBool())
Expand All @@ -60,6 +62,10 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
ndpi_info_mod = NULL;
}

ndpi_set_user_data(ndpi_info_mod, (void *)0xabcdabcd); /* Random pointer */
ndpi_set_user_data(ndpi_info_mod, (void *)0xabcdabcd); /* Twice to trigger overwriting */
ndpi_get_user_data(ndpi_info_mod);

ndpi_set_tls_cert_expire_days(ndpi_info_mod, fuzzed_data.ConsumeIntegral<u_int8_t>());

if(fuzzed_data.ConsumeBool())
Expand Down Expand Up @@ -99,13 +105,20 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
ndpi_set_detection_preferences(ndpi_info_mod, ndpi_pref_max_packets_to_process,
fuzzed_data.ConsumeIntegralInRange(0, (1 << 16)));

ndpi_set_detection_preferences(ndpi_info_mod, static_cast<ndpi_detection_preference>(0xFF), 0xFF); /* Invalid preference */

if(fuzzed_data.ConsumeBool()) {
ndpi_set_monitoring_state(ndpi_info_mod, NDPI_PROTOCOL_STUN,
fuzzed_data.ConsumeIntegralInRange(0, (1 << 16)),
fuzzed_data.ConsumeIntegralInRange(0, 7));
ndpi_get_monitoring_state(ndpi_info_mod, NDPI_PROTOCOL_STUN, &num, &num2);
}

random_proto = fuzzed_data.ConsumeIntegralInRange(0, (1 << 16) - 1);
random_value = fuzzed_data.ConsumeIntegralInRange(0,2);
ndpi_set_monitoring_state(ndpi_info_mod, random_proto, random_value, random_value);
ndpi_get_monitoring_state(ndpi_info_mod, random_proto, &num, &num2);

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);
ndpi_set_opportunistic_tls(ndpi_info_mod, NDPI_PROTOCOL_MAIL_IMAP, fuzzed_data.ConsumeBool());
Expand All @@ -128,17 +141,24 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
ndpi_finalize_initialization(ndpi_info_mod);

/* Random protocol configuration */
pid = fuzzed_data.ConsumeIntegralInRange<u_int16_t>(0, ndpi_get_num_supported_protocols(ndpi_info_mod) + 1);
pid = fuzzed_data.ConsumeIntegralInRange<u_int16_t>(0, NDPI_MAX_SUPPORTED_PROTOCOLS + NDPI_MAX_NUM_CUSTOM_PROTOCOLS + 1); /* + 1 to trigger invalid pid */
protoname = ndpi_get_proto_by_id(ndpi_info_mod, pid);
if (protoname) {
assert(ndpi_get_proto_by_name(ndpi_info_mod, protoname) == pid);
}
ndpi_map_user_proto_id_to_ndpi_id(ndpi_info_mod, pid);
ndpi_map_ndpi_id_to_user_proto_id(ndpi_info_mod, pid);
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);
ndpi_get_proto_breed(ndpi_info_mod, pid);

ndpi_get_proto_by_name(ndpi_info_mod, NULL); /* Error */
ndpi_get_proto_by_name(ndpi_info_mod, "foo"); /* Invalid protocol */

/* Custom category configuration */
cat = fuzzed_data.ConsumeIntegralInRange(static_cast<int>(NDPI_PROTOCOL_CATEGORY_CUSTOM_1),
static_cast<int>(NDPI_PROTOCOL_CATEGORY_CUSTOM_5 + 1)); /* + 1 to trigger invalid cat */
static_cast<int>(NDPI_PROTOCOL_NUM_CATEGORIES + 1)); /* + 1 to trigger invalid cat */
ndpi_category_set_name(ndpi_info_mod, static_cast<ndpi_protocol_category_t>(cat), catname);
ndpi_is_custom_category(static_cast<ndpi_protocol_category_t>(cat));
ndpi_category_get_name(ndpi_info_mod, static_cast<ndpi_protocol_category_t>(cat));
Expand Down Expand Up @@ -190,6 +210,11 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
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));

ndpi_guess_undetected_protocol_v4(ndpi_info_mod, bool_value ? &flow : NULL,
flow.l4_proto,
flow.c_address.v4, flow.c_port,
flow.s_address.v4, flow.s_port);
}
/* Another "strange" function: fuzz it here, for lack of a better alternative */
ndpi_search_tcp_or_udp(ndpi_info_mod, &flow);
Expand Down
2 changes: 2 additions & 0 deletions fuzz/fuzz_ds_ahocorasick.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
else
mc = NULL;

ac_automata_enable_debug(0);

a = ac_automata_init(mc);
a2 = ndpi_init_automa();

Expand Down
63 changes: 63 additions & 0 deletions fuzz/fuzz_ds_hash.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
#include "ndpi_api.h"
#include "fuzz_common_code.h"

#include <stdint.h>
#include <stdio.h>
#include <assert.h>
#include "fuzzer/FuzzedDataProvider.h"

extern "C" void cleanup_func(ndpi_str_hash *h) {
/* Nothing to do */
return;
}

extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
FuzzedDataProvider fuzzed_data(data, size);
u_int16_t i, rc, num_iteration, data_len, is_added = 0;
std::vector<char>value_added;
void *value;
ndpi_str_hash *h = NULL;

/* Just to have some data */
if (fuzzed_data.remaining_bytes() < 1024)
return -1;

/* To allow memory allocation failures */
fuzz_set_alloc_callbacks_and_seed(size);

if (fuzzed_data.ConsumeBool())
ndpi_hash_init(&h);
else
ndpi_hash_init(NULL);

num_iteration = fuzzed_data.ConsumeIntegral<u_int8_t>();
for (i = 0; i < num_iteration; i++) {

data_len = fuzzed_data.ConsumeIntegralInRange(0, 127);
std::vector<char>data = fuzzed_data.ConsumeBytes<char>(data_len);

rc = ndpi_hash_add_entry(&h, data.data(), data.size(), &i);
/* Keep one random entry really added */
if (rc == 0 && fuzzed_data.ConsumeBool()) {
value_added = data;
is_added = 1;
}
}

/* "Random" search */
num_iteration = fuzzed_data.ConsumeIntegral<u_int8_t>();
for (i = 0; i < num_iteration; i++) {
data_len = fuzzed_data.ConsumeIntegralInRange(0, 127);
std::vector<char>data = fuzzed_data.ConsumeBytes<char>(data_len);

ndpi_hash_find_entry(h, data.data(), data.size(), &value);
}
/* Search of an added entry */
if (is_added) {
ndpi_hash_find_entry(h, value_added.data(), value_added.size(), &value);
}

ndpi_hash_free(&h, cleanup_func);

return 0;
}
4 changes: 2 additions & 2 deletions fuzz/fuzz_ds_patricia.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
if(fuzzed_data.remaining_bytes() > 4) {
std::vector<u_int8_t>data = fuzzed_data.ConsumeBytes<u_int8_t>(4);
ip = data.data();
ip_len = fuzzed_data.ConsumeIntegralInRange(0, 32);
ip_len = fuzzed_data.ConsumeIntegralInRange(0, 33); /* 33 to force error */
ndpi_fill_prefix_v4(&prefix, (struct in_addr *)ip, ip_len, 32);
node = ndpi_patricia_lookup(p, &prefix);
/* Keep one random node really added */
Expand All @@ -71,7 +71,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
if(fuzzed_data.remaining_bytes() > 16) {
std::vector<u_int8_t>data = fuzzed_data.ConsumeBytes<u_int8_t>(16);
ip = data.data();
ip_len = fuzzed_data.ConsumeIntegralInRange(0, 128);
ip_len = fuzzed_data.ConsumeIntegralInRange(0, 129); /* 129 to force error */
ndpi_fill_prefix_v6(&prefix, (const struct in6_addr *)ip, ip_len, 128);
node = ndpi_patricia_lookup(p, &prefix);
/* Keep one random node really added */
Expand Down
26 changes: 7 additions & 19 deletions fuzz/fuzz_libinjection.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,36 +4,24 @@
#include "../src/lib/third_party/include/libinjection_sqli.h"

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

/* No memory allocations involved */

/* Libinjection: it wants null-terminated string */

query = malloc(size + 1);
if (!query)
return 0;
memcpy(query, data, size);
query[size] = '\0';


libinjection_sqli_init(&state, query, strlen(query), 0); /* Default: FLAG_QUOTE_NONE | FLAG_SQL_ANSI */
libinjection_sqli_init(&state, (char *)data, size, 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_sqli_init(&state, (char *)data, size, FLAG_QUOTE_SINGLE | FLAG_SQL_ANSI);
libinjection_is_sqli(&state);
libinjection_sqli_init(&state, query, strlen(query), FLAG_QUOTE_DOUBLE | FLAG_SQL_ANSI);
libinjection_sqli_init(&state, (char *)data, size, FLAG_QUOTE_DOUBLE | FLAG_SQL_ANSI);
libinjection_is_sqli(&state);
libinjection_sqli_init(&state, query, strlen(query), FLAG_QUOTE_NONE | FLAG_SQL_MYSQL);
libinjection_sqli_init(&state, (char *)data, size, FLAG_QUOTE_NONE | FLAG_SQL_MYSQL);
libinjection_is_sqli(&state);
libinjection_sqli_init(&state, query, strlen(query), FLAG_QUOTE_SINGLE | FLAG_SQL_MYSQL);
libinjection_sqli_init(&state, (char *)data, size, FLAG_QUOTE_SINGLE | FLAG_SQL_MYSQL);
libinjection_is_sqli(&state);
libinjection_sqli_init(&state, query, strlen(query), FLAG_QUOTE_DOUBLE | FLAG_SQL_MYSQL);
libinjection_sqli_init(&state, (char *)data, size, FLAG_QUOTE_DOUBLE | FLAG_SQL_MYSQL);
libinjection_is_sqli(&state);

libinjection_xss(query, strlen(query));

free(query);
libinjection_xss((char *)data, size);

libinjection_version();

Expand Down
5 changes: 5 additions & 0 deletions fuzz/fuzz_ndpi_reader.c
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,11 @@ int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
ndpi_load_malicious_ja3_file(workflow->ndpi_struct, "ja3_fingerprints.csv");
ndpi_load_malicious_sha1_file(workflow->ndpi_struct, "sha1_fingerprints.csv");

ndpi_set_detection_preferences(workflow->ndpi_struct, ndpi_pref_enable_tls_block_dissection, 0 /* unused */);

ndpi_set_monitoring_state(workflow->ndpi_struct, NDPI_PROTOCOL_STUN,
10, NDPI_MONITORING_STUN_SUBCLASSIFIED);

memset(workflow->stats.protocol_counter, 0,
sizeof(workflow->stats.protocol_counter));
memset(workflow->stats.protocol_counter_bytes, 0,
Expand Down
Loading
Loading