diff --git a/fuzzer/http_endpoint_fingerprint/src/main.cpp b/fuzzer/http_endpoint_fingerprint/src/main.cpp index 6f313e55e..a6dc9fb81 100644 --- a/fuzzer/http_endpoint_fingerprint/src/main.cpp +++ b/fuzzer/http_endpoint_fingerprint/src/main.cpp @@ -45,7 +45,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *bytes, size_t size) processor_cache cache; ddwaf::timer deadline{2s}; auto [output, attr] = gen.eval_impl({{}, {}, false, buffer.get()}, - {{}, {}, false, buffer.get()}, {{}, {}, false, &query}, + {{}, {}, false, buffer.get()}, {{{}, {}, false, &query}}, {{{}, {}, false, &body}}, cache, deadline); ddwaf_object_free(&query); diff --git a/src/processor/fingerprint.cpp b/src/processor/fingerprint.cpp index 2a5d6dd60..61110f1ec 100644 --- a/src/processor/fingerprint.cpp +++ b/src/processor/fingerprint.cpp @@ -553,7 +553,7 @@ std::pair get_header_type_and_index(std::string_view head // NOLINTNEXTLINE(readability-convert-member-functions-to-static) std::pair http_endpoint_fingerprint::eval_impl( const unary_argument &method, const unary_argument &uri_raw, - const unary_argument &query, + const optional_argument &query, const optional_argument &body, processor_cache &cache, ddwaf::timer &deadline) const { @@ -573,7 +573,7 @@ std::pair http_endpoint_fingerprint::eval try { res = generate_fragment_cached("http", cache.fingerprint.fragment_fields, string_field{method.value}, string_hash_field{stripped_uri}, - key_hash_field{query.value}, optional_generator{body}); + optional_generator{query}, optional_generator{body}); } catch (const std::out_of_range &e) { DDWAF_WARN("Failed to generate http endpoint fingerprint: {}", e.what()); } diff --git a/src/processor/fingerprint.hpp b/src/processor/fingerprint.hpp index 13cecb9f2..4f05b2d11 100644 --- a/src/processor/fingerprint.hpp +++ b/src/processor/fingerprint.hpp @@ -26,7 +26,7 @@ class http_endpoint_fingerprint : public structured_processor eval_impl( const unary_argument &method, const unary_argument &uri_raw, - const unary_argument &query, + const optional_argument &query, const optional_argument &body, processor_cache &cache, ddwaf::timer &deadline) const; }; diff --git a/tests/integration/processors/fingerprint/test.cpp b/tests/integration/processors/fingerprint/test.cpp index 8636bc202..ad428e7b4 100644 --- a/tests/integration/processors/fingerprint/test.cpp +++ b/tests/integration/processors/fingerprint/test.cpp @@ -144,10 +144,6 @@ TEST(TestFingerprintIntegration, PostprocessorRegeneration) ddwaf_object map = DDWAF_OBJECT_MAP; ddwaf_object settings = DDWAF_OBJECT_MAP; - ddwaf_object query = DDWAF_OBJECT_MAP; - ddwaf_object_map_add(&query, "key", ddwaf_object_invalid(&tmp)); - ddwaf_object_map_add(&map, "server.request.query", &query); - ddwaf_object_map_add( &map, "server.request.uri.raw", ddwaf_object_string(&tmp, "/path/to/resource/?key=")); ddwaf_object_map_add(&map, "server.request.method", ddwaf_object_string(&tmp, "PuT")); @@ -188,7 +184,7 @@ TEST(TestFingerprintIntegration, PostprocessorRegeneration) EXPECT_EQ(ddwaf_object_size(&out.derivatives), 3); auto derivatives = test::object_to_map(out.derivatives); - EXPECT_STRV(derivatives["_dd.appsec.fp.http.endpoint"], "http-put-729d56c3-2c70e12b-"); + EXPECT_STRV(derivatives["_dd.appsec.fp.http.endpoint"], "http-put-729d56c3--"); EXPECT_STRV(derivatives["_dd.appsec.fp.http.header"], "hdr-1111111111-a441b15f-0-"); EXPECT_STRV(derivatives["_dd.appsec.fp.http.network"], "net-1-1111111111"); @@ -210,6 +206,27 @@ TEST(TestFingerprintIntegration, PostprocessorRegeneration) EXPECT_EQ(ddwaf_object_size(&out.derivatives), 1); + auto derivatives = test::object_to_map(out.derivatives); + EXPECT_STRV(derivatives["_dd.appsec.fp.http.endpoint"], "http-put-729d56c3--2c70e12b"); + + ddwaf_result_free(&out); + } + + { + ddwaf_object tmp; + + ddwaf_object map = DDWAF_OBJECT_MAP; + + ddwaf_object query = DDWAF_OBJECT_MAP; + ddwaf_object_map_add(&query, "key", ddwaf_object_invalid(&tmp)); + ddwaf_object_map_add(&map, "server.request.query", &query); + + ddwaf_result out; + ASSERT_EQ(ddwaf_run(context, &map, nullptr, &out, LONG_TIME), DDWAF_OK); + EXPECT_FALSE(out.timeout); + + EXPECT_EQ(ddwaf_object_size(&out.derivatives), 1); + auto derivatives = test::object_to_map(out.derivatives); EXPECT_STRV( derivatives["_dd.appsec.fp.http.endpoint"], "http-put-729d56c3-2c70e12b-2c70e12b"); @@ -469,10 +486,6 @@ TEST(TestFingerprintIntegration, PreprocessorRegeneration) ddwaf_object map = DDWAF_OBJECT_MAP; ddwaf_object settings = DDWAF_OBJECT_MAP; - ddwaf_object query = DDWAF_OBJECT_MAP; - ddwaf_object_map_add(&query, "key", ddwaf_object_invalid(&tmp)); - ddwaf_object_map_add(&map, "server.request.query", &query); - ddwaf_object_map_add( &map, "server.request.uri.raw", ddwaf_object_string(&tmp, "/path/to/resource/?key=")); ddwaf_object_map_add(&map, "server.request.method", ddwaf_object_string(&tmp, "PuT")); @@ -538,6 +551,24 @@ TEST(TestFingerprintIntegration, PreprocessorRegeneration) ddwaf_result_free(&out); } + { + ddwaf_object tmp; + + ddwaf_object map = DDWAF_OBJECT_MAP; + + ddwaf_object query = DDWAF_OBJECT_MAP; + ddwaf_object_map_add(&query, "key", ddwaf_object_invalid(&tmp)); + ddwaf_object_map_add(&map, "server.request.query", &query); + + ddwaf_result out; + ASSERT_EQ(ddwaf_run(context, &map, nullptr, &out, LONG_TIME), DDWAF_OK); + EXPECT_FALSE(out.timeout); + + EXPECT_EQ(ddwaf_object_size(&out.derivatives), 0); + + ddwaf_result_free(&out); + } + { ddwaf_object tmp; @@ -816,10 +847,6 @@ TEST(TestFingerprintIntegration, ProcessorRegeneration) ddwaf_object map = DDWAF_OBJECT_MAP; ddwaf_object settings = DDWAF_OBJECT_MAP; - ddwaf_object query = DDWAF_OBJECT_MAP; - ddwaf_object_map_add(&query, "key", ddwaf_object_invalid(&tmp)); - ddwaf_object_map_add(&map, "server.request.query", &query); - ddwaf_object_map_add( &map, "server.request.uri.raw", ddwaf_object_string(&tmp, "/path/to/resource/?key=")); ddwaf_object_map_add(&map, "server.request.method", ddwaf_object_string(&tmp, "PuT")); @@ -884,13 +911,34 @@ TEST(TestFingerprintIntegration, ProcessorRegeneration) EXPECT_EQ(ddwaf_object_size(&out.derivatives), 3); auto derivatives = test::object_to_map(out.derivatives); - EXPECT_STRV(derivatives["_dd.appsec.fp.http.endpoint"], "http-put-729d56c3-2c70e12b-"); + EXPECT_STRV(derivatives["_dd.appsec.fp.http.endpoint"], "http-put-729d56c3--"); EXPECT_STRV(derivatives["_dd.appsec.fp.http.header"], "hdr-1111111111-a441b15f-0-"); EXPECT_STRV(derivatives["_dd.appsec.fp.http.network"], "net-1-1111111111"); ddwaf_result_free(&out); } + { + ddwaf_object tmp; + + ddwaf_object map = DDWAF_OBJECT_MAP; + + ddwaf_object query = DDWAF_OBJECT_MAP; + ddwaf_object_map_add(&query, "key", ddwaf_object_invalid(&tmp)); + ddwaf_object_map_add(&map, "server.request.query", &query); + + ddwaf_result out; + ASSERT_EQ(ddwaf_run(context, &map, nullptr, &out, LONG_TIME), DDWAF_OK); + EXPECT_FALSE(out.timeout); + + EXPECT_EQ(ddwaf_object_size(&out.derivatives), 1); + + auto derivatives = test::object_to_map(out.derivatives); + EXPECT_STRV(derivatives["_dd.appsec.fp.http.endpoint"], "http-put-729d56c3-2c70e12b-"); + + ddwaf_result_free(&out); + } + { ddwaf_object tmp; diff --git a/tests/unit/processor/fingerprint_test.cpp b/tests/unit/processor/fingerprint_test.cpp index 39237474b..43c4d26e6 100644 --- a/tests/unit/processor/fingerprint_test.cpp +++ b/tests/unit/processor/fingerprint_test.cpp @@ -37,7 +37,7 @@ TEST(TestHttpEndpointFingerprint, Basic) processor_cache cache; auto [output, attr] = gen.eval_impl({{}, {}, false, "GET"}, {{}, {}, false, "/path/to/whatever?param=hello"}, - {{}, {}, false, &query}, {{{}, {}, false, &body}}, cache, deadline); + {{{}, {}, false, &query}}, {{{}, {}, false, &body}}, cache, deadline); EXPECT_EQ(output.type, DDWAF_OBJ_STRING); EXPECT_EQ(attr, object_store::attribute::none); @@ -70,7 +70,7 @@ TEST(TestHttpEndpointFingerprint, EmptyQuery) processor_cache cache; auto [output, attr] = gen.eval_impl({{}, {}, false, "GET"}, {{}, {}, false, "/path/to/whatever?param=hello"}, - {{}, {}, false, &query}, {{{}, {}, false, &body}}, cache, deadline); + {{{}, {}, false, &query}}, {{{}, {}, false, &body}}, cache, deadline); EXPECT_EQ(output.type, DDWAF_OBJ_STRING); EXPECT_EQ(attr, object_store::attribute::none); @@ -101,7 +101,7 @@ TEST(TestHttpEndpointFingerprint, EmptyBody) processor_cache cache; auto [output, attr] = gen.eval_impl({{}, {}, false, "GET"}, {{}, {}, false, "/path/to/whatever?param=hello"}, - {{}, {}, false, &query}, {{{}, {}, false, &body}}, cache, deadline); + {{{}, {}, false, &query}}, {{{}, {}, false, &body}}, cache, deadline); EXPECT_EQ(output.type, DDWAF_OBJ_STRING); EXPECT_EQ(attr, object_store::attribute::none); @@ -126,7 +126,7 @@ TEST(TestHttpEndpointFingerprint, EmptyEverything) ddwaf::timer deadline{2s}; processor_cache cache; auto [output, attr] = gen.eval_impl({{}, {}, false, ""}, {{}, {}, false, ""}, - {{}, {}, false, &query}, {{{}, {}, false, &body}}, cache, deadline); + {{{}, {}, false, &query}}, {{{}, {}, false, &body}}, cache, deadline); EXPECT_EQ(output.type, DDWAF_OBJ_STRING); EXPECT_EQ(attr, object_store::attribute::none); @@ -161,7 +161,7 @@ TEST(TestHttpEndpointFingerprint, KeyConsistency) processor_cache cache; auto [output, attr] = gen.eval_impl({{}, {}, false, "GET"}, {{}, {}, false, "/path/to/whatever?param=hello"}, - {{}, {}, false, &query}, {{{}, {}, false, &body}}, cache, deadline); + {{{}, {}, false, &query}}, {{{}, {}, false, &body}}, cache, deadline); EXPECT_EQ(output.type, DDWAF_OBJ_STRING); EXPECT_EQ(attr, object_store::attribute::none); @@ -196,7 +196,7 @@ TEST(TestHttpEndpointFingerprint, InvalidQueryType) processor_cache cache; auto [output, attr] = gen.eval_impl({{}, {}, false, "GET"}, {{}, {}, false, "/path/to/whatever?param=hello"}, - {{}, {}, false, &query}, {{{}, {}, false, &body}}, cache, deadline); + {{{}, {}, false, &query}}, {{{}, {}, false, &body}}, cache, deadline); EXPECT_EQ(output.type, DDWAF_OBJ_STRING); EXPECT_EQ(attr, object_store::attribute::none); @@ -231,7 +231,7 @@ TEST(TestHttpEndpointFingerprint, InvalidBodyType) processor_cache cache; auto [output, attr] = gen.eval_impl({{}, {}, false, "GET"}, {{}, {}, false, "/path/to/whatever?param=hello"}, - {{}, {}, false, &query}, {{{}, {}, false, &body}}, cache, deadline); + {{{}, {}, false, &query}}, {{{}, {}, false, &body}}, cache, deadline); EXPECT_EQ(output.type, DDWAF_OBJ_STRING); EXPECT_EQ(attr, object_store::attribute::none); @@ -266,7 +266,7 @@ TEST(TestHttpEndpointFingerprint, InvalidQueryAndBodyType) processor_cache cache; auto [output, attr] = gen.eval_impl({{}, {}, false, "GET"}, {{}, {}, false, "/path/to/whatever?param=hello"}, - {{}, {}, false, &query}, {{{}, {}, false, &body}}, cache, deadline); + {{{}, {}, false, &query}}, {{{}, {}, false, &body}}, cache, deadline); EXPECT_EQ(output.type, DDWAF_OBJ_STRING); EXPECT_EQ(attr, object_store::attribute::none); @@ -301,7 +301,7 @@ TEST(TestHttpEndpointFingerprint, UriRawConsistency) processor_cache cache; auto [output, attr] = gen.eval_impl({{}, {}, false, "GET"}, {{}, {}, false, "/path/to/whatever?param=hello"}, - {{}, {}, false, &query}, {{{}, {}, false, &body}}, cache, deadline); + {{{}, {}, false, &query}}, {{{}, {}, false, &body}}, cache, deadline); EXPECT_EQ(output.type, DDWAF_OBJ_STRING); EXPECT_EQ(attr, object_store::attribute::none); @@ -316,7 +316,7 @@ TEST(TestHttpEndpointFingerprint, UriRawConsistency) processor_cache cache; auto [output, attr] = gen.eval_impl({{}, {}, false, "GET"}, {{}, {}, false, "/path/to/whatever#fragment"}, - {{}, {}, false, &query}, {{{}, {}, false, &body}}, cache, deadline); + {{{}, {}, false, &query}}, {{{}, {}, false, &body}}, cache, deadline); EXPECT_EQ(output.type, DDWAF_OBJ_STRING); EXPECT_EQ(attr, object_store::attribute::none); @@ -330,7 +330,7 @@ TEST(TestHttpEndpointFingerprint, UriRawConsistency) ddwaf::timer deadline{2s}; processor_cache cache; auto [output, attr] = gen.eval_impl({{}, {}, false, "GET"}, - {{}, {}, false, "/path/to/whatever?param=hello#fragment"}, {{}, {}, false, &query}, + {{}, {}, false, "/path/to/whatever?param=hello#fragment"}, {{{}, {}, false, &query}}, {{{}, {}, false, &body}}, cache, deadline); EXPECT_EQ(output.type, DDWAF_OBJ_STRING); EXPECT_EQ(attr, object_store::attribute::none); @@ -346,7 +346,7 @@ TEST(TestHttpEndpointFingerprint, UriRawConsistency) processor_cache cache; auto [output, attr] = gen.eval_impl({{}, {}, false, "GET"}, {{}, {}, false, "/path/to/whatever"}, - {{}, {}, false, &query}, {{{}, {}, false, &body}}, cache, deadline); + {{{}, {}, false, &query}}, {{{}, {}, false, &body}}, cache, deadline); EXPECT_EQ(output.type, DDWAF_OBJ_STRING); EXPECT_EQ(attr, object_store::attribute::none); @@ -361,7 +361,7 @@ TEST(TestHttpEndpointFingerprint, UriRawConsistency) processor_cache cache; auto [output, attr] = gen.eval_impl({{}, {}, false, "GET"}, {{}, {}, false, "/PaTh/To/WhAtEVER"}, - {{}, {}, false, &query}, {{{}, {}, false, &body}}, cache, deadline); + {{{}, {}, false, &query}}, {{{}, {}, false, &body}}, cache, deadline); EXPECT_EQ(output.type, DDWAF_OBJ_STRING); EXPECT_EQ(attr, object_store::attribute::none); @@ -392,7 +392,7 @@ TEST(TestHttpEndpointFingerprint, Regeneration) ddwaf::timer deadline{2s}; auto [output, attr] = gen.eval_impl({{}, {}, false, "GET"}, {{}, {}, false, "/path/to/whatever?param=hello"}, - {{}, {}, false, &query}, std::nullopt, cache, deadline); + {{{}, {}, false, &query}}, std::nullopt, cache, deadline); EXPECT_EQ(output.type, DDWAF_OBJ_STRING); EXPECT_EQ(attr, object_store::attribute::none); @@ -414,7 +414,7 @@ TEST(TestHttpEndpointFingerprint, Regeneration) ddwaf::timer deadline{2s}; auto [output, attr] = gen.eval_impl({{}, {}, false, "GET"}, {{}, {}, false, "/path/to/whatever?param=hello"}, - {{}, {}, false, &query}, {{{}, {}, false, &body}}, cache, deadline); + {{{}, {}, false, &query}}, {{{}, {}, false, &body}}, cache, deadline); EXPECT_EQ(output.type, DDWAF_OBJ_STRING); EXPECT_EQ(attr, object_store::attribute::none);