From 473988d9ab162634de240a1834cd5e90a34c197a Mon Sep 17 00:00:00 2001 From: Ryan O'Hara Date: Tue, 6 Jun 2023 10:56:45 -0500 Subject: [PATCH] Update to 2.4.22 Resolves: #2196530 --- ...1140-refuse-response-end-stream-flag.patch | 52 ------ ...9510-reject-empty-http-header-fields.patch | 164 ------------------ ...cgi-fix-uninitialized-reserved-bytes.patch | 51 ------ haproxy.spec | 14 +- sources | 2 +- 5 files changed, 6 insertions(+), 277 deletions(-) delete mode 100644 bz2161140-refuse-response-end-stream-flag.patch delete mode 100644 bz2169510-reject-empty-http-header-fields.patch delete mode 100644 bz2180861-fcgi-fix-uninitialized-reserved-bytes.patch diff --git a/bz2161140-refuse-response-end-stream-flag.patch b/bz2161140-refuse-response-end-stream-flag.patch deleted file mode 100644 index e3e83d9..0000000 --- a/bz2161140-refuse-response-end-stream-flag.patch +++ /dev/null @@ -1,52 +0,0 @@ -From 2c681c6f30fb90adab4701e287ff7a7db669b2e7 Mon Sep 17 00:00:00 2001 -From: Christopher Faulet -Date: Thu, 22 Dec 2022 09:47:01 +0100 -Subject: [PATCH] BUG/MEDIUM: mux-h2: Refuse interim responses with end-stream - flag set - -As state in RFC9113#8.1, HEADERS frame with the ES flag set that carries an -informational status code is malformed. However, there is no test on this -condition. - -On 2.4 and higher, it is hard to predict consequences of this bug because -end of the message is only reported with a flag. But on 2.2 and lower, it -leads to a crash because there is an unexpected extra EOM block at the end -of an interim response. - -Now, when a ES flag is detected on a HEADERS frame for an interim message, a -stream error is sent (RST_STREAM/PROTOCOL_ERROR). - -This patch should solve the issue #1972. It should be backported as far as -2.0. - -(cherry picked from commit 827a6299e6995c5c3ba620d8b7cbacdaef67f2c4) -Signed-off-by: Willy Tarreau -(cherry picked from commit ebfae006c6b5de1d1fe0cdd51847ec1e39d5cf59) -Signed-off-by: Christopher Faulet -(cherry picked from commit 84f5cba24f59b1c8339bb38323fcb01f434ba8e5) -Signed-off-by: Christopher Faulet -(cherry picked from commit f5748a98c34bc889cae9386ca4f7073ab3f4c6b1) -Signed-off-by: Christopher Faulet ---- - src/mux_h2.c | 5 +++++ - 1 file changed, 5 insertions(+) - -diff --git a/src/mux_h2.c b/src/mux_h2.c -index 7d23e5abd..7dbbfefec 100644 ---- a/src/mux_h2.c -+++ b/src/mux_h2.c -@@ -4942,6 +4942,11 @@ static int h2c_decode_headers(struct h2c *h2c, struct buffer *rxbuf, uint32_t *f - *flags |= H2_SF_HEADERS_RCVD; - - if (h2c->dff & H2_F_HEADERS_END_STREAM) { -+ if (msgf & H2_MSGF_RSP_1XX) { -+ /* RFC9113#8.1 : HEADERS frame with the ES flag set that carries an informational status code is malformed */ -+ TRACE_STATE("invalid interim response with ES flag!", H2_EV_RX_FRAME|H2_EV_RX_HDR|H2_EV_H2C_ERR|H2_EV_PROTO_ERR, h2c->conn); -+ goto fail; -+ } - /* no more data are expected for this message */ - htx->flags |= HTX_FL_EOM; - } --- -2.37.3 - diff --git a/bz2169510-reject-empty-http-header-fields.patch b/bz2169510-reject-empty-http-header-fields.patch deleted file mode 100644 index 5623d7a..0000000 --- a/bz2169510-reject-empty-http-header-fields.patch +++ /dev/null @@ -1,164 +0,0 @@ -From 486cd730485c8a119ef65b3f792134b56e7941b4 Mon Sep 17 00:00:00 2001 -From: Willy Tarreau -Date: Thu, 9 Feb 2023 21:36:54 +0100 -Subject: [PATCH] BUG/CRITICAL: http: properly reject empty http header field - names - -The HTTP header parsers surprizingly accepts empty header field names, -and this is a leftover from the original code that was agnostic to this. - -When muxes were introduced, for H2 first, the HPACK decompressor needed -to feed headers lists, and since empty header names were strictly -forbidden by the protocol, the lists of headers were purposely designed -to be terminated by an empty header field name (a principle that is -similar to H1's empty line termination). This principle was preserved -and generalized to other protocols migrated to muxes (H1/FCGI/H3 etc) -without anyone ever noticing that the H1 parser was still able to deliver -empty header field names to this list. In addition to this it turns out -that the HPACK decompressor, despite a comment in the code, may -successfully decompress an empty header field name, and this mistake -was propagated to the QPACK decompressor as well. - -The impact is that an empty header field name may be used to truncate -the list of headers and thus make some headers disappear. While for -H2/H3 the impact is limited as haproxy sees a request with missing -headers, and headers are not used to delimit messages, in the case of -HTTP/1, the impact is significant because the presence (and sometimes -contents) of certain sensitive headers is detected during the parsing. -Thus, some of these headers may be seen, marked as present, their value -extracted, but never delivered to upper layers and obviously not -forwarded to the other side either. This can have for consequence that -certain important header fields such as Connection, Upgrade, Host, -Content-length, Transfer-Encoding etc are possibly seen as different -between what haproxy uses to parse/forward/route and what is observed -in http-request rules and of course, forwarded. One direct consequence -is that it is possible to exploit this property in HTTP/1 to make -affected versions of haproxy forward more data than is advertised on -the other side, and bypass some access controls or routing rules by -crafting extraneous requests. Note, however, that responses to such -requests will normally not be passed back to the client, but this can -still cause some harm. - -This specific risk can be mostly worked around in configuration using -the following rule that will rely on the bug's impact to precisely -detect the inconsistency between the known body size and the one -expected to be advertised to the server (the rule works from 2.0 to -2.8-dev): - - http-request deny if { fc_http_major 1 } !{ req.body_size 0 } !{ req.hdr(content-length) -m found } !{ req.hdr(transfer-encoding) -m found } !{ method CONNECT } - -This will exclusively block such carefully crafted requests delivered -over HTTP/1. HTTP/2 and HTTP/3 do not need content-length, and a body -that arrives without being announced with a content-length will be -forwarded using transfer-encoding, hence will not cause discrepancies. -In HAProxy 2.0 in legacy mode ("no option http-use-htx"), this rule will -simply have no effect but will not cause trouble either. - -A clean solution would consist in modifying the loops iterating over -these headers lists to check the header name's pointer instead of its -length (since both are zero at the end of the list), but this requires -to touch tens of places and it's very easy to miss one. Functions such -as htx_add_header(), htx_add_trailer(), htx_add_all_headers() would be -good starting points for such a possible future change. - -Instead the current fix focuses on blocking empty headers where they -are first inserted, hence in the H1/HPACK/QPACK decoders. One benefit -of the current solution (for H1) is that it allows "show errors" to -report a precise diagnostic when facing such invalid HTTP/1 requests, -with the exact location of the problem and the originating address: - - $ printf "GET / HTTP/1.1\r\nHost: localhost\r\n:empty header\r\n\r\n" | nc 0 8001 - HTTP/1.1 400 Bad request - Content-length: 90 - Cache-Control: no-cache - Connection: close - Content-Type: text/html - -

