http: have a headers limit

Ticket: 7191

So as to avoid quadratic complexity in libhtp.
Make the limit configurable from suricata.yaml,
and have an event when network traffic goes over the limit.
pull/11852/head
Philippe Antoine 6 months ago committed by Victor Julien
parent 1e152d1f10
commit bb714c9178

@ -1622,6 +1622,7 @@
AC_CHECK_LIB([htp], [htp_config_set_compression_bomb_limit],AC_DEFINE_UNQUOTED([HAVE_HTP_CONFIG_SET_COMPRESSION_BOMB_LIMIT],[1],[Found htp_config_set_compression_bomb_limit function in libhtp]) ,,[-lhtp])
AC_CHECK_LIB([htp], [htp_config_set_compression_time_limit],AC_DEFINE_UNQUOTED([HAVE_HTP_CONFIG_SET_COMPRESSION_TIME_LIMIT],[1],[Found htp_config_set_compression_time_limit function in libhtp]) ,,[-lhtp])
AC_CHECK_LIB([htp], [htp_config_set_max_tx],AC_DEFINE_UNQUOTED([HAVE_HTP_CONFIG_SET_MAX_TX],[1],[Found htp_config_set_max_tx function in libhtp]) ,,[-lhtp])
AC_CHECK_LIB([htp], [htp_config_set_number_headers_limit],AC_DEFINE_UNQUOTED([HAVE_HTP_CONFIG_SET_HEADERS_LIMIT],[1],[Found htp_config_set_number_headers_limit function in libhtp]) ,,[-lhtp])
])
if test "x$enable_non_bundled_htp" = "xno"; then
@ -1648,6 +1649,7 @@
AC_DEFINE_UNQUOTED([HAVE_HTP_CONFIG_SET_COMPRESSION_BOMB_LIMIT],[1],[Assuming htp_config_set_compression_bomb_limit function in bundled libhtp])
AC_DEFINE_UNQUOTED([HAVE_HTP_CONFIG_SET_COMPRESSION_TIME_LIMIT],[1],[Assuming htp_config_set_compression_time_limit function in bundled libhtp])
AC_DEFINE_UNQUOTED([HAVE_HTP_CONFIG_SET_MAX_TX],[1],[Assuming htp_config_set_max_tx function in bundled libhtp])
AC_DEFINE_UNQUOTED([HAVE_HTP_CONFIG_SET_HEADERS_LIMIT],[1],[Assuming htp_config_set_number_headers_limit function in bundled libhtp])
else
echo
echo " ERROR: Libhtp is not bundled. Get libhtp by doing:"

@ -1588,6 +1588,10 @@ use of libhtp.
#compression-bomb-limit: 1 Mb
# Maximum time spent decompressing a single transaction in usec
#decompression-time-limit: 100000
# Maximum number of live transactions per flow
#max-tx: 512
# Maximum used number of HTTP1 headers in one request or response
#headers-limit: 1024
Other parameters are customizable from Suricata.
::

