diff --git a/CVE-2021-39241-pre.patch b/CVE-2021-39241-pre.patch new file mode 100644 index 0000000000000000000000000000000000000000..0d264be94137f4a87d356cae4dc7863369622eeb --- /dev/null +++ b/CVE-2021-39241-pre.patch @@ -0,0 +1,25 @@ +From 038af20a857ab1f656d5f949c2c5e00d55005c73 Mon Sep 17 00:00:00 2001 +From: Amaury Denoyelle +Date: Fri, 11 Dec 2020 17:53:09 +0100 +Subject: [PATCH 1/1] MEDIUM:h2: parse Extended CONNECT request to htx + +--- + src/h2.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/h2.c b/src/h2.c +index 656fed4..3f739e7 100644 +--- a/src/h2.c ++++ b/src/h2.c +@@ -173,7 +173,7 @@ int h2_parse_cont_len_header(unsigned int *msgf, struct ist *value, unsigned lon + */ + static struct htx_sl *h2_prepare_htx_reqline(uint32_t fields, struct ist *phdr, struct htx *htx, unsigned int *msgf) + { +- struct ist uri; ++ struct ist uri,meth_sl; + unsigned int flags = HTX_SL_F_NONE; + struct htx_sl *sl; + size_t i; +-- +2.23.0 + diff --git a/CVE-2021-39241.patch b/CVE-2021-39241.patch new file mode 100644 index 0000000000000000000000000000000000000000..07798d527b774de41e5d67c82147a105f062aef6 --- /dev/null +++ b/CVE-2021-39241.patch @@ -0,0 +1,79 @@ +From 89265224d314a056d77d974284802c1b8a0dc97f Mon Sep 17 00:00:00 2001 +From: Willy Tarreau +Date: Wed, 11 Aug 2021 11:12:46 +0200 +Subject: [PATCH] BUG/MAJOR: h2: enforce stricter syntax checks on the :method + pseudo-header +MIME-Version: 1.0 +Content-Type: text/plain; charset=utf8 +Content-Transfer-Encoding: 8bit + +Before HTX was introduced, all the HTTP request elements passed in +pseudo-headers fields were used to build an HTTP/1 request whose syntax +was then scrutinized by the HTTP/1 parser, leaving no room to inject +invalid characters. + +While NUL, CR and LF are properly blocked, it is possible to inject +spaces in the method so that once translated to HTTP/1, fields are +shifted by one spcae, and a lenient HTTP/1 server could possibly be +fooled into using a part of the method as the URI. For example, the +following request: + + H2 request + :method: "GET /admin? HTTP/1.1" + :path: "/static/images" + +would become: + + GET /admin? HTTP/1.1 /static/images HTTP/1.1 + +It's important to note that the resulting request is *not* valid, and +that in order for this to be a problem, it requires that this request +is delivered to an already vulnerable HTTP/1 server. + +A workaround here is to reject malformed methods by placing this rule +in the frontend or backend, at least before leaving haproxy in H1: + + http-request reject if { method -m reg [^A-Z0-9] } + +Alternately H2 may be globally disabled by commenting out the "alpn" +directive on "bind" lines, and by rejecting H2 streams creation by +adding the following statement to the global section: + + tune.h2.max-concurrent-streams 0 + +This patch adds a check for each character of the method to make sure +they belong to the ones permitted in a token, as mentioned in RFC7231#4.1. + +This should be backported to versions 2.0 and above. For older versions +not having HTX_FL_PARSING_ERROR, a "goto fail" works as well as it +results in a protocol error at the stream level. Non-HTX versions are +safe because the resulting invalid request will be rejected by the +internal HTTP/1 parser. + +Thanks to Tim Düsterhus for reporting that one. +--- + src/h2.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/src/h2.c b/src/h2.c +index b31ff93..280bbd7 100644 +--- a/src/h2.c ++++ b/src/h2.c +@@ -328,6 +328,14 @@ static struct htx_sl *h2_prepare_htx_reqline(uint32_t fields, struct ist *phdr, + flags |= HTX_SL_F_HAS_AUTHORITY; + } + ++ /* The method is a non-empty token (RFC7231#4.1) */ ++ if (!meth_sl.len) ++ goto fail; ++ for (i = 0; i < meth_sl.len; i++) { ++ if (!HTTP_IS_TOKEN(meth_sl.ptr[i])) ++ htx->flags |= HTX_FL_PARSING_ERROR; ++ } ++ + /* make sure the final URI isn't empty. Note that 7540#8.1.2.3 states + * that :path must not be empty. + */ +-- +1.7.10.4 + diff --git a/CVE-2021-39242.patch b/CVE-2021-39242.patch new file mode 100644 index 0000000000000000000000000000000000000000..c89a9e4d89f2c72c552afc1482c70a8650d00eb6 --- /dev/null +++ b/CVE-2021-39242.patch @@ -0,0 +1,97 @@ +From b5d2b9e154d78e4075db163826c5e0f6d31b2ab1 Mon Sep 17 00:00:00 2001 +From: Willy Tarreau +Date: Wed, 11 Aug 2021 15:39:13 +0200 +Subject: [PATCH] BUG/MEDIUM: h2: give :authority precedence over Host +MIME-Version: 1.0 +Content-Type: text/plain; charset=utf8 +Content-Transfer-Encoding: 8bit + +The wording regarding Host vs :authority in RFC7540 is ambiguous as it +says that an intermediary must produce a host header from :authority if +Host is missing, but, contrary to HTTP/1.1, doesn't say anything regarding +the possibility that Host and :authority differ, which leaves Host with +higher precedence there. In addition it mentions that clients should use +:authority *instead* of Host, and that H1->H2 should use :authority only +if the original request was in authority form. This leaves some gray +area in the middle of the chain for fully valid H2 requests arboring a +Host header that are forwarded to the other side where it's possible to +drop the Host header and use the authority only after forwarding to a +second H2 layer, thus possibly seeing two different values of Host at +a different stage. There's no such issue when forwarding from H2 to H1 +as the authority is dropped only only the Host is kept. + +Note that the following request is sufficient to re-normalize such a +request: + + http-request set-header host %[req.hdr(host)] + +The new spec in progress (draft-ietf-httpbis-http2bis-03) addresses +this trouble by being a bit is stricter on these rules. It clarifies +that :authority must always be used instead of Host and that Host ought +to be ignored. This is much saner as it avoids to convey two distinct +values along the chain. This becomes the protocol-level equivalent of: + + http-request set-uri %[url] + +So this patch does exactly this, which we were initially a bit reluctant +to do initially by lack of visibility about other implementations' +expectations. In addition it slightly simplifies the Host header field +creation by always placing it first in the list of headers instead of +last; this could also speed up the look up a little bit. + +This needs to be backported to 2.0. Non-HTX versions are safe regarding +this because they drop the URI during the conversion to HTTP/1.1 so +only Host is used and transmitted. + +Thanks to Tim Düsterhus for reporting that one. +--- + src/h2.c | 23 +++++++++++++++++++++-- + 1 file changed, 21 insertions(+), 2 deletions(-) + +diff --git a/src/h2.c b/src/h2.c +index 280bbd7..bbc5853 100644 +--- a/src/h2.c ++++ b/src/h2.c +@@ -456,10 +456,27 @@ int h2_make_htx_request(struct http_hdr *list, struct htx *htx, unsigned int *ms + if (!sl) + goto fail; + fields |= H2_PHDR_FND_NONE; ++ ++ /* http2bis draft recommends to drop Host in favor of :authority when ++ * the latter is present. This is required to make sure there is no ++ * discrepancy between the authority and the host header, especially ++ * since routing rules usually involve Host. Here we already know if ++ * :authority was found so we can emit it right now and mark the host ++ * as filled so that it's skipped later. ++ */ ++ if (fields & H2_PHDR_FND_AUTH) { ++ if (!htx_add_header(htx, ist("host"), phdr_val[H2_PHDR_IDX_AUTH])) ++ goto fail; ++ fields |= H2_PHDR_FND_HOST; ++ } + } + +- if (isteq(list[idx].n, ist("host"))) ++ if (isteq(list[idx].n, ist("host"))) { ++ if (fields & H2_PHDR_FND_HOST) ++ continue; ++ + fields |= H2_PHDR_FND_HOST; ++ } + + if (isteq(list[idx].n, ist("content-length"))) { + ret = h2_parse_cont_len_header(msgf, &list[idx].v, body_len); +@@ -531,7 +548,9 @@ int h2_make_htx_request(struct http_hdr *list, struct htx *htx, unsigned int *ms + /* update the start line with last detected header info */ + sl->flags |= sl_flags; + +- /* complete with missing Host if needed */ ++ /* complete with missing Host if needed (we may validate this test if ++ * no regular header was found). ++ */ + if ((fields & (H2_PHDR_FND_HOST|H2_PHDR_FND_AUTH)) == H2_PHDR_FND_AUTH) { + /* missing Host field, use :authority instead */ + if (!htx_add_header(htx, ist("host"), phdr_val[H2_PHDR_IDX_AUTH])) +-- +1.7.10.4 + diff --git a/haproxy.spec b/haproxy.spec index 703c3df8d86973d1761b688383e69100abb71303..4e2785d04bd71205038e13fa81aa2140869d108a 100644 --- a/haproxy.spec +++ b/haproxy.spec @@ -5,7 +5,7 @@ Name: haproxy Version: 2.0.17 -Release: 1 +Release: 2 Summary: The Reliable, High Performance TCP/HTTP Load Balancer License: GPLv2+ @@ -15,7 +15,9 @@ Source1: %{name}.service Source2: %{name}.cfg Source3: %{name}.logrotate Source4: %{name}.sysconfig - +Patch001: CVE-2021-39241-pre.patch +Patch002: CVE-2021-39241.patch +Patch003: CVE-2021-39242.patch BuildRequires: gcc lua-devel pcre-devel zlib-devel openssl-devel systemd-devel systemd-units libatomic Requires(pre): shadow-utils @@ -30,7 +32,7 @@ and proxying for TCP and HTTP-based applications. It is particularly suited for web sites and powers quite a number of the world's most visited ones. %prep -%autosetup -n %{name}-%{version} +%autosetup -n %{name}-%{version} -p1 %build use_regparm_opt= @@ -122,6 +124,9 @@ exit 0 %{_mandir}/man1/* %changelog +* Tue Aug 31 2021 liwu - 2.0.17-2 +- fix CVE-2021-39241,CVE-2021-39242 + * Tue Sep 15 2020 Ge Wang - 2.0.17-1 - update to 2.0.17 and modify source0 url