Skip to content

Commit

Permalink
fuzz: improve fuzzing coverage
Browse files Browse the repository at this point in the history
Remove some code never triggered

AFP: the removed check is included in the following one
MQTT: fix flags extraction
  • Loading branch information
IvanNardi committed Jun 17, 2024
1 parent bbe52da commit b6c54fc
Show file tree
Hide file tree
Showing 19 changed files with 97 additions and 66 deletions.
2 changes: 1 addition & 1 deletion example/reader_util.c
Original file line number Diff line number Diff line change
Expand Up @@ -1353,7 +1353,7 @@ void process_ndpi_collected_info(struct ndpi_workflow * workflow, struct ndpi_fl
flow->detected_protocol,
&flow->ndpi_flow_serializer) != 0) {
LOG(NDPI_LOG_ERROR, "flow2json failed\n");
exit(-1);
return;
}

ndpi_serialize_string_uint32(&flow->ndpi_flow_serializer, "detection_completed", flow->detection_completed);
Expand Down
Binary file not shown.
16 changes: 13 additions & 3 deletions fuzz/fuzz_alg_shoco.cpp
Original file line number Diff line number Diff line change
@@ -1,22 +1,32 @@
#include <stdint.h>
#include "shoco.h"
#include "ndpi_api.h"
#include "fuzzer/FuzzedDataProvider.h"

extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
FuzzedDataProvider fuzzed_data(data, size);
const char *in;
size_t in_len, out_len;
char out[8192], orig[8192];
int higher_level_api;

/* No memory allocations involved */

higher_level_api = fuzzed_data.ConsumeBool();

std::string s = fuzzed_data.ConsumeRemainingBytesAsString().c_str();
in = s.c_str();
in_len = strlen(in);

out_len = shoco_compress(in, in_len, out, sizeof(out));
if(out_len <= sizeof(out)) /* No error */
shoco_decompress(out, out_len, orig, sizeof(orig));
if(!higher_level_api) {
out_len = shoco_compress(in, in_len, out, sizeof(out));
if(out_len <= sizeof(out)) /* No error */
shoco_decompress(out, out_len, orig, sizeof(orig));
} else {
out_len = ndpi_compress_str(in, in_len, out, sizeof(out));
if(out_len != 0) /* No error */
ndpi_decompress_str(out, out_len, orig, sizeof(orig));
}

return 0;
}
7 changes: 6 additions & 1 deletion fuzz/fuzz_config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -518,6 +518,12 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
ndpi_severity2str(static_cast<ndpi_risk_severity>(fuzzed_data.ConsumeIntegral<u_int8_t>()));
ndpi_risk2score(static_cast<ndpi_risk_enum>(fuzzed_data.ConsumeIntegral<u_int64_t>()), &unused1, &unused2);
ndpi_http_method2str(static_cast<ndpi_http_method>(fuzzed_data.ConsumeIntegral<u_int8_t>()));
ndpi_confidence_get_name(static_cast<ndpi_confidence_t>(fuzzed_data.ConsumeIntegral<u_int8_t>()));
ndpi_get_proto_breed_name(static_cast<ndpi_protocol_breed_t>(fuzzed_data.ConsumeIntegral<u_int8_t>()));
ndpi_get_l4_proto_name(static_cast<ndpi_l4_proto_info>(fuzzed_data.ConsumeIntegral<u_int8_t>()));

char buf2[16];
ndpi_entropy2str(fuzzed_data.ConsumeFloatingPoint<float>(), fuzzed_data.ConsumeBool() ? buf2 : NULL, sizeof(buf2));

