Compare commits

...

10 Commits

Author SHA1 Message Date
openeuler-ci-bot
29cd96f4b1
!128 backport upstream patches
From: @xinghe_1 
Reviewed-by: @wu-leilei 
Signed-off-by: @wu-leilei
2024-06-27 08:20:59 +00:00
xh
3ce43447d9 backport upstream patches 2024-06-24 09:28:57 +00:00
openeuler-ci-bot
9021ac06be
!95 Fix CVE-2023-45539
From: @starlet-dx 
Reviewed-by: @wu-leilei 
Signed-off-by: @wu-leilei
2023-12-06 09:00:22 +00:00
starlet-dx
0f0329de3e Fix CVE-2023-45539 2023-12-06 16:09:38 +08:00
openeuler-ci-bot
eb3e775bfa
!90 Fix CVE-2023-0836
From: @li_ning_jie 
Reviewed-by: @wu-leilei 
Signed-off-by: @wu-leilei
2023-12-06 08:05:34 +00:00
liningjie
0614a9b80f Fix CVE-2023-0836 2023-12-01 13:54:35 +08:00
openeuler-ci-bot
82e7a81403
!76 [sync] PR-75: Fix CVE-2023-40225
From: @openeuler-sync-bot 
Reviewed-by: @wu-leilei 
Signed-off-by: @wu-leilei
2023-08-21 07:42:31 +00:00
wk333
098fdacd23 Fix CVE-2023-40225
(cherry picked from commit 8b350381fb62cfc32bd1a17cfc02357bf79d804e)
2023-08-21 15:30:22 +08:00
openeuler-ci-bot
c23bb006d9
!64 [sync] PR-60: Fix CVE-2023-25725 and CVE-2023-0056
From: @openeuler-sync-bot 
Reviewed-by: @wang--ge 
Signed-off-by: @wang--ge
2023-02-27 01:13:00 +00:00
starlet-dx
b9c8f31338 Fix CVE-2023-25725 and CVE-2023-0056
(cherry picked from commit bd1a84b31185abe6aea91d91d6002ad35c66f15e)
2023-02-25 18:45:29 +08:00
7 changed files with 702 additions and 1 deletions

52
CVE-2023-0056.patch Normal file
View File

