Skip to content

Commit

Permalink
http: have a headers limit
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
catenacyber authored and victorjulien committed Sep 25, 2024
1 parent 1e152d1 commit bb714c9
Show file tree
Hide file tree
Showing 6 changed files with 34 additions and 1 deletion.
2 changes: 2 additions & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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:"
Expand Down
4 changes: 4 additions & 0 deletions doc/userguide/configuration/suricata-yaml.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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.
::
Expand Down
5 changes: 4 additions & 1 deletion rules/http-events.rules
Original file line number Diff line number Diff line change
Expand Up @@ -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
20 changes: 20 additions & 0 deletions src/app-layer-htp.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 },
Expand Down Expand Up @@ -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]))
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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) {
Expand Down
2 changes: 2 additions & 0 deletions src/app-layer-htp.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
2 changes: 2 additions & 0 deletions suricata.yaml.in
Original file line number Diff line number Diff line change
Expand Up @@ -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:

Expand Down

0 comments on commit bb714c9

Please sign in to comment.