summaryrefslogtreecommitdiffstats
path: root/src/tests/fuzz/fuzz_applayerprotodetectgetproto.c
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 17:39:49 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 17:39:49 +0000
commita0aa2307322cd47bbf416810ac0292925e03be87 (patch)
tree37076262a026c4b48c8a0e84f44ff9187556ca35 /src/tests/fuzz/fuzz_applayerprotodetectgetproto.c
parentInitial commit. (diff)
downloadsuricata-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.c99
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;
+}