haproxy.git
2 months agoBUG/MINOR: h3: reject more chars from the :path pseudo header
Willy Tarreau [Tue, 8 Aug 2023 15:54:26 +0000 (17:54 +0200)]
BUG/MINOR: h3: reject more chars from the :path pseudo header

Origin: https://git.haproxy.org/?p=haproxy-2.6.git;a=commit;h=eacaa76e7b0e4182dfd17e1e7ca8c02c1cdab72c

This is the h3 version of this previous fix:

   BUG/MINOR: h2: reject more chars from the :path pseudo header

In addition to the current NUL/CR/LF, this will also reject all other
control chars, the space and '#' from the :path pseudo-header, to avoid
taking the '#' for a part of the path. It's still possible to fall back
to the previous behavior using "option accept-invalid-http-request".

Here the :path header value is scanned a second time to look for
forbidden chars because we don't know upfront if we're dealing with a
path header field or another one. This is no big deal anyway for now.

This should be progressively backported to 2.6, along with the
following commits it relies on (the same as for h2):

   REGTESTS: http-rules: add accept-invalid-http-request for normalize-uri tests
   REORG: http: move has_forbidden_char() from h2.c to http.h
   MINOR: ist: add new function ist_find_range() to find a character range
   MINOR: http: add new function http_path_has_forbidden_char()

(cherry picked from commit 2e97857a845540887a92029a566deb5b51f61d0b)
Signed-off-by: Amaury Denoyelle <adenoyelle@haproxy.com>
(cherry picked from commit 96dfea858edab8f1f63fa6e4df43f505b81fdad9)
Signed-off-by: Amaury Denoyelle <adenoyelle@haproxy.com>
(cherry picked from commit 97c15782afd9c70281ff0c72971485227494cc12)
Signed-off-by: Amaury Denoyelle <adenoyelle@haproxy.com>
Gbp-Pq: Name BUG-MINOR-h3-reject-more-chars-from-the-path-pseudo-.patch

2 months agoBUG/MINOR: h2: reject more chars from the :path pseudo header
Willy Tarreau [Tue, 8 Aug 2023 13:40:49 +0000 (15:40 +0200)]
BUG/MINOR: h2: reject more chars from the :path pseudo header

Origin: https://git.haproxy.org/?p=haproxy-2.6.git;a=commit;h=c8e07f2fd8b5462527f102f7145d6027c0d041da

This is the h2 version of this previous fix:

    BUG/MINOR: h1: do not accept '#' as part of the URI component

In addition to the current NUL/CR/LF, this will also reject all other
control chars, the space and '#' from the :path pseudo-header, to avoid
taking the '#' for a part of the path. It's still possible to fall back
to the previous behavior using "option accept-invalid-http-request".

This patch modifies the request parser to change the ":path" pseudo header
validation function with a new one that rejects 0x00-0x1F (control chars),
space and '#'. This way such chars will be dropped early in the chain, and
the search for '#' doesn't incur a second pass over the header's value.

This should be progressively backported to stable versions, along with the
following commits it relies on:

     REGTESTS: http-rules: add accept-invalid-http-request for normalize-uri tests
     REORG: http: move has_forbidden_char() from h2.c to http.h
     MINOR: ist: add new function ist_find_range() to find a character range
     MINOR: http: add new function http_path_has_forbidden_char()
     MINOR: h2: pass accept-invalid-http-request down the request parser

(cherry picked from commit b3119d4fb4588087e2483a80b01d322683719e29)
Signed-off-by: Amaury Denoyelle <adenoyelle@haproxy.com>
(cherry picked from commit 462a8600ce9e478573a957e046b446a7dcffd286)
Signed-off-by: Amaury Denoyelle <adenoyelle@haproxy.com>
(cherry picked from commit 648e59e30723b8fd4e71aab02cb679f6ea7446e7)
Signed-off-by: Amaury Denoyelle <adenoyelle@haproxy.com>
Gbp-Pq: Name BUG-MINOR-h2-reject-more-chars-from-the-path-pseudo-.patch

2 months agoBUG/MINOR: h1: do not accept '#' as part of the URI component
Willy Tarreau [Tue, 8 Aug 2023 14:17:22 +0000 (16:17 +0200)]
BUG/MINOR: h1: do not accept '#' as part of the URI component