@ -0,0 +1,52 @@
From 038a7e8aeb1c5b90c18c55d2bcfb3aaa476bce89 Mon Sep 17 00:00:00 2001
From: Christopher Faulet <cfaulet@haproxy.com>
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 <w@1wt.eu>
(cherry picked from commit ebfae006c6b5de1d1fe0cdd51847ec1e39d5cf59)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 84f5cba24f59b1c8339bb38323fcb01f434ba8e5)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit f5748a98c34bc889cae9386ca4f7073ab3f4c6b1)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 2c681c6f30fb90adab4701e287ff7a7db669b2e7)
[cf: ctx adjustment]
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
---
src/mux_h2.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/src/mux_h2.c b/src/mux_h2.c
index f9daf8a7540..4611942a05c 100644
--- a/src/mux_h2.c
+++ b/src/mux_h2.c
@@ -4607,6 +4607,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;
+ }
/* Mark the end of message using EOM */
htx->flags |= HTX_FL_EOI; /* no more data are expected. Only EOM remains to add now */
if (!htx_add_endof(htx, HTX_BLK_EOM)) {

41
CVE-2023-0836.patch Normal file
View File

@ -0,0 +1,41 @@
From 2e6bf0a2722866ae0128a4392fa2375bd1f03ff8 Mon Sep 17 00:00:00 2001
From: Youfu Zhang <zhangyoufu@gmail.com>
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.
---
src/fcgi.c | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/src/fcgi.c b/src/fcgi.c
index dcf2db2..1d1a82b 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;
--
1.7.10.4

145
CVE-2023-25725.patch Normal file
View File

@ -0,0 +1,145 @@
From a6c7ac9d51248a641f456906549120d3f6387049 Mon Sep 17 00:00:00 2001
From: Willy Tarreau <w@1wt.eu>
Date: Thu, 9 Feb 2023 21:36:54 +0100
Subject: 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
<html><body><h1>400 Bad request</h1>
Your browser sent an invalid request.
</body></html>
$ 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 <NONE> (#-1), server <NONE> (#-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.
---
src/h1.c | 4 ++++
src/hpack-dec.c | 9 +++++++++
src/qpack-dec.c | 9 +++++++++
3 files changed, 22 insertions(+)
--- a/src/h1.c
+++ b/src/h1.c
@@ -706,6 +706,10 @@ int h1_headers_to_hdr_list(char *start,
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);
}
--- a/src/hpack-dec.c
+++ b/src/hpack-dec.c
@@ -419,6 +419,15 @@ int hpack_decode_frame(struct hpack_dht
/* <name> and <value> 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

276
CVE-2023-40225.patch Normal file
View File

@ -0,0 +1,276 @@
From e8ba5e106444fc78558f4ff26e9ce946f89216f4 Mon Sep 17 00:00:00 2001
From: Willy Tarreau <w@1wt.eu>
Date: Wed, 9 Aug 2023 08:32:48 +0200
Subject: [PATCH] BUG/MAJOR: http: reject any empty content-length header value
Origin: https://github.com/FireBurn/haproxy/commit/e8ba5e106444fc78558f4ff26e9ce946f89216f4
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>
(cherry picked from commit d17c50010d591d1c070e1cb0567a06032d8869e9)
[wt: applied to h2_parse_cont_len_header() in src/h2.c instead]
Signed-off-by: Willy Tarreau <w@1wt.eu>
(cherry picked from commit ba9afd2774c03e434165475b537d0462801f49bb)
Signed-off-by: Willy Tarreau <w@1wt.eu>
---
reg-tests/http-messaging/h1_to_h1.vtc | 26 ++++++++++++
reg-tests/http-messaging/h2_to_h1.vtc | 60 +++++++++++++++++++++++++++
src/h1.c | 20 +++++++--
src/h2.c | 20 +++++++--
4 files changed, 120 insertions(+), 6 deletions(-)
diff --git a/reg-tests/http-messaging/h1_to_h1.vtc b/reg-tests/http-messaging/h1_to_h1.vtc
index 5b02f172433b..39708a246f6d 100644
--- a/reg-tests/http-messaging/h1_to_h1.vtc
+++ b/reg-tests/http-messaging/h1_to_h1.vtc
@@ -269,3 +269,29 @@ client c3h1 -connect ${h1_feh1_sock} {
# arrive here.
expect_close
} -run
+
+client c4h1 -connect ${h1_feh1_sock} {
+ # this request is invalid and advertises an invalid C-L ending with an
+ # empty value, which results in a stream error.
+ txreq \
+ -req "GET" \
+ -url "/test31.html" \
+ -hdr "content-length: 0," \
+ -hdr "connection: close"
+ rxresp
+ expect resp.status == 400
+ expect_close
+} -run
+
+client c5h1 -connect ${h1_feh1_sock} {
+ # this request is invalid and advertises an empty C-L, which results
+ # in a stream error.
+ txreq \
+ -req "GET" \
+ -url "/test41.html" \
+ -hdr "content-length:" \
+ -hdr "connection: close"
+ rxresp
+ expect resp.status == 400
+ expect_close
+} -run
diff --git a/reg-tests/http-messaging/h2_to_h1.vtc b/reg-tests/http-messaging/h2_to_h1.vtc
index 481aded12aee..3ed3751902e1 100644
--- a/reg-tests/http-messaging/h2_to_h1.vtc
+++ b/reg-tests/http-messaging/h2_to_h1.vtc
@@ -10,6 +10,8 @@ barrier b1 cond 2 -cyclic
barrier b2 cond 2 -cyclic
barrier b3 cond 2 -cyclic
barrier b4 cond 2 -cyclic
+barrier b5 cond 2 -cyclic
+barrier b6 cond 2 -cyclic
server s1 {
rxreq
@@ -31,6 +33,12 @@ server s1 {
barrier b4 sync
# the next request is never received
+
+ barrier b5 sync
+ # the next request is never received
+
+ barrier b6 sync
+ # the next request is never received
} -repeat 2 -start
haproxy h1 -conf {
@@ -115,6 +123,32 @@ client c1h2 -connect ${h1_feh2_sock} {
txdata -data "this is sent and ignored"
rxrst
} -run
+
+ # fifth request is invalid and advertises an invalid C-L ending with an
+ # empty value, which results in a stream error.
+ stream 9 {
+ barrier b5 sync
+ txreq \
+ -req "GET" \
+ -scheme "https" \
+ -url "/test5.html" \
+ -hdr "content-length" "0," \
+ -nostrend
+ rxrst
+ } -run
+
+ # sixth request is invalid and advertises an empty C-L, which results
+ # in a stream error.
+ stream 11 {
+ barrier b6 sync
+ txreq \
+ -req "GET" \
+ -scheme "https" \
+ -url "/test6.html" \
+ -hdr "content-length" "" \
+ -nostrend
+ rxrst
+ } -run
} -run
# HEAD requests : don't work well yet
@@ -257,4 +291,30 @@ client c3h2 -connect ${h1_feh2_sock} {
txdata -data "this is sent and ignored"
rxrst
} -run
+
+ # fifth request is invalid and advertises invalid C-L ending with an
+ # empty value, which results in a stream error.
+ stream 9 {
+ barrier b5 sync
+ txreq \
+ -req "POST" \
+ -scheme "https" \
+ -url "/test25.html" \
+ -hdr "content-length" "0," \
+ -nostrend
+ rxrst
+ } -run
+
+ # sixth request is invalid and advertises an empty C-L, which results
+ # in a stream error.
+ stream 11 {
+ barrier b6 sync
+ txreq \
+ -req "POST" \
+ -scheme "https" \
+ -url "/test26.html" \
+ -hdr "content-length" "" \
+ -nostrend
+ rxrst
+ } -run
} -run
diff --git a/src/h1.c b/src/h1.c
index 83912343d2c1..f351af8f7125 100644
--- a/src/h1.c
+++ b/src/h1.c
@@ -29,13 +29,20 @@ int h1_parse_cont_len_header(struct h1m *h1m, struct ist *value)
int not_first = !!(h1m->flags & H1_MF_CLEN);
struct ist word;
- word.ptr = value->ptr - 1; // -1 for next loop's pre-increment
+ word.ptr = value->ptr;
e = value->ptr + value->len;
- while (++word.ptr < e) {
+ while (1) {
+ if (word.ptr >= e) {
+ /* empty header or empty value */
+ goto fail;
+ }
+
/* skip leading delimiter and blanks */
- if (unlikely(HTTP_IS_LWS(*word.ptr)))
+ if (unlikely(HTTP_IS_LWS(*word.ptr))) {
+ word.ptr++;
continue;
+ }
/* digits only now */
for (cl = 0, n = word.ptr; n < e; n++) {
@@ -74,6 +81,13 @@ int h1_parse_cont_len_header(struct h1m *h1m, struct ist *value)
h1m->flags |= H1_MF_CLEN;
h1m->curr_len = h1m->body_len = cl;
*value = word;
+
+ /* Now either n==e and we're done, or n points to the comma,
+ * and we skip it and continue.
+ */
+ if (n++ == e)
+ break;
+
word.ptr = n;
}
/* here we've reached the end with a single value or a series of
diff --git a/src/h2.c b/src/h2.c
index bda4b05c7e22..b25aee10a51b 100644
--- a/src/h2.c
+++ b/src/h2.c
@@ -79,13 +79,20 @@ int h2_parse_cont_len_header(unsigned int *msgf, struct ist *value, unsigned lon
int not_first = !!(*msgf & H2_MSGF_BODY_CL);
struct ist word;
- word.ptr = value->ptr - 1; // -1 for next loop's pre-increment
+ word.ptr = value->ptr;
e = value->ptr + value->len;
- while (++word.ptr < e) {
+ while (1) {
+ if (word.ptr >= e) {
+ /* empty header or empty value */
+ goto fail;
+ }
+
/* skip leading delimiter and blanks */
- if (unlikely(HTTP_IS_LWS(*word.ptr)))
+ if (unlikely(HTTP_IS_LWS(*word.ptr))) {
+ word.ptr++;
continue;
+ }
/* digits only now */
for (cl = 0, n = word.ptr; n < e; n++) {
@@ -124,6 +131,13 @@ int h2_parse_cont_len_header(unsigned int *msgf, struct ist *value, unsigned lon
*msgf |= H2_MSGF_BODY_CL;
*body_len = cl;
*value = word;
+
+ /* Now either n==e and we're done, or n points to the comma,
+ * and we skip it and continue.
+ */
+ if (n++ == e)
+ break;
+
word.ptr = n;
}
/* here we've reached the end with a single value or a series of

107
CVE-2023-45539.patch Normal file
View File

@ -0,0 +1,107 @@
From 2eab6d354322932cfec2ed54de261e4347eca9a6 Mon Sep 17 00:00:00 2001
From: Willy Tarreau <w@1wt.eu>
Date: Tue, 8 Aug 2023 16:17:22 +0200
Subject: [PATCH] BUG/MINOR: h1: do not accept '#' as part of the URI component
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.
---
src/h1.c | 15 +++++++++++----
1 file changed, 11 insertions(+), 4 deletions(-)
diff --git a/src/h1.c b/src/h1.c
index 88a54c4a593d..4e224f895422 100644
--- a/src/h1.c
+++ b/src/h1.c
@@ -551,13 +551,13 @@ int h1_headers_to_hdr_list(char *start, const char *stop,
case H1_MSG_RQURI:
http_msg_rquri:
#ifdef HA_UNALIGNED_LE
- /* speedup: skip bytes not between 0x21 and 0x7e inclusive */
+ /* speedup: skip bytes not between 0x24 and 0x7e inclusive */
while (ptr <= end - sizeof(int)) {
- int x = *(int *)ptr - 0x21212121;
+ int x = *(int *)ptr - 0x24242424;
if (x & 0x80808080)
break;
- x -= 0x5e5e5e5e;
+ x -= 0x5b5b5b5b;
if (!(x & 0x80808080))
break;
@@ -569,8 +569,15 @@ int h1_headers_to_hdr_list(char *start, const char *stop,
goto http_msg_ood;
}
http_msg_rquri2:
- if (likely((unsigned char)(*ptr - 33) <= 93)) /* 33 to 126 included */
+ if (likely((unsigned char)(*ptr - 33) <= 93)) { /* 33 to 126 included */
+ if (*ptr == '#') {
+ if (h1m->err_pos < -1) /* PR_O2_REQBUG_OK not set */
+ goto invalid_char;
+ if (h1m->err_pos == -1) /* PR_O2_REQBUG_OK set: just log */
+ h1m->err_pos = ptr - start + skip;
+ }
EAT_AND_JUMP_OR_RETURN(ptr, end, http_msg_rquri2, http_msg_ood, state, H1_MSG_RQURI);
+ }
if (likely(HTTP_IS_SPHT(*ptr))) {
sl.rq.u.len = ptr - sl.rq.u.ptr;

View File

@ -0,0 +1,55 @@
From 0013757152ef499539377943e556a7f96acf605c Mon Sep 17 00:00:00 2001
From: Aurelien DARRAGON <adarragon@haproxy.com>
Date: Tue, 26 Mar 2024 10:42:48 +0100
Subject: [PATCH] BUG/MINOR: server: 'source' interface ignored from
'default-server' directive
Sebastien Gross reported that 'interface' keyword ('source' subargument)
is silently ignored when used from 'default-server' directive despite the
documentation implicitly stating that the keyword should be supported
there.
When support for 'source' keyword was added to 'default-server' directive
in dba97077 ("MINOR: server: Make 'default-server' support 'source'
keyword."), we properly duplicated the conn iface_name from the default-
server but we forgot to copy the conn iface_len which must be set as well
since it is used as setsockopt()'s 'optlen' argument in
tcp_connect_server().
It should be backported to all stable versions.
(cherry picked from commit bd98db50785b6cef946d38715b48f72e7ca73a59)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit ada8c0e37df568c58e3a328c171d6f27bcfbe652)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 92b935e99aef7573e658ff53858619bca737aeaf)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 8acf8e51f8a0cbeea778f2c392dad7a7e068a075)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit b7ff822695e72695dfd753be23ff11fc97696fb3)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit e34253add4973de6082795706cd105f2f5d8247e)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
Conflict: NA
Reference: https://git.haproxy.org/?p=haproxy-2.2.git;a=commit;h=0013757152ef499539377943e556a7f96acf605c
---
src/server.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/src/server.c b/src/server.c
index 2b9340734cff0..d011d397aecff 100644
--- a/src/server.c
+++ b/src/server.c
@@ -1539,8 +1539,10 @@ static void srv_conn_src_cpy(struct server *srv, const struct server *src)
srv->conn_src.bind_hdr_occ = src->conn_src.bind_hdr_occ;
srv->conn_src.tproxy_addr = src->conn_src.tproxy_addr;
#endif
- if (src->conn_src.iface_name != NULL)
+ if (src->conn_src.iface_name != NULL) {
srv->conn_src.iface_name = strdup(src->conn_src.iface_name);
+ srv->conn_src.iface_len = src->conn_src.iface_len;
+ }
}
/*

View File

@ -5,7 +5,7 @@
Name: haproxy
Version: 2.2.16
Release: 3
Release: 8
Summary: The Reliable, High Performance TCP/HTTP Load Balancer
License: GPLv2+
@ -18,6 +18,13 @@ Source4: %{name}.sysconfig
Patch0001: CVE-2021-40346.patch
Patch0002: CVE-2022-0711.patch
Patch0003: CVE-2023-25725.patch
Patch0004: CVE-2023-0056.patch
Patch0005: CVE-2023-40225.patch
Patch0006: CVE-2023-0836.patch
# https://github.com/haproxy/haproxy/commit/2eab6d354322932cfec2ed54de261e4347eca9a6
Patch0007: CVE-2023-45539.patch
Patch0008: backport-BUG-MINOR-server-source-interface-ignored-from-defau.patch
BuildRequires: gcc lua-devel pcre-devel zlib-devel openssl-devel systemd-devel systemd-units libatomic
Requires: %{name}-help = %{version}-%{release}
@ -125,6 +132,24 @@ exit 0
%{_mandir}/man1/*
%changelog
* Mon Jun 24 2024 xinghe <xinghe2@h-partners.com> - 2.2.16-8
- Type:bugfix
- CVE:NA
- SUG:NA
- DESC:server: 'source' interface ignored from 'default-server' directive
* Wed Dec 06 2023 yaoxin <yao_xin001@hoperun.com> - 2.2.16-7
- Fix CVE-2023-45539
* Fri Dec 1 2023 liningjie <liningjie@xfusion.com> - 2.2.16-6
- Fix CVE-2023-0836
* Mon Aug 21 2023 wangkai <wang_kai001@hoperun.com> - 2.2.16-5
- Fix CVE-2023-40225
* Sat Feb 25 2023 yaoxin <yaoxin30@h-partners.com> - 2.2.16-4
- Fix CVE-2023-25725 and CVE-2023-0056
* Fri Mar 11 2022 yaoxin <yaoxin30@huawei.com> - 2.2.16-3
- Fix CVE-2022-0711