@ -93,4 +93,7 @@ alert http any any -> any any (msg:"SURICATA HTTP failed protocol change"; flow:
alert http any any -> any any (msg:"SURICATA HTTP request missing protocol"; flow:established,to_server; app-layer-event:http.request_line_missing_protocol; classtype:protocol-command-decode; sid:2221055; rev:1;)
# next sid 2221056
alert http any any -> any any (msg:"SURICATA HTTP request too many headers"; flow:established,to_server; app-layer-event:http.request_too_many_headers; classtype:protocol-command-decode; sid:2221056; rev:1;)
alert http any any -> any any (msg:"SURICATA HTTP response too many headers"; flow:established,to_client; app-layer-event:http.response_too_many_headers; classtype:protocol-command-decode; sid:2221057; rev:1;)
# next sid 2221058

@ -170,6 +170,9 @@ SCEnumCharMap http_decoder_event_table[] = {
{ "REQUEST_CHUNK_EXTENSION", HTTP_DECODER_EVENT_REQUEST_CHUNK_EXTENSION },
{ "REQUEST_LINE_MISSING_PROTOCOL", HTTP_DECODER_EVENT_REQUEST_LINE_MISSING_PROTOCOL },
{ "REQUEST_TOO_MANY_HEADERS", HTTP_DECODER_EVENT_REQUEST_TOO_MANY_HEADERS },
{ "RESPONSE_TOO_MANY_HEADERS", HTTP_DECODER_EVENT_RESPONSE_TOO_MANY_HEADERS },
/* suricata warnings/errors */
{ "MULTIPART_GENERIC_ERROR", HTTP_DECODER_EVENT_MULTIPART_GENERIC_ERROR },
{ "MULTIPART_NO_FILEDATA", HTTP_DECODER_EVENT_MULTIPART_NO_FILEDATA },
@ -629,6 +632,8 @@ struct {
HTTP_DECODER_EVENT_DUPLICATE_CONTENT_LENGTH_FIELD_IN_RESPONSE },
{ "Request chunk extension", HTTP_DECODER_EVENT_REQUEST_CHUNK_EXTENSION },
{ "Request line: missing protocol", HTTP_DECODER_EVENT_REQUEST_LINE_MISSING_PROTOCOL },
{ "Too many request headers", HTTP_DECODER_EVENT_REQUEST_TOO_MANY_HEADERS },
{ "Too many response headers", HTTP_DECODER_EVENT_RESPONSE_TOO_MANY_HEADERS },
};
#define HTP_ERROR_MAX (sizeof(htp_errors) / sizeof(htp_errors[0]))
@ -2101,6 +2106,10 @@ static void HTPConfigSetDefaultsPhase1(HTPCfgRec *cfg_prec)
#ifdef HAVE_HTP_CONFIG_SET_MAX_TX
#define HTP_CONFIG_DEFAULT_MAX_TX_LIMIT 512
htp_config_set_max_tx(cfg_prec->cfg, HTP_CONFIG_DEFAULT_MAX_TX_LIMIT);
#endif
#ifdef HAVE_HTP_CONFIG_SET_HEADERS_LIMIT
#define HTP_CONFIG_DEFAULT_HEADERS_LIMIT 1024
htp_config_set_number_headers_limit(cfg_prec->cfg, HTP_CONFIG_DEFAULT_HEADERS_LIMIT);
#endif
/* libhtp <= 0.5.9 doesn't use soft limit, but it's impossible to set
* only the hard limit. So we set both here to the (current) htp defaults.
@ -2461,6 +2470,17 @@ static void HTPConfigParseParameters(HTPCfgRec *cfg_prec, ConfNode *s,
/* set default soft-limit with our new hard limit */
SCLogConfig("Setting HTTP max-tx limit to %" PRIu32 " bytes", limit);
htp_config_set_max_tx(cfg_prec->cfg, limit);
#endif
#ifdef HAVE_HTP_CONFIG_SET_HEADERS_LIMIT
} else if (strcasecmp("headers-limit", p->name) == 0) {
uint32_t limit = 0;
if (ParseSizeStringU32(p->val, &limit) < 0) {
FatalError("failed to parse 'headers-limit' "
"from conf file - %s.",
p->val);
}
SCLogConfig("Setting HTTP headers limit to %" PRIu32, limit);
htp_config_set_number_headers_limit(cfg_prec->cfg, limit);
#endif
} else if (strcasecmp("randomize-inspection-sizes", p->name) == 0) {
if (!g_disable_randomness) {

@ -126,6 +126,8 @@ enum {
HTTP_DECODER_EVENT_RANGE_INVALID,
HTTP_DECODER_EVENT_REQUEST_CHUNK_EXTENSION,
HTTP_DECODER_EVENT_REQUEST_LINE_MISSING_PROTOCOL,
HTTP_DECODER_EVENT_REQUEST_TOO_MANY_HEADERS,
HTTP_DECODER_EVENT_RESPONSE_TOO_MANY_HEADERS,
/* suricata errors/warnings */
HTTP_DECODER_EVENT_MULTIPART_GENERIC_ERROR,

@ -1098,6 +1098,8 @@ app-layer:
#decompression-time-limit: 100000
# Maximum number of live transactions per flow
#max-tx: 512
# Maximum used number of HTTP1 headers in one request or response
#headers-limit: 1024
server-config:

Loading…
Cancel
Save