Origin: https://git.haproxy.org/?p=haproxy-2.6.git;a=commit;h=832b672eee54866c7a42a1d46078cc9ae0d544d9
Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2023-45539

Seth Manesse and Paul Plasil reported that the "path" sample fetch
function incorrectly accepts '#' as part of the path component. This
can in some cases lead to misrouted requests for rules that would apply
on the suffix:

    use_backend static if { path_end .png .jpg .gif .css .js }

Note that this behavior can be selectively configured using
"normalize-uri fragment-encode" and "normalize-uri fragment-strip".

The problem is that while the RFC says that this '#' must never be
emitted, as often it doesn't suggest how servers should handle it. A
diminishing number of servers still do accept it and trim it silently,
while others are rejecting it, as indicated in the conversation below
with other implementers:

   https://lists.w3.org/Archives/Public/ietf-http-wg/2023JulSep/0070.html

Looking at logs from publicly exposed servers, such requests appear at
a rate of roughly 1 per million and only come from attacks or poorly
written web crawlers incorrectly following links found on various pages.

Thus it looks like the best solution to this problem is to simply reject
such ambiguous requests by default, and include this in the list of
controls that can be disabled using "option accept-invalid-http-request".

We're already rejecting URIs containing any control char anyway, so we
should also reject '#'.

