From: Philippe Antoine Date: Wed, 17 Feb 2021 08:37:57 +0000 (+0100) Subject: http: makes decompression time limit configurable X-Git-Tag: suricata-7.0.0-beta1~1774 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=refs%2Fpull%2F5899%2Fhead;p=thirdparty%2Fsuricata.git http: makes decompression time limit configurable --- diff --git a/configure.ac b/configure.ac index af47d47b4b..12a90a3ebf 100644 --- a/configure.ac +++ b/configure.ac @@ -1697,6 +1697,7 @@ AC_CHECK_LIB([htp], [htp_config_set_lzma_memlimit],AC_DEFINE_UNQUOTED([HAVE_HTP_CONFIG_SET_LZMA_MEMLIMIT],[1],[Found htp_config_set_lzma_memlimit function in libhtp]) ,,[-lhtp]) AC_CHECK_LIB([htp], [htp_config_set_lzma_layers],AC_DEFINE_UNQUOTED([HAVE_HTP_CONFIG_SET_LZMA_LAYERS],[1],[Found htp_config_set_lzma_layers function in libhtp]) ,,[-lhtp]) 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]) ]) if test "x$enable_non_bundled_htp" = "xno"; then @@ -1720,6 +1721,7 @@ AC_DEFINE_UNQUOTED([HAVE_HTP_CONFIG_SET_LZMA_MEMLIMIT],[1],[Assuming htp_config_set_lzma_memlimit function in bundled libhtp]) AC_DEFINE_UNQUOTED([HAVE_HTP_CONFIG_SET_LZMA_LAYERS],[1],[Assuming htp_config_set_lzma_layers function in bundled libhtp]) 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]) else echo echo " ERROR: Libhtp is not bundled. Get libhtp by doing:" diff --git a/doc/userguide/configuration/suricata-yaml.rst b/doc/userguide/configuration/suricata-yaml.rst index a976df4a60..a4fcd75fc0 100644 --- a/doc/userguide/configuration/suricata-yaml.rst +++ b/doc/userguide/configuration/suricata-yaml.rst @@ -1366,12 +1366,26 @@ use of libhtp. # Maximum decompressed size with a compression ratio # above 2048 (only reachable by LZMA) #compression-bomb-limit: 1 Mb + # Maximum time spent decompressing a single transaction in usec + #decompression-time-limit: 100000 Other parameters are customizable from Suricata. :: - # double-decode-path: Double decode path section of the URI - # double-decode-query: Double decode query section of the URI +# double-decode-path: Double decode path section of the URI +# double-decode-query: Double decode query section of the URI + +decompression-time-limit +------------------------ + +decompression-time-limit was implemented to avoid DOS by resource exhaustion +on inputs such as decompression bombs (found by fuzzing). +The lower the limit, the better the protection against DOS is, but this +may also lead to false positives. +In case the time limit is reached, +the app-layer event ``http.compression_bomb`` is set +(this event can also set from other conditions). +This can happen on slow configurations (hardware, ASAN, etc...) Configure SMB (Rust) ~~~~~~~~~~~~~~~~~~~~ diff --git a/src/app-layer-htp.c b/src/app-layer-htp.c index c19a0b658f..02df3bb6cd 100644 --- a/src/app-layer-htp.c +++ b/src/app-layer-htp.c @@ -2394,6 +2394,9 @@ static void HTPConfigSetDefaultsPhase1(HTPCfgRec *cfg_prec) #ifdef HAVE_HTP_CONFIG_SET_COMPRESSION_BOMB_LIMIT htp_config_set_compression_bomb_limit(cfg_prec->cfg, HTP_CONFIG_DEFAULT_COMPRESSION_BOMB_LIMIT); +#endif +#ifdef HAVE_HTP_CONFIG_SET_COMPRESSION_TIME_LIMIT + htp_config_set_compression_time_limit(cfg_prec->cfg, HTP_CONFIG_DEFAULT_COMPRESSION_TIME_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. @@ -2747,6 +2750,19 @@ static void HTPConfigParseParameters(HTPCfgRec *cfg_prec, ConfNode *s, /* set default soft-limit with our new hard limit */ SCLogConfig("Setting HTTP compression bomb limit to %"PRIu32" bytes", limit); htp_config_set_compression_bomb_limit(cfg_prec->cfg, (size_t)limit); +#endif +#ifdef HAVE_HTP_CONFIG_SET_COMPRESSION_TIME_LIMIT + } else if (strcasecmp("decompression-time-limit", p->name) == 0) { + uint32_t limit = 0; + // between 1 usec and 1 second + if (StringParseU32RangeCheck(&limit, 10, 0, p->val, 1, 1000000) < 0) { + FatalError(SC_ERR_SIZE_PARSE, + "failed to parse 'decompression-time-limit' " + "from conf file - %s.", + p->val); + } + SCLogConfig("Setting HTTP decompression time limit to %" PRIu32 " usec", limit); + htp_config_set_compression_time_limit(cfg_prec->cfg, (size_t)limit); #endif } else if (strcasecmp("randomize-inspection-sizes", p->name) == 0) { if (!g_disable_randomness) { diff --git a/src/app-layer-htp.h b/src/app-layer-htp.h index 2037e90655..d6fa4f0095 100644 --- a/src/app-layer-htp.h +++ b/src/app-layer-htp.h @@ -56,6 +56,8 @@ /* default libhtp lzma limit, taken from libhtp. */ #define HTP_CONFIG_DEFAULT_LZMA_MEMLIMIT 1048576U #define HTP_CONFIG_DEFAULT_COMPRESSION_BOMB_LIMIT 1048576U +// 100000 usec is 0.1 sec +#define HTP_CONFIG_DEFAULT_COMPRESSION_TIME_LIMIT 100000 #define HTP_CONFIG_DEFAULT_RANDOMIZE 1 #define HTP_CONFIG_DEFAULT_RANDOMIZE_RANGE 10 diff --git a/suricata.yaml.in b/suricata.yaml.in index 3f1bae8f11..8534f7ee9d 100644 --- a/suricata.yaml.in +++ b/suricata.yaml.in @@ -897,6 +897,8 @@ app-layer: # Maximum decompressed size with a compression ratio # above 2048 (only LZMA can reach this ratio, deflate cannot) #compression-bomb-limit: 1mb + # Maximum time spent decompressing a single transaction in usec + #decompression-time-limit: 100000 server-config: