detect/http2: do not escape ':' in header name or value

for keywords http.request_header and http.response_header

Ticket: #5780
pull/9001/head
Philippe Antoine 3 years ago committed by Victor Julien
parent 656554f293
commit 7256ec8a6e

@ -115,7 +115,6 @@ http.request_header
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::
@ -132,7 +131,6 @@ http.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::

@ -713,21 +713,11 @@ pub unsafe extern "C" fn rs_http2_tx_get_header_value(
fn http2_escape_header(blocks: &[parser::HTTP2FrameHeaderBlock], i: u32) -> Vec<u8> {
//minimum size + 2 for escapes
let normalsize = blocks[i as usize].value.len() + 2 + blocks[i as usize].name.len() + 2;
let normalsize = blocks[i as usize].value.len() + 2 + blocks[i as usize].name.len();
let mut vec = Vec::with_capacity(normalsize);
for j in 0..blocks[i as usize].name.len() {
vec.push(blocks[i as usize].name[j]);
if blocks[i as usize].name[j] == b':' {
vec.push(b':');
}
}
vec.extend_from_slice(&blocks[i as usize].name);
vec.extend_from_slice(&[b':', b' ']);
for j in 0..blocks[i as usize].value.len() {
vec.push(blocks[i as usize].value[j]);
if blocks[i as usize].value[j] == b':' {
vec.push(b':');
}
}
vec.extend_from_slice(&blocks[i as usize].value);
return vec;
}

@ -99,8 +99,6 @@ static int PrefilterMpmHttp2HeaderRegister(DetectEngineCtx *de_ctx, SigGroupHead
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 DetectHttp2RequestHeaderValidateCallback(const Signature *s, const char **sigerror);
static bool DetectHttp2ResponseHeaderValidateCallback(const Signature *s, const char **sigerror);
#ifdef UNITTESTS
void DetectHTTP2RegisterTests (void);
@ -218,8 +216,6 @@ void DetectHttp2Register(void)
PrefilterMpmHttp2HeaderRegister, NULL, ALPROTO_HTTP2, HTTP2StateOpen);
DetectAppLayerInspectEngineRegister2("http_request_header", ALPROTO_HTTP2, SIG_FLAG_TOSERVER,
HTTP2StateOpen, DetectEngineInspectHttp2Header, NULL);
DetectBufferTypeRegisterValidateCallback(
"http_request_header", DetectHttp2RequestHeaderValidateCallback);
DetectBufferTypeSetDescriptionByName("http_request_header", "HTTP header name and value");
g_http_request_header_buffer_id = DetectBufferTypeGetByName("http_request_header");
@ -235,8 +231,6 @@ void DetectHttp2Register(void)
PrefilterMpmHttp2HeaderRegister, NULL, ALPROTO_HTTP2, HTTP2StateOpen);
DetectAppLayerInspectEngineRegister2("http_response_header", ALPROTO_HTTP2, SIG_FLAG_TOCLIENT,
HTTP2StateOpen, DetectEngineInspectHttp2Header, NULL);
DetectBufferTypeRegisterValidateCallback(
"http_response_header", DetectHttp2ResponseHeaderValidateCallback);
DetectBufferTypeSetDescriptionByName("http_response_header", "HTTP header name and value");
g_http_response_header_buffer_id = DetectBufferTypeGetByName("http_response_header");
@ -939,72 +933,6 @@ static uint8_t DetectEngineInspectHttp2Header(DetectEngineCtx *de_ctx,
return DETECT_ENGINE_INSPECT_SIG_NO_MATCH;
}
static bool DetectHttp2HeaderValidateCallback(
const Signature *s, const char **sigerror, int buffer_id)
{
for (uint32_t x = 0; x < s->init_data->buffer_index; x++) {
if (s->init_data->buffers[x].id != (uint32_t)g_http_request_header_buffer_id &&
s->init_data->buffers[x].id != (uint32_t)g_http_response_header_buffer_id)
continue;
const SigMatch *sm = s->init_data->buffers[x].head;
for (; sm != NULL; sm = sm->next) {
if (sm->type != DETECT_CONTENT)
continue;
const SigMatch *sm = s->init_data->buffers[x].head;
for (; sm != NULL; sm = sm->next) {
if (sm->type != DETECT_CONTENT)
continue;
const DetectContentData *cd = (DetectContentData *)sm->ctx;
bool escaped = false;
bool namevaluesep = false;
for (size_t i = 0; i < cd->content_len; ++i) {
if (escaped) {
if (cd->content[i] == ' ') {
if (namevaluesep) {
*sigerror =
"Invalid http2.header string : "
"': ' is a special sequence for separation between name "
"and value "
" and thus can only be present once";
SCLogWarning("rule %u: %s", s->id, *sigerror);
return false;
}
namevaluesep = true;
} else if (cd->content[i] != ':') {
*sigerror = "Invalid http2.header string : "
"':' is an escaping character for itself, "
"or space for the separation between name and value";
SCLogWarning("rule %u: %s", s->id, *sigerror);
return false;
}
escaped = false;
} else if (cd->content[i] == ':') {
escaped = true;
}
}
if (escaped) {
*sigerror = "Invalid http2.header string : "
"':' is an escaping character for itself, "
"or space for the separation between name and value";
SCLogWarning("rule %u: %s", s->id, *sigerror);
return false;
}
}
}
}
return true;
}
static bool DetectHttp2RequestHeaderValidateCallback(const Signature *s, const char **sigerror)
{
return DetectHttp2HeaderValidateCallback(s, sigerror, g_http_request_header_buffer_id);
}
static bool DetectHttp2ResponseHeaderValidateCallback(const Signature *s, const char **sigerror)
{
return DetectHttp2HeaderValidateCallback(s, sigerror, g_http_response_header_buffer_id);
}
#ifdef UNITTESTS
#include "tests/detect-http2.c"
#endif

Loading…
Cancel
Save