In the H1 parser for the H1_MSG_RQURI state, there is an accelerated
parser for bytes 0x21..0x7e that has been tightened to 0x24..0x7e (it
should not impact perf since 0x21..0x23 are not supposed to appear in
a URI anyway). This way '#' falls through the fine-grained filter and
we can add the special case for it also conditionned by a check on the
proxy's option "accept-invalid-http-request", with no overhead for the
vast majority of valid URIs. Here this information is available through
h1m->err_pos that's set to -2 when the option is here (so we don't need
to change the API to expose the proxy). Example with a trivial GET
through netcat:

  [08/Aug/2023:16:16:52.651] frontend layer1 (#2): invalid request
    backend <NONE> (#-1), server <NONE> (#-1), event #0, src 127.0.0.1:50812
    buffer starts at 0 (including 0 out), 16361 free,
    len 23, wraps at 16336, error at position 7
    H1 connection flags 0x00000000, H1 stream flags 0x00000810
    H1 msg state MSG_RQURI(4), H1 msg flags 0x00001400
    H1 chunk len 0 bytes, H1 body len 0 bytes :

    00000  GET /aa#bb HTTP/1.0\r\n
    00021  \r\n

This should be progressively backported to all stable versions along with
the following patch:

    REGTESTS: http-rules: add accept-invalid-http-request for normalize-uri tests

Similar fixes for h2 and h3 will come in followup patches.

Thanks to Seth Manesse and Paul Plasil for reporting this problem with
detailed explanations.

(cherry picked from commit 2eab6d354322932cfec2ed54de261e4347eca9a6)
Signed-off-by: Amaury Denoyelle <adenoyelle@haproxy.com>
(cherry picked from commit 9bf75c8e22a8f2537f27c557854a8803087046d0)
Signed-off-by: Amaury Denoyelle <adenoyelle@haproxy.com>
(cherry picked from commit 9facd01c9ac85fe9bcb331594b80fa08e7406552)
Signed-off-by: Amaury Denoyelle <adenoyelle@haproxy.com>
Gbp-Pq: Name BUG-MINOR-h1-do-not-accept-as-part-of-the-URI-compon.patch

2 months agoREGTESTS: http-rules: add accept-invalid-http-request for normalize-uri tests
Willy Tarreau [Tue, 8 Aug 2023 17:52:45 +0000 (19:52 +0200)]
REGTESTS: http-rules: add accept-invalid-http-request for normalize-uri tests

Origin: https://git.haproxy.org/?p=haproxy-2.6.git;a=commit;h=65849396fd6f192d9f14e81702c6c3851e580345

We'll soon block the '#' by default so let's prepare the test to continue
to work.

(cherry picked from commit 069d0e221e58a46119d7c049bb07fa4bcb8d0075)
 [ad: backported for following fix : BUG/MINOR: h2: reject more chars
  from the :path pseudo header]
Signed-off-by: Amaury Denoyelle <adenoyelle@haproxy.com>
(cherry picked from commit 1660481fab69856a39ac44cf88b76cdbcc0ea954)
Signed-off-by: Amaury Denoyelle <adenoyelle@haproxy.com>
(cherry picked from commit 90d0300cea6cda18a4e20369f4dc0b4c4783d6c9)
Signed-off-by: Amaury Denoyelle <adenoyelle@haproxy.com>
Gbp-Pq: Name REGTESTS-http-rules-add-accept-invalid-http-request-.patch

2 months agoMINOR: h2: pass accept-invalid-http-request down the request parser
Willy Tarreau [Tue, 8 Aug 2023 13:38:28 +0000 (15:38 +0200)]
MINOR: h2: pass accept-invalid-http-request down the request parser

Origin: https://git.haproxy.org/?p=haproxy-2.6.git;a=commit;h=014945a1508f43e88ac4e89950fa9037e4fb0679

We're adding a new argument "relaxed" to h2_make_htx_request() so that
we can control its level of acceptance of certain invalid requests at
the proxy level with "option accept-invalid-http-request". The goal
will be to add deactivable checks that are still desirable to have by
default. For now no test is subject to it.

(cherry picked from commit d93a00861d714313faa0395ff9e2acb14b0a2fca)
 [ad: backported for following fix : BUG/MINOR: h2: reject more chars
  from the :path pseudo header]
Signed-off-by: Amaury Denoyelle <adenoyelle@haproxy.com>
(cherry picked from commit b6be1a4f858eb6602490c192235114c1a163fef9)
Signed-off-by: Amaury Denoyelle <adenoyelle@haproxy.com>
(cherry picked from commit 26fa3a285df0748fc79e73e552161268b66fb527)
Signed-off-by: Amaury Denoyelle <adenoyelle@haproxy.com>
Gbp-Pq: Name MINOR-h2-pass-accept-invalid-http-request-down-the-r.patch

2 months agoMINOR: http: add new function http_path_has_forbidden_char()
Willy Tarreau [Tue, 8 Aug 2023 13:24:54 +0000 (15:24 +0200)]
MINOR: http: add new function http_path_has_forbidden_char()

Origin: https://git.haproxy.org/?p=haproxy-2.6.git;a=commit;h=c699bb17b7e334c9d56e829422e29e5a204615ec

As its name implies, this function checks if a path component has any
forbidden headers starting at the designated location. The goal is to
seek from the result of a successful ist_find_range() for more precise
chars. Here we're focusing on 0x00-0x1F, 0x20 and 0x23 to make sure
we're not too strict at this point.

(cherry picked from commit 30f58f4217d585efeac3d85cb1b695ba53b7760b)
 [ad: backported for following fix : BUG/MINOR: h2: reject more chars
  from the :path pseudo header]
Signed-off-by: Amaury Denoyelle <adenoyelle@haproxy.com>
(cherry picked from commit b491940181a88bb6c69ab2afc24b93a50adfa67c)
Signed-off-by: Amaury Denoyelle <adenoyelle@haproxy.com>
(cherry picked from commit f7666e5e43ce63e804ebffdf224d92cfd3367282)
Signed-off-by: Amaury Denoyelle <adenoyelle@haproxy.com>
Gbp-Pq: Name MINOR-http-add-new-function-http_path_has_forbidden_.patch

2 months agoMINOR: ist: add new function ist_find_range() to find a character range
Willy Tarreau [Tue, 8 Aug 2023 13:23:19 +0000 (15:23 +0200)]
MINOR: ist: add new function ist_find_range() to find a character range

Origin: https://git.haproxy.org/?p=haproxy-2.6.git;a=commit;h=b375df60341c7f7a4904c2d8041a09c66115c754

This looks up the character range <min>..<max> in the input string and
returns a pointer to the first one found. It's essentially the equivalent
of ist_find_ctl() in that it searches by 32 or 64 bits at once, but deals
with a range.

(cherry picked from commit 197668de975e495f0c0f0e4ff51b96203fa9842d)
 [ad: backported for following fix : BUG/MINOR: h2: reject more chars
 from the :path pseudo header]
Signed-off-by: Amaury Denoyelle <adenoyelle@haproxy.com>
(cherry picked from commit 451ac6628acc4b9eed3260501a49c60d4e4d4e55)
Signed-off-by: Amaury Denoyelle <adenoyelle@haproxy.com>
(cherry picked from commit 3468f7f8e04c9c5ca5c985c7511e05e78fe1eded)
Signed-off-by: Amaury Denoyelle <adenoyelle@haproxy.com>
Gbp-Pq: Name MINOR-ist-add-new-function-ist_find_range-to-find-a-.patch

2 months agoBUG/MAJOR: http: reject any empty content-length header value
Willy Tarreau [Wed, 9 Aug 2023 06:32:48 +0000 (08:32 +0200)]
BUG/MAJOR: http: reject any empty content-length header value

Origin: https://git.haproxy.org/?p=haproxy-2.6.git;a=commit;h=d17c50010d591d1c070e1cb0567a06032d8869e9
Bug-Debian: https://bugs.debian.org/1043502
Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2023-40225

The content-length header parser has its dedicated function, in order
to take extreme care about invalid, unparsable, or conflicting values.
But there's a corner case in it, by which it stops comparing values
when reaching the end of the header. This has for a side effect that
an empty value or a value that ends with a comma does not deserve
further analysis, and it acts as if the header was absent.

While this is not necessarily a problem for the value ending with a
comma as it will be cause a header folding and will disappear, it is a
problem for the first isolated empty header because this one will not
be recontructed when next ones are seen, and will be passed as-is to the
backend server. A vulnerable HTTP/1 server hosted behind haproxy that
would just use this first value as "0" and ignore the valid one would
then not be protected by haproxy and could be attacked this way, taking
the payload for an extra request.

In field the risk depends on the server. Most commonly used servers
already have safe content-length parsers, but users relying on haproxy
to protect a known-vulnerable server might be at risk (and the risk of
a bug even in a reputable server should never be dismissed).

A configuration-based work-around consists in adding the following rule
in the frontend, to explicitly reject requests featuring an empty
content-length header that would have not be folded into an existing
one:

    http-request deny if { hdr_len(content-length) 0 }

The real fix consists in adjusting the parser so that it always expects a
value at the beginning of the header or after a comma. It will now reject
requests and responses having empty values anywhere in the C-L header.

This needs to be backported to all supported versions. Note that the
modification was made to functions h1_parse_cont_len_header() and
http_parse_cont_len_header(). Prior to 2.8 the latter was in
h2_parse_cont_len_header(). One day the two should be refused but the
former is also used by Lua.

The HTTP messaging reg-tests were completed to test these cases.

Thanks to Ben Kallus of Dartmouth College and Narf Industries for
reporting this! (this is in GH #2237).

(cherry picked from commit 6492f1f29d738457ea9f382aca54537f35f9d856)
Signed-off-by: Amaury Denoyelle <adenoyelle@haproxy.com>
(cherry picked from commit a32f99f6f991d123ea3e307bf8aa63220836d365)
Signed-off-by: Amaury Denoyelle <adenoyelle@haproxy.com>
(cherry picked from commit 65921ee12d88e9fb1fa9f6cd8198fd64b3a3f37f)
Signed-off-by: Amaury Denoyelle <adenoyelle@haproxy.com>
Gbp-Pq: Name BUG-MAJOR-http-reject-any-empty-content-length-heade.patch

2 months agoBUG/MAJOR: h3: reject header values containing invalid chars
Willy Tarreau [Tue, 8 Aug 2023 15:18:27 +0000 (17:18 +0200)]
BUG/MAJOR: h3: reject header values containing invalid chars

Origin: https://git.haproxy.org/?p=haproxy-2.6.git;a=commit;h=20a35c4d505475215122d37405ce173075338032

In practice it's exactly the same for h3 as 54f53ef7c ("BUG/MAJOR: h2:
reject header values containing invalid chars") was for h2: we must
make sure never to accept NUL/CR/LF in any header value because this
may be used to construct splitted headers on the backend. Hence we
apply the same solution. Here pseudo-headers, headers and trailers are
checked separately, which explains why we have 3 locations instead of
2 for h2 (+1 for response which we don't have here).

This is marked major for consistency and due to the impact if abused,
but the reality is that at the time of writing, this problem is limited
by the scarcity of the tools which would permit to build such a request
in the first place. But this may change over time.

This must be backported to 2.6. This depends on the following commit
that exposes the filtering function:

    REORG: http: move has_forbidden_char() from h2.c to http.h

(cherry picked from commit d13a80abb7c1badaa42045c37cfff79f24f05726)
Signed-off-by: Amaury Denoyelle <adenoyelle@haproxy.com>
(cherry picked from commit 0404bf14c900d6ac879ec432a198435e0741d835)
Signed-off-by: Amaury Denoyelle <adenoyelle@haproxy.com>
(cherry picked from commit f58b63af68f239464c29e698a34f08ff3eef862f)
 [ad: no http/3 trailer support in 2.6]
Signed-off-by: Amaury Denoyelle <adenoyelle@haproxy.com>
Gbp-Pq: Name BUG-MAJOR-h3-reject-header-values-containing-invalid.patch

2 months agoREORG: http: move has_forbidden_char() from h2.c to http.h
Willy Tarreau [Tue, 8 Aug 2023 15:00:50 +0000 (17:00 +0200)]
REORG: http: move has_forbidden_char() from h2.c to http.h

Origin: https://git.haproxy.org/?p=haproxy-2.6.git;a=commit;h=4a776fd01560a8dfa7a57b30b4d5249c8da7b12c

This function is not H2 specific but rather generic to HTTP. We'll
need it in H3 soon, so let's move it to HTTP and rename it to
http_header_has_forbidden_char().

(cherry picked from commit d4069f3cee0f6e94afaec518b6373dd368073f52)
 [ad: backported for next patch BUG/MAJOR: h3: reject header values
 containing invalid chars]
Signed-off-by: Amaury Denoyelle <adenoyelle@haproxy.com>
(cherry picked from commit 21c4ffd025115058994a3e2765c17fc3cee52f90)
Signed-off-by: Amaury Denoyelle <adenoyelle@haproxy.com>
(cherry picked from commit 9c0bc4f201cf58c10706416cb4807c0f4794f8ac)
Signed-off-by: Amaury Denoyelle <adenoyelle@haproxy.com>
Gbp-Pq: Name REORG-http-move-has_forbidden_char-from-h2.c-to-http.patch

2 months agoreproducible
Debian HAProxy Maintainers [Fri, 3 Oct 2025 06:03:00 +0000 (08:03 +0200)]
reproducible

Gbp-Pq: Name reproducible.patch

2 months agohaproxy.service: make systemd bind /dev/log inside chroot
Vincent Bernat [Thu, 25 Nov 2021 20:35:48 +0000 (21:35 +0100)]
haproxy.service: make systemd bind /dev/log inside chroot

This enables logging to work without rsyslog being present.

Gbp-Pq: Name haproxy.service-make-systemd-bind-dev-log-inside-chroot.patch

2 months agoAdd documentation field to the systemd unit
Debian HAProxy Maintainers [Sun, 25 Mar 2018 09:31:50 +0000 (11:31 +0200)]
Add documentation field to the systemd unit

Forwarded: no
Last-Update: 2014-01-03

Gbp-Pq: Name haproxy.service-add-documentation.patch

2 months agoStart after rsyslog.service
Apollon Oikonomopoulos [Sun, 25 Mar 2018 09:31:50 +0000 (11:31 +0200)]
Start after rsyslog.service

As HAProxy is running chrooted by default, we rely on an additional syslog
socket created by rsyslog inside the chroot for logging. As this socket cannot
trigger syslog activation, we explicitly order HAProxy after rsyslog.service.
Note that we are not using syslog.service here, since the additional socket is
rsyslog-specific.
Forwarded: no
Last-Update: 2017-12-01

Gbp-Pq: Name haproxy.service-start-after-syslog.patch

2 months agohaproxy (2.6.12-1+deb12u3) bookworm-security; urgency=high
Vincent Bernat [Fri, 3 Oct 2025 06:03:00 +0000 (08:03 +0200)]
haproxy (2.6.12-1+deb12u3) bookworm-security; urgency=high

  * CVE-2025-11230: fix possible DoS when parsing JSON numbers.

[dgit import unpatched haproxy 2.6.12-1+deb12u3]

2 months agoImport haproxy_2.6.12-1+deb12u3.debian.tar.xz
Vincent Bernat [Fri, 3 Oct 2025 06:03:00 +0000 (08:03 +0200)]
Import haproxy_2.6.12-1+deb12u3.debian.tar.xz

[dgit import tarball haproxy 2.6.12-1+deb12u3 haproxy_2.6.12-1+deb12u3.debian.tar.xz]

2 years agoImport haproxy_2.6.12.orig.tar.gz
Vincent Bernat [Sat, 1 Apr 2023 09:05:57 +0000 (11:05 +0200)]
Import haproxy_2.6.12.orig.tar.gz

[dgit import orig haproxy_2.6.12.orig.tar.gz]