diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 17:39:49 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 17:39:49 +0000 |
commit | a0aa2307322cd47bbf416810ac0292925e03be87 (patch) | |
tree | 37076262a026c4b48c8a0e84f44ff9187556ca35 /src/tests/fuzz/fuzz_applayerprotodetectgetproto.c | |
parent | Initial commit. (diff) | |
download | suricata-a0aa2307322cd47bbf416810ac0292925e03be87.tar.xz suricata-a0aa2307322cd47bbf416810ac0292925e03be87.zip |
Adding upstream version 1:7.0.3.upstream/1%7.0.3
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/tests/fuzz/fuzz_applayerprotodetectgetproto.c')
-rw-r--r-- | src/tests/fuzz/fuzz_applayerprotodetectgetproto.c | 99 |
1 files changed, 99 insertions, 0 deletions
diff --git a/src/tests/fuzz/fuzz_applayerprotodetectgetproto.c b/src/tests/fuzz/fuzz_applayerprotodetectgetproto.c new file mode 100644 index 0000000..598e7cc --- /dev/null +++ b/src/tests/fuzz/fuzz_applayerprotodetectgetproto.c @@ -0,0 +1,99 @@ +/** + * @file + * @author Philippe Antoine <contact@catenacyber.fr> + * fuzz target for AppLayerProtoDetectGetProto + */ + + +#include "suricata-common.h" +#include "suricata.h" +#include "app-layer-detect-proto.h" +#include "flow-util.h" +#include "app-layer-parser.h" +#include "util-unittest-helper.h" +#include "conf-yaml-loader.h" + +#define HEADER_LEN 6 + +//rule of thumb constant, so as not to timeout target +#define PROTO_DETECT_MAX_LEN 1024 + +#include "confyaml.c" + +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size); + +AppLayerProtoDetectThreadCtx *alpd_tctx = NULL; +SC_ATOMIC_EXTERN(unsigned int, engine_stage); + +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + Flow *f; + TcpSession ssn; + bool reverse; + AppProto alproto; + AppProto alproto2; + + if (alpd_tctx == NULL) { + //global init + InitGlobal(); + run_mode = RUNMODE_UNITTEST; + if (ConfYamlLoadString(configNoChecksum, strlen(configNoChecksum)) != 0) { + abort(); + } + MpmTableSetup(); + SpmTableSetup(); + EngineModeSetIDS(); + AppLayerProtoDetectSetup(); + AppLayerParserSetup(); + AppLayerParserRegisterProtocolParsers(); + alpd_tctx = AppLayerProtoDetectGetCtxThread(); + SC_ATOMIC_SET(engine_stage, SURICATA_RUNTIME); + } + + if (size < HEADER_LEN) { + return 0; + } + + f = TestHelperBuildFlow(AF_INET, "1.2.3.4", "5.6.7.8", (uint16_t)((data[2] << 8) | data[3]), + (uint16_t)((data[4] << 8) | data[5])); + if (f == NULL) { + return 0; + } + f->proto = data[1]; + memset(&ssn, 0, sizeof(TcpSession)); + f->protoctx = &ssn; + f->protomap = FlowGetProtoMapping(f->proto); + + uint8_t flags = STREAM_TOCLIENT; + if (data[0] & STREAM_TOSERVER) { + flags = STREAM_TOSERVER; + } + alproto = AppLayerProtoDetectGetProto( + alpd_tctx, f, data + HEADER_LEN, size - HEADER_LEN, f->proto, flags, &reverse); + if (alproto != ALPROTO_UNKNOWN && alproto != ALPROTO_FAILED && f->proto == IPPROTO_TCP) { + /* If we find a valid protocol at the start of a stream : + * check that with smaller input + * we find the same protocol or ALPROTO_UNKNOWN. + * Otherwise, we have evasion with TCP splitting + */ + for (size_t i = 0; i < size-HEADER_LEN && i < PROTO_DETECT_MAX_LEN; i++) { + // reset detection at each try cf probing_parser_toserver_alproto_masks + AppLayerProtoDetectReset(f); + alproto2 = AppLayerProtoDetectGetProto( + alpd_tctx, f, data + HEADER_LEN, i, f->proto, flags, &reverse); + if (alproto2 != ALPROTO_UNKNOWN && alproto2 != alproto) { + printf("Failed with input length %" PRIuMAX " versus %" PRIuMAX + ", found %s instead of %s\n", + (uintmax_t)i, (uintmax_t)size - HEADER_LEN, AppProtoToString(alproto2), + AppProtoToString(alproto)); + printf("Assertion failure: %s-%s\n", AppProtoToString(alproto2), + AppProtoToString(alproto)); + fflush(stdout); + abort(); + } + } + } + FlowFree(f); + + return 0; +} |