diff --git a/src/detect-engine-register.h b/src/detect-engine-register.h index 7acec2f211..4077d9113a 100644 --- a/src/detect-engine-register.h +++ b/src/detect-engine-register.h @@ -131,6 +131,7 @@ enum { DETECT_AL_HTTP_HEADER_CONTENT_TYPE, DETECT_AL_HTTP_HEADER_REFERER, DETECT_AL_HTTP_RAW_HEADER, + DETECT_HTTP_RAW_HEADER, DETECT_AL_HTTP_URI, DETECT_HTTP_URI, DETECT_HTTP_URI_RAW, diff --git a/src/detect-http-raw-header.c b/src/detect-http-raw-header.c index e6318668a1..9f36db7112 100644 --- a/src/detect-http-raw-header.c +++ b/src/detect-http-raw-header.c @@ -53,6 +53,7 @@ #include "detect-http-raw-header.h" static int DetectHttpRawHeaderSetup(DetectEngineCtx *, Signature *, const char *); +static int DetectHttpRawHeaderSetupSticky(DetectEngineCtx *de_ctx, Signature *s, const char *str); #ifdef UNITTESTS static void DetectHttpRawHeaderRegisterTests(void); #endif @@ -74,12 +75,22 @@ static int PrefilterMpmHttpHeaderRawResponseRegister(DetectEngineCtx *de_ctx, */ void DetectHttpRawHeaderRegister(void) { + /* http_raw_header content modifier */ sigmatch_table[DETECT_AL_HTTP_RAW_HEADER].name = "http_raw_header"; sigmatch_table[DETECT_AL_HTTP_RAW_HEADER].Setup = DetectHttpRawHeaderSetup; #ifdef UNITTESTS sigmatch_table[DETECT_AL_HTTP_RAW_HEADER].RegisterTests = DetectHttpRawHeaderRegisterTests; #endif sigmatch_table[DETECT_AL_HTTP_RAW_HEADER].flags |= SIGMATCH_NOOPT; + sigmatch_table[DETECT_AL_HTTP_RAW_HEADER].alternative = DETECT_HTTP_RAW_HEADER; + + /* http.header.raw sticky buffer */ + sigmatch_table[DETECT_HTTP_RAW_HEADER].name = "http.header.raw"; + sigmatch_table[DETECT_HTTP_RAW_HEADER].desc = "sticky buffer to match the raw HTTP header buffer"; + sigmatch_table[DETECT_HTTP_RAW_HEADER].url = DOC_URL DOC_VERSION "/rules/http-keywords.html#http-raw-header"; + sigmatch_table[DETECT_HTTP_RAW_HEADER].Setup = DetectHttpRawHeaderSetupSticky; + sigmatch_table[DETECT_HTTP_RAW_HEADER].flags |= SIGMATCH_NOOPT; + sigmatch_table[DETECT_HTTP_RAW_HEADER].flags |= SIGMATCH_INFO_STICKY_BUFFER; DetectAppLayerInspectEngineRegister2("http_raw_header", ALPROTO_HTTP, SIG_FLAG_TOSERVER, HTP_REQUEST_HEADERS+1, @@ -125,6 +136,24 @@ int DetectHttpRawHeaderSetup(DetectEngineCtx *de_ctx, Signature *s, const char * ALPROTO_HTTP); } +/** + * \brief this function setup the http.header.raw keyword used in the rule + * + * \param de_ctx Pointer to the Detection Engine Context + * \param s Pointer to the Signature to which the current keyword belongs + * \param str Should hold an empty string always + * + * \retval 0 On success + */ +static int DetectHttpRawHeaderSetupSticky(DetectEngineCtx *de_ctx, Signature *s, const char *str) +{ + if (DetectBufferSetActiveList(s, g_http_raw_header_buffer_id) < 0) + return -1; + if (DetectSignatureSetAppProto(s, ALPROTO_HTTP) < 0) + return -1; + return 0; +} + static _Bool DetectHttpRawHeaderValidateCallback(const Signature *s, const char **sigerror) { if ((s->flags & (SIG_FLAG_TOCLIENT|SIG_FLAG_TOSERVER)) == (SIG_FLAG_TOCLIENT|SIG_FLAG_TOSERVER)) { diff --git a/src/tests/detect-http-raw-header.c b/src/tests/detect-http-raw-header.c index dee84cdc74..283d8010c7 100644 --- a/src/tests/detect-http-raw-header.c +++ b/src/tests/detect-http-raw-header.c @@ -54,6 +54,41 @@ #ifdef UNITTESTS +/** + * \test Test parser accepting valid rules and rejecting invalid rules + */ +static int DetectHttpRawHeaderParserTest01(void) +{ + FAIL_IF_NOT(UTHParseSignature("alert http any any -> any any (flow:to_server; content:\"abc\"; http_raw_header; sid:1;)", true)); + FAIL_IF_NOT(UTHParseSignature("alert http any any -> any any (flow:to_server; content:\"abc\"; nocase; http_raw_header; sid:1;)", true)); + FAIL_IF_NOT(UTHParseSignature("alert http any any -> any any (flow:to_server; content:\"abc\"; endswith; http_raw_header; sid:1;)", true)); + FAIL_IF_NOT(UTHParseSignature("alert http any any -> any any (flow:to_server; content:\"abc\"; startswith; http_raw_header; sid:1;)", true)); + FAIL_IF_NOT(UTHParseSignature("alert http any any -> any any (flow:to_server; content:\"abc\"; startswith; endswith; http_raw_header; sid:1;)", true)); + + FAIL_IF_NOT(UTHParseSignature("alert http any any -> any any (flow:to_server; content:\"abc\"; rawbytes; http_raw_header; sid:1;)", false)); + FAIL_IF_NOT(UTHParseSignature("alert tcp any any -> any any (flow:to_server; http_raw_header; sid:1;)", false)); + FAIL_IF_NOT(UTHParseSignature("alert tls any any -> any any (flow:to_server; content:\"abc\"; http_raw_header; sid:1;)", false)); + PASS; +} + +/** + * \test Test parser accepting valid rules and rejecting invalid rules + */ +static int DetectHttpRawHeaderParserTest02(void) +{ + FAIL_IF_NOT(UTHParseSignature("alert http any any -> any any (flow:to_server; http.header.raw; content:\"abc\"; sid:1;)", true)); + FAIL_IF_NOT(UTHParseSignature("alert http any any -> any any (flow:to_server; http.header.raw; content:\"abc\"; nocase; sid:1;)", true)); + FAIL_IF_NOT(UTHParseSignature("alert http any any -> any any (flow:to_server; http.header.raw; content:\"abc\"; endswith; sid:1;)", true)); + FAIL_IF_NOT(UTHParseSignature("alert http any any -> any any (flow:to_server; http.header.raw; content:\"abc\"; startswith; sid:1;)", true)); + FAIL_IF_NOT(UTHParseSignature("alert http any any -> any any (flow:to_server; http.header.raw; content:\"abc\"; startswith; endswith; sid:1;)", true)); + FAIL_IF_NOT(UTHParseSignature("alert http any any -> any any (flow:to_server; http.header.raw; bsize:10; sid:1;)", true)); + + FAIL_IF_NOT(UTHParseSignature("alert http any any -> any any (flow:to_server; http.header.raw; content:\"abc\"; rawbytes; sid:1;)", false)); + FAIL_IF_NOT(UTHParseSignature("alert tcp any any -> any any (flow:to_server; http.header.raw; sid:1;)", false)); + FAIL_IF_NOT(UTHParseSignature("alert tls any any -> any any (flow:to_server; http.header.raw; content:\"abc\"; sid:1;)", false)); + PASS; +} + /** *\test Test that the http_header content matches against a http request * which holds the content. @@ -4480,6 +4515,11 @@ static int DetectHttpRawHeaderIsdataatParseTest(void) void DetectHttpRawHeaderRegisterTests(void) { + UtRegisterTest("DetectHttpRawHeaderParserTest01", + DetectHttpRawHeaderParserTest01); + UtRegisterTest("DetectHttpRawHeaderParserTest02", + DetectHttpRawHeaderParserTest02); + UtRegisterTest("DetectEngineHttpRawHeaderTest01", DetectEngineHttpRawHeaderTest01); UtRegisterTest("DetectEngineHttpRawHeaderTest02",