Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

http2: remove http2.header keyword #8615

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
30 changes: 23 additions & 7 deletions doc/userguide/rules/http2-keywords.rst
Expand Up @@ -110,22 +110,38 @@ Examples::
``http2.header_name`` can be used as ``fast_pattern``.


http2.header
-----------------
http2.request_header
--------------------

Match on the name and value of a HTTP2 header from a HEADER frame (or PUSH_PROMISE or CONTINUATION).
Match on the name and value of a HTTP2 request header from a HEADER frame (or PUSH_PROMISE or CONTINUATION).
Name and value get concatenated by ": ", colon and space.
Each colon in the name or the value should be escaped as a double colon "::" for detection

Examples::

http2.header; content:"agent: nghttp2";
http2.header; content:"custom-header: I love::colons";
http2.request_header; content:"agent: nghttp2";
http2.request_header; content:"custom-header: I love::colons";

``http2.request_header`` is a 'sticky buffer'.

``http2.request_header`` can be used as ``fast_pattern``.


http2.response_header
---------------------

Match on the name and value of a HTTP2 response header from a HEADER frame (or PUSH_PROMISE or CONTINUATION).
Name and value get concatenated by ": ", colon and space.
Each colon in the name or the value should be escaped as a double colon "::" for detection

Examples::

``http2.header`` is a 'sticky buffer'.
http2.response_header; content:"server: nghttp2";
http2.response_header; content:"custom-header: I love::colons";

``http2.header`` can be used as ``fast_pattern``.
``http2.response_header`` is a 'sticky buffer'.

``http2.response_header`` can be used as ``fast_pattern``.

Additional information
----------------------
Expand Down
1 change: 1 addition & 0 deletions doc/userguide/upgrade.rst
Expand Up @@ -60,6 +60,7 @@ Logging changes

