Version in base suite: 0.5.42-1 Base version: libhtp_0.5.42-1 Target version: libhtp_0.5.42-1+deb12u1 Base file: /srv/ftp-master.debian.org/ftp/pool/main/libh/libhtp/libhtp_0.5.42-1.dsc Target file: /srv/ftp-master.debian.org/policy/pool/main/libh/libhtp/libhtp_0.5.42-1+deb12u1.dsc changelog | 8 libhtp2.symbols | 1 patches/0001-headers-limit-the-size-of-folded-headers.patch | 77 +++++ patches/0002-headers-put-a-configurable-limit-on-their-numbers.patch | 141 ++++++++++ patches/series | 2 5 files changed, 229 insertions(+) diff -Nru libhtp-0.5.42/debian/changelog libhtp-0.5.42/debian/changelog --- libhtp-0.5.42/debian/changelog 2022-12-02 12:31:28.000000000 +0000 +++ libhtp-0.5.42/debian/changelog 2025-09-08 12:17:26.000000000 +0000 @@ -1,3 +1,11 @@ +libhtp (1:0.5.42-1+deb12u1) bookworm; urgency=medium + + * Non-maintainer upload. + * CVE-2024-23837: DoS due to unbounded folded header handling + * CVE-2024-45797: DoS due to unbounded header handling + + -- Adrian Bunk Mon, 08 Sep 2025 15:17:26 +0300 + libhtp (1:0.5.42-1) unstable; urgency=medium * New upstream release. diff -Nru libhtp-0.5.42/debian/libhtp2.symbols libhtp-0.5.42/debian/libhtp2.symbols --- libhtp-0.5.42/debian/libhtp2.symbols 2022-12-02 12:31:28.000000000 +0000 +++ libhtp-0.5.42/debian/libhtp2.symbols 2025-09-08 12:17:26.000000000 +0000 @@ -150,6 +150,7 @@ htp_config_set_nul_encoded_unwanted@Base 0.5.16 htp_config_set_nul_raw_terminates@Base 0.5.16 htp_config_set_nul_raw_unwanted@Base 0.5.16 + htp_config_set_number_headers_limit@Base 1:0.5.42-1+deb12u1~ htp_config_set_parse_request_auth@Base 0.5.16 htp_config_set_parse_request_cookies@Base 0.5.16 htp_config_set_path_separators_compress@Base 0.5.16 diff -Nru libhtp-0.5.42/debian/patches/0001-headers-limit-the-size-of-folded-headers.patch libhtp-0.5.42/debian/patches/0001-headers-limit-the-size-of-folded-headers.patch --- libhtp-0.5.42/debian/patches/0001-headers-limit-the-size-of-folded-headers.patch 1970-01-01 00:00:00.000000000 +0000 +++ libhtp-0.5.42/debian/patches/0001-headers-limit-the-size-of-folded-headers.patch 2025-09-08 12:17:26.000000000 +0000 @@ -0,0 +1,77 @@ +From 9810ae38dd930c18853f50c462291d37125bfc5c Mon Sep 17 00:00:00 2001 +From: Philippe Antoine +Date: Wed, 8 Nov 2023 09:42:50 +0100 +Subject: headers: limit the size of folded headers + +Ticket: #6444 + +So as to limit the quadratic complexity of always reallocating +to push more bytes in header value +--- + htp/htp_private.h | 3 +++ + htp/htp_request.c | 12 ++++++++---- + htp/htp_response.c | 12 ++++++++---- + 3 files changed, 19 insertions(+), 8 deletions(-) + +diff --git a/htp/htp_private.h b/htp/htp_private.h +index e239082..543367a 100644 +--- a/htp/htp_private.h ++++ b/htp/htp_private.h +@@ -259,5 +259,8 @@ size_t strlcpy(char *dst, const char *src, size_t size); + } + #endif + ++// as CURL_MAX_HTTP_HEADER ++#define HTP_MAX_HEADER_FOLDED 102400 ++ + #endif /* _HTP_PRIVATE_H */ + +diff --git a/htp/htp_request.c b/htp/htp_request.c +index 31a2122..6660651 100644 +--- a/htp/htp_request.c ++++ b/htp/htp_request.c +@@ -710,10 +710,14 @@ htp_status_t htp_connp_REQ_HEADERS(htp_connp_t *connp) { + connp->in_header = bstr_dup_mem(data + trim, len - trim); + if (connp->in_header == NULL) return HTP_ERROR; + } else { +- // Add to the existing header. +- bstr *new_in_header = bstr_add_mem(connp->in_header, data, len); +- if (new_in_header == NULL) return HTP_ERROR; +- connp->in_header = new_in_header; ++ // Add to the existing header. ++ if (bstr_len(connp->in_header) < HTP_MAX_HEADER_FOLDED) { ++ bstr *new_in_header = bstr_add_mem(connp->in_header, data, len); ++ if (new_in_header == NULL) return HTP_ERROR; ++ connp->in_header = new_in_header; ++ } else { ++ htp_log(connp, HTP_LOG_MARK, HTP_LOG_WARNING, 0, "Request field length exceeds folded maximum"); ++ } + } + } + +diff --git a/htp/htp_response.c b/htp/htp_response.c +index dec1222..3466fbc 100644 +--- a/htp/htp_response.c ++++ b/htp/htp_response.c +@@ -976,10 +976,14 @@ htp_status_t htp_connp_RES_HEADERS(htp_connp_t *connp) { + return HTP_ERROR; + } else { + // Add to the existing header. +- bstr *new_out_header = bstr_add_mem(connp->out_header, data, len); +- if (new_out_header == NULL) +- return HTP_ERROR; +- connp->out_header = new_out_header; ++ if (bstr_len(connp->out_header) < HTP_MAX_HEADER_FOLDED) { ++ bstr *new_out_header = bstr_add_mem(connp->out_header, data, len); ++ if (new_out_header == NULL) ++ return HTP_ERROR; ++ connp->out_header = new_out_header; ++ } else { ++ htp_log(connp, HTP_LOG_MARK, HTP_LOG_WARNING, 0, "Response field length exceeds folded maximum"); ++ } + } + } + } +-- +2.30.2 + diff -Nru libhtp-0.5.42/debian/patches/0002-headers-put-a-configurable-limit-on-their-numbers.patch libhtp-0.5.42/debian/patches/0002-headers-put-a-configurable-limit-on-their-numbers.patch --- libhtp-0.5.42/debian/patches/0002-headers-put-a-configurable-limit-on-their-numbers.patch 1970-01-01 00:00:00.000000000 +0000 +++ libhtp-0.5.42/debian/patches/0002-headers-put-a-configurable-limit-on-their-numbers.patch 2025-09-08 12:17:26.000000000 +0000 @@ -0,0 +1,141 @@ +From 94075375de0bee6f14083d935b321fd200d22d7d Mon Sep 17 00:00:00 2001 +From: Philippe Antoine +Date: Mon, 12 Aug 2024 14:06:40 +0200 +Subject: headers: put a configurable limit on their numbers + +So as to avoid quadratic complexity + +Ticket: 7191 +--- + htp/htp_config.c | 8 ++++++++ + htp/htp_config.h | 8 ++++++++ + htp/htp_config_private.h | 3 +++ + htp/htp_core.h | 1 + + htp/htp_request_generic.c | 11 +++++++++++ + htp/htp_response_generic.c | 10 ++++++++++ + 6 files changed, 41 insertions(+) + +diff --git a/htp/htp_config.c b/htp/htp_config.c +index 767458f..9e0eee3 100644 +--- a/htp/htp_config.c ++++ b/htp/htp_config.c +@@ -145,6 +145,8 @@ static unsigned char bestfit_1252[] = { + 0xff, 0x5d, 0x7d, 0xff, 0x5e, 0x7e, 0x00, 0x00, 0x00 + }; + ++#define HTP_HEADERS_LIMIT 1024 ++ + htp_cfg_t *htp_config_create(void) { + htp_cfg_t *cfg = calloc(1, sizeof (htp_cfg_t)); + if (cfg == NULL) return NULL; +@@ -163,6 +165,7 @@ htp_cfg_t *htp_config_create(void) { + cfg->response_lzma_layer_limit = 1; // default is only one layer + cfg->compression_bomb_limit = HTP_COMPRESSION_BOMB_LIMIT; + cfg->compression_time_limit = HTP_COMPRESSION_TIME_LIMIT_USEC; ++ cfg->number_headers_limit = HTP_HEADERS_LIMIT; + cfg->allow_space_uri = 0; + + // Default settings for URL-encoded data. +@@ -542,6 +545,11 @@ void htp_config_set_compression_time_limit(htp_cfg_t *cfg, size_t useclimit) { + } + } + ++void htp_config_set_number_headers_limit(htp_cfg_t *cfg, uint32_t limit) { ++ if (cfg == NULL) return; ++ cfg->number_headers_limit = limit; ++} ++ + void htp_config_set_log_level(htp_cfg_t *cfg, enum htp_log_level_t log_level) { + if (cfg == NULL) return; + cfg->log_level = log_level; +diff --git a/htp/htp_config.h b/htp/htp_config.h +index d1365dc..4391441 100644 +--- a/htp/htp_config.h ++++ b/htp/htp_config.h +@@ -458,6 +458,14 @@ void htp_config_set_compression_bomb_limit(htp_cfg_t *cfg, size_t bomblimit); + */ + void htp_config_set_compression_time_limit(htp_cfg_t *cfg, size_t useclimit); + ++/** ++ * Configures the maximum number of headers LibHTP will accept per request or response. ++ * ++ * @param[in] cfg ++ * @param[in] limit ++ */ ++void htp_config_set_number_headers_limit(htp_cfg_t *cfg, uint32_t limit); ++ + /** + * Configures the desired log level. + * +diff --git a/htp/htp_config_private.h b/htp/htp_config_private.h +index 5f1d60d..dff1663 100644 +--- a/htp/htp_config_private.h ++++ b/htp/htp_config_private.h +@@ -360,6 +360,9 @@ struct htp_cfg_t { + + /** Whether to decompress compressed request bodies. */ + int request_decompression_enabled; ++ ++ /** Maximum number of headers. */ ++ uint32_t number_headers_limit; + }; + + #ifdef __cplusplus +diff --git a/htp/htp_core.h b/htp/htp_core.h +index bdc63d5..780fcf1 100644 +--- a/htp/htp_core.h ++++ b/htp/htp_core.h +@@ -232,6 +232,7 @@ enum htp_file_source_t { + #define HTP_REQUEST_INVALID 0x100000000ULL + #define HTP_REQUEST_INVALID_C_L 0x200000000ULL + #define HTP_AUTH_INVALID 0x400000000ULL ++#define HTP_HEADERS_TOO_MANY 0x800000000ULL + + #define HTP_MAX_HEADERS_REPETITIONS 64 + +diff --git a/htp/htp_request_generic.c b/htp/htp_request_generic.c +index 435cf0a..1350e57 100644 +--- a/htp/htp_request_generic.c ++++ b/htp/htp_request_generic.c +@@ -120,6 +120,17 @@ htp_status_t htp_process_request_header_generic(htp_connp_t *connp, unsigned cha + bstr_free(h->value); + free(h); + } else { ++ if (htp_table_size(connp->in_tx->request_headers) > connp->cfg->number_headers_limit) { ++ if (!(connp->in_tx->flags & HTP_HEADERS_TOO_MANY)) { ++ connp->in_tx->flags |= HTP_HEADERS_TOO_MANY; ++ htp_log(connp, HTP_LOG_MARK, HTP_LOG_WARNING, 0, "Too many request headers"); ++ } ++ bstr_free(h->name); ++ bstr_free(h->value); ++ free(h); ++ // give up on what comes next ++ return HTP_ERROR; ++ } + // Add as a new header. + if (htp_table_add(connp->in_tx->request_headers, h->name, h) != HTP_OK) { + bstr_free(h->name); +diff --git a/htp/htp_response_generic.c b/htp/htp_response_generic.c +index 56a344c..c228486 100644 +--- a/htp/htp_response_generic.c ++++ b/htp/htp_response_generic.c +@@ -321,6 +321,16 @@ htp_status_t htp_process_response_header_generic(htp_connp_t *connp, unsigned ch + bstr_free(h->value); + free(h); + } else { ++ if (htp_table_size(connp->out_tx->response_headers) > connp->cfg->number_headers_limit) { ++ if (!(connp->out_tx->flags & HTP_HEADERS_TOO_MANY)) { ++ connp->out_tx->flags |= HTP_HEADERS_TOO_MANY; ++ htp_log(connp, HTP_LOG_MARK, HTP_LOG_WARNING, 0, "Too many response headers"); ++ } ++ bstr_free(h->name); ++ bstr_free(h->value); ++ free(h); ++ return HTP_ERROR; ++ } + // Add as a new header. + if (htp_table_add(connp->out_tx->response_headers, h->name, h) != HTP_OK) { + bstr_free(h->name); +-- +2.30.2 + diff -Nru libhtp-0.5.42/debian/patches/series libhtp-0.5.42/debian/patches/series --- libhtp-0.5.42/debian/patches/series 1970-01-01 00:00:00.000000000 +0000 +++ libhtp-0.5.42/debian/patches/series 2025-09-08 12:17:26.000000000 +0000 @@ -0,0 +1,2 @@ +0001-headers-limit-the-size-of-folded-headers.patch +0002-headers-put-a-configurable-limit-on-their-numbers.patch