]> git.kaiwu.me - haproxy.git/commitdiff
MINOR: http/hardening: implement hardening "reject-content-length-leading-zero"
authorWilly Tarreau <w@1wt.eu>
Wed, 4 Nov 2026 15:15:02 +0000 (16:15 +0100)
committerWilly Tarreau <w@1wt.eu>
Wed, 4 Nov 2026 21:45:33 +0000 (22:45 +0100)
Rejects requests and responses having a Content-Length header field
whose value contains a leading zero before a digit. Some client and
server applications tend to parse this as an octal value giving a
different body size (e.g. "0300" = 192). This can be used in attacks
trying to desynchronize a client or server from the rest of the
communication, and for example for cache poisionning attacks. These may
seldom be seen on legacy applications but not on standard compoennts
found on the internet, so it is generally safe to reject them on public
facing listeners.

doc/configuration.txt
include/haproxy/http-t.h
src/http.c

index b1cafe91abfdfc43eb5c4407d1f43144d69e42a3..adf73fd7f335fefef2fd85b1fdd532fb6714ef96 100644 (file)
@@ -34578,6 +34578,17 @@ http-hardening <name> [from <name2>]
         safe and even recommended to delete such trailers from inbound internet
         requests.
 
+  - reject-content-length-leading-zero (inbound request and response)
+        Rejects requests and responses having a Content-Length header field
+        whose value contains a leading zero before a digit. Some client and
+        server applications tend to parse this as an octal value giving a
+        different body size (e.g. "0300" = 192). This can be used in attacks
+        trying to desynchronize a client or server from the rest of the
+        communication, and for example for cache poisionning attacks. These may
+        seldom be seen on legacy applications but not on standard components
+        found on the internet, so it is generally safe to reject them on public
+        facing listeners.
+
   - reject-content-length-with-te (inbound request and response)
         Rejects requests and responses having both a Content-Length header
         field and a Transfer-Encoding header field. While these are permitted
index 66d8ae7e139e684e8278a3b714e52734cd6b3343..d3b3c0b62af3cf60c49078001f165b8e2c0cac2b 100644 (file)
@@ -252,6 +252,7 @@ struct http_violation {
 #define HTTP_HRD_REJ_HDR_FOLD               0x00000200
 #define HTTP_HRD_REJ_CTL_IN_HDR             0x00000400
 #define HTTP_HRD_REJ_CL_TE                  0x00000800
+#define HTTP_HRD_REJ_CL_LEAD_ZERO           0x00001000
 /* insert new masks above this line */
 #define HTTP_HRD_ALL                        0xFFFFFFFF
 
index fa8ffb4294b5cc9a9d2474d32534e237a91a368b..e4b7c4306fe55005f41d875c6bafd090034acf22 100644 (file)
@@ -813,7 +813,10 @@ int http_parse_cont_len_header(struct ist *value, unsigned long long *body_len,
                        if (unlikely(!cl && n > word.ptr)) {
                                /* There was a leading zero before this digit,
                                 * let's trim it.
+                                * In strict mode we reject it though.
                                 */
+                               if (http_harden(HTTP_HRD_REJ_CL_LEAD_ZERO))
+                                       goto fail;
                                word.ptr = n;
                        }
 
@@ -1787,6 +1790,7 @@ const struct http_hardening_kw http_hardening_kws[] = {
        { "reject-header-trailer-folding",     HTTP_HRD_REJ_HDR_FOLD, HTTP_DIR_BOTH },
        { "reject-ctl-in-header-trailer",      HTTP_HRD_REJ_CTL_IN_HDR, HTTP_DIR_BOTH },
        { "reject-content-length-with-te",     HTTP_HRD_REJ_CL_TE, HTTP_DIR_BOTH },
+       { "reject-content-length-leading-zero",HTTP_HRD_REJ_CL_LEAD_ZERO, HTTP_DIR_BOTH },
        /* insert new hardening options above this line */
        { "all",                            HTTP_HRD_ALL,              HTTP_DIR_BOTH },
        { NULL, 0 }