Other changes
~~~~~~~~~~~~~
- Experimental keyword `http2.header` is removed. `http.header`, `http2.request_header`, and `http2.response_header` are to be used.
- NSS is no longer required. File hashing and JA3 can now be used without the NSS compile time dependency.
- If installing Suricata without the bundled Suricata-Update, the ``default-rule-path`` has been changed from ``/etc/suricata/rules`` to ``/var/lib/suricata/rules`` to be consistent with Suricata when installed with Suricata-Update.
- FTP has been updated with a maximum command request and response line length of 4096 bytes. To change the default see :ref:`suricata-yaml-configure-ftp`.
Expand Down
3 changes: 2 additions & 1 deletion src/detect-engine-register.h
Expand Up @@ -187,7 +187,8 @@ enum DetectKeywordId {
DETECT_HTTP2_SIZEUPDATE,
DETECT_HTTP2_SETTINGS,
DETECT_HTTP2_HEADERNAME,
DETECT_HTTP2_HEADER,
DETECT_HTTP2_REQUEST_HEADER,
DETECT_HTTP2_RESPONSE_HEADER,

DETECT_DCE_IFACE,
DETECT_DCE_OPNUM,
Expand Down
96 changes: 65 additions & 31 deletions src/detect-http2.c
Expand Up @@ -93,23 +93,25 @@ static uint8_t DetectEngineInspectHttp2HeaderName(DetectEngineCtx *de_ctx,
DetectEngineThreadCtx *det_ctx, const DetectEngineAppInspectionEngine *engine,
const Signature *s, Flow *f, uint8_t flags, void *alstate, void *txv, uint64_t tx_id);

static int DetectHTTP2headerSetup(DetectEngineCtx *de_ctx, Signature *s, const char *arg);
static int DetectHTTP2RequestHeaderSetup(DetectEngineCtx *de_ctx, Signature *s, const char *arg);
static int DetectHTTP2ResponseHeaderSetup(DetectEngineCtx *de_ctx, Signature *s, const char *arg);
static int PrefilterMpmHttp2HeaderRegister(DetectEngineCtx *de_ctx,
SigGroupHead *sgh, MpmCtx *mpm_ctx,
const DetectBufferMpmRegistery *mpm_reg, int list_id);
static uint8_t DetectEngineInspectHttp2Header(DetectEngineCtx *de_ctx,
DetectEngineThreadCtx *det_ctx, const DetectEngineAppInspectionEngine *engine,
const Signature *s, Flow *f, uint8_t flags, void *alstate, void *txv, uint64_t tx_id);
static bool DetectHttp2HeaderValidateCallback(const Signature *s, const char **sigerror);
static bool DetectHttp2RequestHeaderValidateCallback(const Signature *s, const char **sigerror);
static bool DetectHttp2ResponseHeaderValidateCallback(const Signature *s, const char **sigerror);

#ifdef UNITTESTS
void DetectHTTP2RegisterTests (void);
#endif

static int g_http2_match_buffer_id = 0;
static int g_http2_header_name_buffer_id = 0;
static int g_http2_header_buffer_id = 0;

static int g_http2_request_header_buffer_id = 0;
static int g_http2_response_header_buffer_id = 0;

/**
* \brief Registration function for HTTP2 keywords
Expand Down Expand Up @@ -206,29 +208,39 @@ void DetectHttp2Register(void)
"HTTP2 header name");
g_http2_header_name_buffer_id = DetectBufferTypeGetByName("http2_header_name");

sigmatch_table[DETECT_HTTP2_HEADER].name = "http2.header";
sigmatch_table[DETECT_HTTP2_HEADER].desc = "sticky buffer to match on one HTTP2 header name and value";
sigmatch_table[DETECT_HTTP2_HEADER].url = "/rules/http2-keywords.html#header";
sigmatch_table[DETECT_HTTP2_HEADER].Setup = DetectHTTP2headerSetup;
sigmatch_table[DETECT_HTTP2_HEADER].flags |= SIGMATCH_NOOPT | SIGMATCH_INFO_STICKY_BUFFER;

DetectAppLayerMpmRegister2("http2_header", SIG_FLAG_TOCLIENT, 2,
PrefilterMpmHttp2HeaderRegister, NULL,
ALPROTO_HTTP2, HTTP2StateOpen);
DetectAppLayerInspectEngineRegister2("http2_header",
ALPROTO_HTTP2, SIG_FLAG_TOCLIENT, HTTP2StateOpen,
DetectEngineInspectHttp2Header, NULL);
DetectAppLayerMpmRegister2("http2_header", SIG_FLAG_TOSERVER, 2,
PrefilterMpmHttp2HeaderRegister, NULL,
ALPROTO_HTTP2, HTTP2StateOpen);
DetectAppLayerInspectEngineRegister2("http2_header",
ALPROTO_HTTP2, SIG_FLAG_TOSERVER, HTTP2StateOpen,
DetectEngineInspectHttp2Header, NULL);

DetectBufferTypeSetDescriptionByName("http2_header",
"HTTP2 header name and value");
DetectBufferTypeRegisterValidateCallback("http2_header", DetectHttp2HeaderValidateCallback);
g_http2_header_buffer_id = DetectBufferTypeGetByName("http2_header");
sigmatch_table[DETECT_HTTP2_REQUEST_HEADER].name = "http2.request_header";
sigmatch_table[DETECT_HTTP2_REQUEST_HEADER].desc =
"sticky buffer to match on only one HTTP2 header name and value";
sigmatch_table[DETECT_HTTP2_REQUEST_HEADER].url = "/rules/http2-keywords.html#request_header";
sigmatch_table[DETECT_HTTP2_REQUEST_HEADER].Setup = DetectHTTP2RequestHeaderSetup;
sigmatch_table[DETECT_HTTP2_REQUEST_HEADER].flags |=
SIGMATCH_NOOPT | SIGMATCH_INFO_STICKY_BUFFER;

DetectAppLayerMpmRegister2("http2_request_header", SIG_FLAG_TOSERVER, 2,
PrefilterMpmHttp2HeaderRegister, NULL, ALPROTO_HTTP2, HTTP2StateOpen);
DetectAppLayerInspectEngineRegister2("http2_request_header", ALPROTO_HTTP2, SIG_FLAG_TOSERVER,
HTTP2StateOpen, DetectEngineInspectHttp2Header, NULL);
DetectBufferTypeRegisterValidateCallback(
"http2_request_header", DetectHttp2RequestHeaderValidateCallback);
DetectBufferTypeSetDescriptionByName("http2_request_header", "HTTP2 header name and value");
g_http2_request_header_buffer_id = DetectBufferTypeGetByName("http2_request_header");

sigmatch_table[DETECT_HTTP2_RESPONSE_HEADER].name = "http2.response_header";
sigmatch_table[DETECT_HTTP2_RESPONSE_HEADER].desc =
"sticky buffer to match on only one HTTP2 header name and value";
sigmatch_table[DETECT_HTTP2_RESPONSE_HEADER].url = "/rules/http2-keywords.html#response_header";
sigmatch_table[DETECT_HTTP2_RESPONSE_HEADER].Setup = DetectHTTP2ResponseHeaderSetup;
sigmatch_table[DETECT_HTTP2_RESPONSE_HEADER].flags |=
SIGMATCH_NOOPT | SIGMATCH_INFO_STICKY_BUFFER;

DetectAppLayerMpmRegister2("http2_response_header", SIG_FLAG_TOCLIENT, 2,
PrefilterMpmHttp2HeaderRegister, NULL, ALPROTO_HTTP2, HTTP2StateOpen);
DetectAppLayerInspectEngineRegister2("http2_response_header", ALPROTO_HTTP2, SIG_FLAG_TOCLIENT,
HTTP2StateOpen, DetectEngineInspectHttp2Header, NULL);
DetectBufferTypeRegisterValidateCallback(
"http2_response_header", DetectHttp2ResponseHeaderValidateCallback);
DetectBufferTypeSetDescriptionByName("http2_response_header", "HTTP2 header name and value");
g_http2_response_header_buffer_id = DetectBufferTypeGetByName("http2_response_header");

DetectAppLayerInspectEngineRegister2(
"http2", ALPROTO_HTTP2, SIG_FLAG_TOSERVER, 0, DetectEngineInspectGenericList, NULL);
Expand Down Expand Up @@ -786,9 +798,20 @@ static uint8_t DetectEngineInspectHttp2HeaderName(DetectEngineCtx *de_ctx,
return DETECT_ENGINE_INSPECT_SIG_NO_MATCH;
}

static int DetectHTTP2headerSetup(DetectEngineCtx *de_ctx, Signature *s, const char *arg)
static int DetectHTTP2RequestHeaderSetup(DetectEngineCtx *de_ctx, Signature *s, const char *arg)
{
if (DetectBufferSetActiveList(s, g_http2_request_header_buffer_id) < 0)
return -1;

if (DetectSignatureSetAppProto(s, ALPROTO_HTTP2) != 0)
return -1;

return 0;
}

static int DetectHTTP2ResponseHeaderSetup(DetectEngineCtx *de_ctx, Signature *s, const char *arg)
{
if (DetectBufferSetActiveList(s, g_http2_header_buffer_id) < 0)
if (DetectBufferSetActiveList(s, g_http2_response_header_buffer_id) < 0)
return -1;

if (DetectSignatureSetAppProto(s, ALPROTO_HTTP2) != 0)
Expand Down Expand Up @@ -917,9 +940,10 @@ static uint8_t DetectEngineInspectHttp2Header(DetectEngineCtx *de_ctx,
return DETECT_ENGINE_INSPECT_SIG_NO_MATCH;
}

static bool DetectHttp2HeaderValidateCallback(const Signature *s, const char **sigerror)
static bool DetectHttp2HeaderValidateCallback(
const Signature *s, const char **sigerror, int buffer_id)
{
const SigMatch *sm = s->init_data->smlists[g_http2_header_buffer_id];
const SigMatch *sm = s->init_data->smlists[buffer_id];
for ( ; sm != NULL; sm = sm->next) {
if (sm->type != DETECT_CONTENT)
continue;
Expand Down Expand Up @@ -960,6 +984,16 @@ static bool DetectHttp2HeaderValidateCallback(const Signature *s, const char **s
return true;
}

static bool DetectHttp2RequestHeaderValidateCallback(const Signature *s, const char **sigerror)
{
return DetectHttp2HeaderValidateCallback(s, sigerror, g_http2_request_header_buffer_id);
}

static bool DetectHttp2ResponseHeaderValidateCallback(const Signature *s, const char **sigerror)
{
return DetectHttp2HeaderValidateCallback(s, sigerror, g_http2_response_header_buffer_id);
}

#ifdef UNITTESTS
#include "tests/detect-http2.c"
#endif