400 Bad request

- Your browser sent an invalid request. - - - $ socat /var/run/haproxy.stat <<< "show errors" - Total events captured on [10/Feb/2023:16:29:37.530] : 1 - - [10/Feb/2023:16:29:34.155] frontend decrypt (#2): invalid request - backend (#-1), server (#-1), event #0, src 127.0.0.1:31092 - buffer starts at 0 (including 0 out), 16334 free, - len 50, wraps at 16336, error at position 33 - H1 connection flags 0x00000000, H1 stream flags 0x00000810 - H1 msg state MSG_HDR_NAME(17), H1 msg flags 0x00001410 - H1 chunk len 0 bytes, H1 body len 0 bytes : - - 00000 GET / HTTP/1.1\r\n - 00016 Host: localhost\r\n - 00033 :empty header\r\n - 00048 \r\n - -I want to address sincere and warm thanks for their great work to the -team composed of the following security researchers who found the issue -together and reported it: Bahruz Jabiyev, Anthony Gavazzi, and Engin -Kirda from Northeastern University, Kaan Onarlioglu from Akamai -Technologies, Adi Peleg and Harvey Tuch from Google. And kudos to Amaury -Denoyelle from HAProxy Technologies for spotting that the HPACK and -QPACK decoders would let this pass despite the comment explicitly -saying otherwise. - -This fix must be backported as far as 2.0. The QPACK changes can be -dropped before 2.6. In 2.0 there is also the equivalent code for legacy -mode, which doesn't suffer from the list truncation, but it would better -be fixed regardless. - -CVE-2023-25725 was assigned to this issue. - -(cherry picked from commit a8598a2eb11b6c989e81f0dbf10be361782e8d32) -Signed-off-by: Willy Tarreau -(cherry picked from commit a0e561ad7f29ed50c473f5a9da664267b60d1112) -Signed-off-by: Willy Tarreau -(cherry picked from commit 73be199c4f5f1ed468161a4c5e10ca77cd5989d8) -[wt: dropped QPACK changes for 2.5] -Signed-off-by: Willy Tarreau -(cherry picked from commit f8b2b88aeae15dc3b261cd3749277ae75caf9db8) -Signed-off-by: Willy Tarreau ---- - src/h1.c | 4 ++++ - src/hpack-dec.c | 9 +++++++++ - 2 files changed, 13 insertions(+) - -diff --git a/src/h1.c b/src/h1.c -index 4c2e234c5..73de48be0 100644 ---- a/src/h1.c -+++ b/src/h1.c -@@ -750,6 +750,10 @@ int h1_headers_to_hdr_list(char *start, const char *stop, - - if (likely(*ptr == ':')) { - col = ptr - start; -+ if (col <= sol) { -+ state = H1_MSG_HDR_NAME; -+ goto http_msg_invalid; -+ } - EAT_AND_JUMP_OR_RETURN(ptr, end, http_msg_hdr_l1_sp, http_msg_ood, state, H1_MSG_HDR_L1_SP); - } - -diff --git a/src/hpack-dec.c b/src/hpack-dec.c -index 04f3d9ffa..ed39007d1 100644 ---- a/src/hpack-dec.c -+++ b/src/hpack-dec.c -@@ -420,6 +420,15 @@ int hpack_decode_frame(struct hpack_dht *dht, const uint8_t *raw, uint32_t len, - /* and are correctly filled here */ - } - -+ /* We must not accept empty header names (forbidden by the spec and used -+ * as a list termination). -+ */ -+ if (!name.len) { -+ hpack_debug_printf("##ERR@%d##\n", __LINE__); -+ ret = -HPACK_ERR_INVALID_ARGUMENT; -+ goto leave; -+ } -+ - /* here's what we have here : - * - name.len > 0 - * - value is filled with either const data or data allocated from tmp --- -2.37.3 - diff --git a/bz2180861-fcgi-fix-uninitialized-reserved-bytes.patch b/bz2180861-fcgi-fix-uninitialized-reserved-bytes.patch deleted file mode 100644 index b38256a..0000000 --- a/bz2180861-fcgi-fix-uninitialized-reserved-bytes.patch +++ /dev/null @@ -1,51 +0,0 @@ -From 0c86fce8028d409de4181e82eec967cfb1e6268e Mon Sep 17 00:00:00 2001 -From: Youfu Zhang -Date: Fri, 9 Dec 2022 19:15:48 +0800 -Subject: [PATCH] BUG/MAJOR: fcgi: Fix uninitialized reserved bytes - -The output buffer is not zero-initialized. If we don't clear reserved -bytes, fcgi requests sent to backend will leak sensitive data. - -This patch must be backported as far as 2.2. - -(cherry picked from commit 2e6bf0a2722866ae0128a4392fa2375bd1f03ff8) -Signed-off-by: Christopher Faulet -(cherry picked from commit db03179fee55c60a92ce6b86a0f04dbb9ba0328b) -Signed-off-by: Christopher Faulet -(cherry picked from commit f988992d16f45ef03d5bbb024a1042ed8123e4c5) -Signed-off-by: Christopher Faulet -(cherry picked from commit 0dc4cdc276d4a0e3347b7c3c4aedca2a2e0ab428) -Signed-off-by: Christopher Faulet ---- - src/fcgi.c | 8 ++++++-- - 1 file changed, 6 insertions(+), 2 deletions(-) - -diff --git a/src/fcgi.c b/src/fcgi.c -index 1c2543def..778ce9e25 100644 ---- a/src/fcgi.c -+++ b/src/fcgi.c -@@ -47,7 +47,7 @@ int fcgi_encode_record_hdr(struct buffer *out, const struct fcgi_header *h) - out->area[len++] = ((h->len >> 8) & 0xff); - out->area[len++] = (h->len & 0xff); - out->area[len++] = h->padding; -- len++; /* rsv */ -+ out->area[len++] = 0; /* rsv */ - - out->data = len; - return 1; -@@ -94,7 +94,11 @@ int fcgi_encode_begin_request(struct buffer *out, const struct fcgi_begin_reques - out->area[len++] = ((r->role >> 8) & 0xff); - out->area[len++] = (r->role & 0xff); - out->area[len++] = r->flags; -- len += 5; /* rsv */ -+ out->area[len++] = 0; /* rsv */ -+ out->area[len++] = 0; -+ out->area[len++] = 0; -+ out->area[len++] = 0; -+ out->area[len++] = 0; - - out->data = len; - return 1; --- -2.39.2 - diff --git a/haproxy.spec b/haproxy.spec index f5a15f3..fca9d6b 100644 --- a/haproxy.spec +++ b/haproxy.spec @@ -7,8 +7,8 @@ %global _hardened_build 1 Name: haproxy -Version: 2.4.17 -Release: 7%{?dist} +Version: 2.4.22 +Release: 1%{?dist} Summary: HAProxy reverse proxy for high availability environments License: GPLv2+ @@ -22,10 +22,6 @@ Source4: %{name}.sysconfig Source5: %{name}.sysusers Source6: halog.1 -Patch0: bz2161140-refuse-response-end-stream-flag.patch -Patch1: bz2169510-reject-empty-http-header-fields.patch -Patch2: bz2180861-fcgi-fix-uninitialized-reserved-bytes.patch - BuildRequires: gcc BuildRequires: lua-devel BuildRequires: pcre2-devel @@ -54,9 +50,6 @@ availability environments. Indeed, it can: %prep %setup -q -%patch0 -p1 -%patch1 -p1 -%patch2 -p1 %build regparm_opts= @@ -139,6 +132,9 @@ done %{_sysusersdir}/%{name}.conf %changelog +* Tue Jun 06 2023 Ryan O'Hara - 2.4.22-1 +- Update to 2.4.22 (#2196530) + * Tue May 02 2023 Ryan O'Hara - 2.4.17-7 - Fix uninitizalized resevered bytes (CVE-2023-0836, #2180861) diff --git a/sources b/sources index 50ab96e..0493cf4 100644 --- a/sources +++ b/sources @@ -1 +1 @@ -SHA512 (haproxy-2.4.17.tar.gz) = 98d46b6dbafd95977a32a6479266f3b9fe6e6ed57e39182a3d031add60dabfdaa7494083109a75eaa3e4b15d0293b11081f9b06556eee1777ede40ed6c002a7f +SHA512 (haproxy-2.4.22.tar.gz) = c22ad38046e3c70beb3bf57a62e4e74db329559059e2f36d2f801768c26b1f1222631702e83e9839fab4396c1b78089a807750ff743b4192da06c751cf9f0779