/* Basic code to try testing this "config" */
bool_value = fuzzed_data.ConsumeBool();
Expand Down Expand Up @@ -545,7 +551,6 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
ndpi_get_flow_ndpi_proto(&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(p.app_protocol);
ndpi_get_http_method(bool_value ? &flow : NULL);
ndpi_get_http_url(&flow);
Expand Down
5 changes: 4 additions & 1 deletion fuzz/fuzz_ds_ahocorasick.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,10 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
ac_automata_enable_debug(0);

a = ac_automata_init(mc);
a2 = ndpi_init_automa();
if (fuzzed_data.ConsumeBool())
a2 = ndpi_init_automa();
else
a2 = ndpi_init_automa_domain();

if (fuzzed_data.ConsumeBool())
ac_automata_feature(a, AC_FEATURE_DEBUG);
Expand Down
2 changes: 1 addition & 1 deletion fuzz/fuzz_ds_domain_classify.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
num_iteration = fuzzed_data.ConsumeIntegral<u_int8_t>();
for (i = 0; i < num_iteration; i++) {
value = fuzzed_data.ConsumeBytesAsString(fuzzed_data.ConsumeIntegral<u_int8_t>());
ndpi_domain_classify_hostname(ndpi_struct, d, &class_id, (char *)value.c_str());
ndpi_domain_classify_hostname(fuzzed_data.ConsumeBool() ? ndpi_struct : NULL, d, &class_id, (char *)value.c_str());
}

/* Search of an added entry */
Expand Down
8 changes: 8 additions & 0 deletions fuzz/fuzz_gcrypt_cipher.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#define MBEDTLS_CHECK_RETURN_TYPICAL
#define MBEDTLS_INTERNAL_VALIDATE_RET( cond, ret ) do { } while( 0 )
#include "gcrypt/cipher.h"
#include "gcrypt/error.h"
#include "gcrypt/aes.h"

extern int force_no_aesni;
Expand Down Expand Up @@ -56,10 +57,17 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
mbedtls_cipher_info_get_type(ctx_e->cipher_info);
mbedtls_cipher_info_get_name(ctx_e->cipher_info);
mbedtls_cipher_info_has_variable_key_bitlen(ctx_e->cipher_info);
mbedtls_cipher_info_has_variable_iv_size(ctx_e->cipher_info);
mbedtls_cipher_info_get_iv_size(ctx_e->cipher_info);
mbedtls_cipher_info_get_block_size(ctx_e->cipher_info);
mbedtls_cipher_get_cipher_mode(ctx_e);
mbedtls_cipher_get_iv_size(ctx_e);
mbedtls_cipher_get_type(ctx_e);
mbedtls_cipher_get_name(ctx_e);
mbedtls_cipher_get_key_bitlen(ctx_e);
mbedtls_cipher_get_operation(ctx_e);
mbedtls_cipher_info_get_key_bitlen(ctx_e->cipher_info);
mbedtls_error_add(0, 0, NULL, 0);

posix_memalign((void **)&ctx_e->cipher_ctx, 8, sizeof(mbedtls_aes_context));
posix_memalign((void **)&ctx_d->cipher_ctx, 8, sizeof(mbedtls_aes_context));
Expand Down
6 changes: 5 additions & 1 deletion fuzz/fuzz_ndpi_reader.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ struct ndpi_global_context *g_ctx;
u_int8_t enable_payload_analyzer = 0;
u_int8_t enable_flow_stats = 1;
u_int8_t human_readeable_string_len = 5;
u_int8_t max_num_udp_dissected_pkts = 16 /* 8 is enough for most protocols, Signal requires more */, max_num_tcp_dissected_pkts = 80 /* due to telnet */;
u_int8_t max_num_udp_dissected_pkts = 0, max_num_tcp_dissected_pkts = 0; /* Disable limits at application layer */;
int malloc_size_stats = 0;

extern void ndpi_report_payload_stats(FILE *out);
Expand Down Expand Up @@ -53,6 +53,8 @@ int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {

workflow = ndpi_workflow_init(prefs, NULL /* pcap handler will be set later */, 0, ndpi_serialization_format_json, g_ctx);

ndpi_workflow_set_flow_callback(workflow, NULL, NULL); /* No real callback */

ndpi_set_config(workflow->ndpi_struct, NULL, "log.level", "3");
ndpi_set_config(workflow->ndpi_struct, "all", "log", "1");

Expand All @@ -68,10 +70,12 @@ int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
NDPI_BITMASK_SET_ALL(all);
ndpi_set_protocol_detection_bitmask2(workflow->ndpi_struct, &all);

ndpi_set_config(workflow->ndpi_struct, NULL, "packets_limit_per_flow", "255");
ndpi_set_config(workflow->ndpi_struct, NULL, "flow.track_payload", "1");
ndpi_set_config(workflow->ndpi_struct, NULL, "tcp_ack_payload_heuristic", "1");
ndpi_set_config(workflow->ndpi_struct, "tls", "application_blocks_tracking", "1");
ndpi_set_config(workflow->ndpi_struct, "stun", "max_packets_extra_dissection", "255");
ndpi_set_config(workflow->ndpi_struct, "zoom", "max_packets_extra_dissection", "255");
ndpi_set_config(workflow->ndpi_struct, "rtp", "search_for_stun", "1");

ndpi_finalize_initialization(workflow->ndpi_struct);
Expand Down
24 changes: 14 additions & 10 deletions fuzz/fuzz_serialization.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
int rc;
std::vector<char>d;
char kbuf[32];
u_int32_t buffer_len;
u_int32_t buffer_len, kbuf_len;

/* To allow memory allocation failures */
fuzz_set_alloc_callbacks_and_seed(size);
Expand Down Expand Up @@ -66,19 +66,23 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
ndpi_serialize_string_raw(&serializer, kbuf, d.data(), d.size());
ndpi_serialize_string_boolean(&serializer, kbuf, fuzzed_data.ConsumeIntegral<int8_t>());

if (fuzzed_data.ConsumeBool())
if (fuzzed_data.ConsumeBool()) {
snprintf(kbuf, sizeof(kbuf), "%d", i); /* To trigger OPTIMIZE_NUMERIC_KEYS */
ndpi_serialize_binary_uint32(&serializer, kbuf, sizeof(kbuf), fuzzed_data.ConsumeIntegral<u_int32_t>());
ndpi_serialize_binary_int32(&serializer, kbuf, sizeof(kbuf), fuzzed_data.ConsumeIntegral<int32_t>());
ndpi_serialize_binary_uint64(&serializer, kbuf, sizeof(kbuf), fuzzed_data.ConsumeIntegral<u_int64_t>());
ndpi_serialize_binary_int64(&serializer, kbuf, sizeof(kbuf), fuzzed_data.ConsumeIntegral<int64_t>());
ndpi_serialize_binary_float(&serializer, kbuf, sizeof(kbuf), fuzzed_data.ConsumeFloatingPoint<float>(), "%f");
kbuf_len = strlen(kbuf);
} else {
kbuf_len = sizeof(kbuf);
}
ndpi_serialize_binary_uint32(&serializer, kbuf, kbuf_len, fuzzed_data.ConsumeIntegral<u_int32_t>());
ndpi_serialize_binary_int32(&serializer, kbuf, kbuf_len, fuzzed_data.ConsumeIntegral<int32_t>());
ndpi_serialize_binary_uint64(&serializer, kbuf, kbuf_len, fuzzed_data.ConsumeIntegral<u_int64_t>());
ndpi_serialize_binary_int64(&serializer, kbuf, kbuf_len, fuzzed_data.ConsumeIntegral<int64_t>());
ndpi_serialize_binary_float(&serializer, kbuf, kbuf_len, fuzzed_data.ConsumeFloatingPoint<float>(), "%f");
if (fmt != ndpi_serialization_format_tlv)
ndpi_serialize_binary_double(&serializer, kbuf, sizeof(kbuf), fuzzed_data.ConsumeFloatingPoint<double>(), "%lf");
ndpi_serialize_binary_boolean(&serializer, kbuf, sizeof(kbuf), fuzzed_data.ConsumeIntegral<int8_t>());
ndpi_serialize_binary_double(&serializer, kbuf, kbuf_len, fuzzed_data.ConsumeFloatingPoint<double>(), "%lf");
ndpi_serialize_binary_boolean(&serializer, kbuf, kbuf_len, fuzzed_data.ConsumeIntegral<int8_t>());
d = fuzzed_data.ConsumeBytes<char>(16);
if (d.size())
ndpi_serialize_binary_binary(&serializer, kbuf, sizeof(kbuf), d.data(), d.size());
ndpi_serialize_binary_binary(&serializer, kbuf, kbuf_len, d.data(), d.size());

if ((i & 0x3) == 0x3)
ndpi_serialize_end_of_record(&serializer);
Expand Down
2 changes: 1 addition & 1 deletion src/lib/ndpi_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -4976,7 +4976,7 @@ int load_category_file_fd(struct ndpi_detection_module_struct *ndpi_str,
continue;
}

if(ndpi_load_category(ndpi_str, line, category_id, NULL) > 0)
if(ndpi_load_category(ndpi_str, line, category_id, NULL) >= 0)
num_loaded++;
}

Expand Down
14 changes: 0 additions & 14 deletions src/lib/protocols/afp.c
Original file line number Diff line number Diff line change
Expand Up @@ -62,20 +62,6 @@ static void ndpi_search_afp(struct ndpi_detection_module_struct *ndpi_struct, st
return;
}

/*
* this will detect the OpenSession command of the Data Stream Interface (DSI) protocol
* which is exclusively used by the Apple Filing Protocol (AFP) on TCP/IP networks
*/
if (packet->payload_packet_len >= 22 && get_u_int16_t(packet->payload, 0) == htons(0x0004) &&
get_u_int16_t(packet->payload, 2) == htons(0x0001) && get_u_int32_t(packet->payload, 4) == 0 &&
get_u_int32_t(packet->payload, 8) == htonl(packet->payload_packet_len - 16) &&
get_u_int32_t(packet->payload, 12) == 0 && get_u_int16_t(packet->payload, 16) == htons(0x0104)) {

NDPI_LOG_INFO(ndpi_struct, "found AFP: DSI OpenSession\n");
ndpi_int_afp_add_connection(ndpi_struct, flow);
return;
}

if((h->flags <= 1)
&& ((h->command >= 1) && (h->command <= 8))
&& (h->reserved == 0)
Expand Down
9 changes: 2 additions & 7 deletions src/lib/protocols/mqtt.c
Original file line number Diff line number Diff line change
Expand Up @@ -179,18 +179,13 @@ static void ndpi_search_mqtt(struct ndpi_detection_module_struct *ndpi_struct,
}
if (pt == PUBLISH) {
// payload CAN be zero bytes length (section 3.3.3 of MQTT standard)
u_int8_t qos = (u_int8_t) (flags & 0x06);
u_int8_t dup = (u_int8_t) (flags & 0x04);
u_int8_t qos = (u_int8_t) (flags & 0x06) >> 1;
u_int8_t dup = (u_int8_t) (flags & 0x08) >> 3;
if (qos > 2) { // qos values possible are 0,1,2
NDPI_LOG_DBG(ndpi_struct, "Excluding Mqtt invalid PUBLISH qos\n");
NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_MQTT);
return;
}
if (dup > 1) { // dup flag possible 0,1
NDPI_LOG_DBG(ndpi_struct, "Excluding Mqtt invalid PUBLISH dup\n");
NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_MQTT);
return;
}
if (qos == 0) {
if (dup != 0) {
NDPI_LOG_DBG(ndpi_struct, "Excluding Mqtt invalid PUBLISH qos0 and dup combination\n");
Expand Down
5 changes: 1 addition & 4 deletions src/lib/protocols/ssdp.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,7 @@ static void ssdp_parse_lines(struct ndpi_detection_module_struct

/* Save host which provides a service if available */
if (packet->host_line.ptr != NULL && packet->host_line.len > 0) {
if (ndpi_hostname_sni_set(flow, packet->host_line.ptr, packet->host_line.len, NDPI_HOSTNAME_NORM_ALL) == NULL)
{
NDPI_LOG_DBG2(ndpi_struct, "Could not set SSDP host\n");
}
ndpi_hostname_sni_set(flow, packet->host_line.ptr, packet->host_line.len, NDPI_HOSTNAME_NORM_ALL);
}
}

Expand Down
3 changes: 0 additions & 3 deletions src/lib/protocols/thrift.c
Original file line number Diff line number Diff line change
Expand Up @@ -83,9 +83,6 @@ static void ndpi_int_thrift_add_connection(struct ndpi_detection_module_struct *
case NDPI_PROTOCOL_HTTP:
NDPI_LOG_DBG(ndpi_struct, "found Apache Thrift HTTP\n");
break;
default:
NDPI_LOG_DBG(ndpi_struct, "found Apache Thrift\n");
break;
}

ndpi_set_detected_protocol(ndpi_struct, flow,
Expand Down
5 changes: 0 additions & 5 deletions src/lib/protocols/tls.c
Original file line number Diff line number Diff line change
Expand Up @@ -1032,10 +1032,6 @@ static int ndpi_search_tls_tcp(struct ndpi_detection_module_struct *ndpi_struct,
break;
}

if(len == 0) {
something_went_wrong = 1;
break;
}

#ifdef DEBUG_TLS_MEMORY
printf("[TLS Mem] Processing %u bytes message\n", len);
Expand Down Expand Up @@ -1638,7 +1634,6 @@ static bool is_grease_version(u_int16_t version) {
case 0xeaea:
case 0xfafa:
return(true);
break;

default:
return(false);
Expand Down
Binary file modified tests/cfgs/default/pcap/netbios.pcap
Binary file not shown.
Binary file added tests/cfgs/default/pcap/pgsql2.pcapng
Binary file not shown.
Loading

0 comments on commit b6c54fc

Please sign in to comment.