From 0e970a71bb32ad1397ca2e450a5bc6b1d2de4de2 Mon Sep 17 00:00:00 2001 From: wk333 <13474090681@163.com> Date: Tue, 12 Dec 2023 15:36:00 +0800 Subject: [PATCH] Fix CVE-2022-45059 (cherry picked from commit 2444e1fa5af9db86e118d2a183e7124d4600481c) --- CVE-2022-45059-pre.patch | 32 ++++++ CVE-2022-45059.patch | 241 +++++++++++++++++++++++++++++++++++++++ varnish.spec | 7 +- 3 files changed, 279 insertions(+), 1 deletion(-) create mode 100644 CVE-2022-45059-pre.patch create mode 100644 CVE-2022-45059.patch diff --git a/CVE-2022-45059-pre.patch b/CVE-2022-45059-pre.patch new file mode 100644 index 0000000..5515946 --- /dev/null +++ b/CVE-2022-45059-pre.patch @@ -0,0 +1,32 @@ +From 0fb3baff7963604a55be0ed6ebdf1e4654ead219 Mon Sep 17 00:00:00 2001 +From: Martin Blix Grydeland +Date: Thu, 4 Aug 2022 11:04:37 +0200 +Subject: [PATCH] Clean up assertions in http_hdr_flags() + +Origin: https://github.com/varnishcache/varnish-cache/commit/0fb3baff7963604a55be0ed6ebdf1e4654ead219 + +The input argument assertions and checks in http_hdr_flags() were +misleading and lacking. With this patch it returns (NULL) on either input +being NULL, and also when called with an empty string instead of +asserting. +--- + bin/varnishd/cache/cache_http.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/bin/varnishd/cache/cache_http.c b/bin/varnishd/cache/cache_http.c +index 3f5ee0384a..194055c3ca 100644 +--- a/bin/varnishd/cache/cache_http.c ++++ b/bin/varnishd/cache/cache_http.c +@@ -140,9 +140,9 @@ http_hdr_flags(const char *b, const char *e) + unsigned u; + struct http_hdrflg *retval; + +- if (e == NULL) +- return(NULL); +- assert(e > b); ++ if (b == NULL || e == NULL) ++ return (NULL); ++ assert(b <= e); + u = (unsigned)(e - b); + assert(b + u == e); + if (u < 2 || u > 19) // MIN_WORD_LENGTH & MAX_WORD_LENGTH diff --git a/CVE-2022-45059.patch b/CVE-2022-45059.patch new file mode 100644 index 0000000..d89059f --- /dev/null +++ b/CVE-2022-45059.patch @@ -0,0 +1,241 @@ +From fcf5722af75fdbf58dd425dd68d0beaa49bab4f4 Mon Sep 17 00:00:00 2001 +From: Martin Blix Grydeland +Date: Thu, 29 Sep 2022 14:38:05 +0200 +Subject: [PATCH] Add all well-known headers to the perfect hash lookup table + +Origin: https://github.com/varnishcache/varnish-cache/commit/fcf5722af75fdbf58dd425dd68d0beaa49bab4f4 + +This expands the perfect hash lookup table to be able to match any entry +in the list of well-known headers from tbl/http_headers.h. + +Previously only the headers that had a non-zero filter flag section was +kept in the fast match table. + +Fixes: VSV00010 +--- + bin/varnishd/cache/cache_http.c | 148 +++++++++++++++++++------------ + bin/varnishtest/tests/f00010.vtc | 19 ++++ + 2 files changed, 112 insertions(+), 55 deletions(-) + create mode 100644 bin/varnishtest/tests/f00010.vtc + +diff --git a/bin/varnishd/cache/cache_http.c b/bin/varnishd/cache/cache_http.c +index 194055c3ca..827197dedf 100644 +--- a/bin/varnishd/cache/cache_http.c ++++ b/bin/varnishd/cache/cache_http.c +@@ -65,73 +65,113 @@ const char H__Reason[] = "\010:reason:"; + * A suitable algorithm can be found with `gperf`: + * + * tr '" ,' ' ' < include/tbl/http_headers.h | +- * awk '$1 == "H(" && $4 != "0" {print$2}' | ++ * awk '$1 == "H(" {print $2}' | + * gperf --ignore-case + * + */ + ++#define GPERF_MIN_WORD_LENGTH 2 ++#define GPERF_MAX_WORD_LENGTH 19 ++#define GPERF_MAX_HASH_VALUE 79 ++ + static const unsigned char http_asso_values[256] = { +- 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, +- 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, +- 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, +- 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, +- 39, 39, 39, 39, 39, 25, 39, 0, 20, 5, 39, 39, 39, 15, 0, 39, +- 10, 39, 0, 39, 15, 10, 39, 39, 0, 39, 39, 39, 39, 39, 39, 39, +- 39, 39, 39, 39, 39, 25, 39, 0, 20, 5, 39, 39, 39, 15, 0, 39, +- 10, 39, 0, 39, 15, 10, 39, 39, 0, 39, 39, 39, 39, 39, 39, 39, +- 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, +- 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, +- 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, +- 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, +- 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, +- 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, +- 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, +- 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39 ++ 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, ++ 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, ++ 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, ++ 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, ++ 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, ++ 80, 80, 80, 0, 80, 80, 80, 80, 80, 80, ++ 80, 80, 80, 80, 80, 5, 80, 20, 0, 0, ++ 5, 10, 5, 5, 80, 0, 15, 0, 20, 80, ++ 40, 80, 0, 35, 10, 20, 55, 45, 0, 0, ++ 80, 80, 80, 80, 80, 80, 80, 5, 80, 20, ++ 0, 0, 5, 10, 5, 5, 80, 0, 15, 0, ++ 20, 80, 40, 80, 0, 35, 10, 20, 55, 45, ++ 0, 0, 80, 80, 80, 80, 80, 80, 80, 80, ++ 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, ++ 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, ++ 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, ++ 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, ++ 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, ++ 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, ++ 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, ++ 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, ++ 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, ++ 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, ++ 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, ++ 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, ++ 80, 80, 80, 80, 80, 80 + }; + + static struct http_hdrflg { + char *hdr; + unsigned flag; +-} http_hdrflg[38 + 1] = { // MAX_HASH_VALUE +- { NULL }, +- { NULL }, +- { H_TE }, +- { H_Age }, +- { NULL }, ++} http_hdrflg[GPERF_MAX_HASH_VALUE + 1] = { ++ { NULL }, { NULL }, { NULL }, { NULL }, ++ { H_Date }, + { H_Range }, + { NULL }, +- { H_Upgrade }, ++ { H_Referer }, ++ { H_Age }, ++ { H_From }, ++ { H_Keep_Alive }, ++ { H_Retry_After }, ++ { H_TE }, + { H_If_Range }, +- { NULL }, +- { H_Connection }, +- { NULL }, ++ { H_ETag }, ++ { H_X_Forwarded_For }, ++ { H_Expect }, + { H_Trailer }, +- { H_If_None_Match }, +- { NULL }, +- { NULL }, +- { NULL }, +- { H_Transfer_Encoding }, +- { H_Proxy_Authenticate }, +- { H_Proxy_Authorization }, +- { H_Keep_Alive }, +- { NULL }, +- { NULL }, + { H_If_Match }, +- { H_HTTP2_Settings }, +- { NULL }, +- { NULL }, +- { NULL }, +- { H_Content_Range }, ++ { H_Host }, ++ { H_Accept_Language }, ++ { H_Accept }, ++ { H_If_Modified_Since }, ++ { H_If_None_Match }, + { H_If_Unmodified_Since }, + { NULL }, ++ { H_Cookie }, ++ { H_Upgrade }, ++ { H_Last_Modified }, ++ { H_Accept_Charset }, ++ { H_Accept_Encoding }, ++ { H_Content_MD5 }, ++ { H_Content_Type }, ++ { H_Content_Range }, ++ { NULL }, { NULL }, ++ { H_Content_Language }, ++ { H_Transfer_Encoding }, ++ { H_Authorization }, ++ { H_Content_Length }, ++ { H_User_Agent }, ++ { H_Server }, ++ { H_Expires }, ++ { H_Location }, + { NULL }, +- { H_If_Modified_Since }, ++ { H_Set_Cookie }, ++ { H_Content_Encoding }, ++ { H_Max_Forwards }, + { H_Cache_Control }, + { NULL }, ++ { H_Connection }, ++ { H_Pragma }, + { NULL }, ++ { H_Accept_Ranges }, ++ { H_HTTP2_Settings }, ++ { H_Allow }, ++ { H_Content_Location }, + { NULL }, ++ { H_Proxy_Authenticate }, ++ { H_Vary }, + { NULL }, +- { H_Accept_Ranges } ++ { H_WWW_Authenticate }, ++ { H_Warning }, ++ { H_Via }, ++ { NULL }, { NULL }, { NULL }, { NULL }, ++ { NULL }, { NULL }, { NULL }, { NULL }, ++ { NULL }, { NULL }, { NULL }, { NULL }, ++ { NULL }, { NULL }, { NULL }, ++ { H_Proxy_Authorization } + }; + + static struct http_hdrflg * +@@ -145,12 +185,12 @@ http_hdr_flags(const char *b, const char *e) + assert(b <= e); + u = (unsigned)(e - b); + assert(b + u == e); +- if (u < 2 || u > 19) // MIN_WORD_LENGTH & MAX_WORD_LENGTH +- return(NULL); +- if (u > 3) +- u += http_asso_values[((const uint8_t*)b)[3]]; +- if (u > 38) // MAX_HASH_VALUE +- return(NULL); ++ if (u < GPERF_MIN_WORD_LENGTH || u > GPERF_MAX_WORD_LENGTH) ++ return (NULL); ++ u += http_asso_values[((const uint8_t *)b)[u - 1]] + ++ http_asso_values[((const uint8_t *)b)[0]]; ++ if (u > GPERF_MAX_HASH_VALUE) ++ return (NULL); + retval = &http_hdrflg[u]; + if (retval->hdr == NULL) + return(NULL); +@@ -168,11 +208,9 @@ http_init_hdr(char *hdr, int flg) + + hdr[0] = strlen(hdr + 1); + f = http_hdr_flags(hdr + 1, hdr + hdr[0]); +- if (flg) { +- AN(f); +- assert(f->hdr == hdr); +- f->flag = flg; +- } ++ AN(f); ++ assert(f->hdr == hdr); ++ f->flag = flg; + } + + void +diff --git a/bin/varnishtest/tests/f00010.vtc b/bin/varnishtest/tests/f00010.vtc +new file mode 100644 +index 0000000000..b381b5cf37 +--- /dev/null ++++ b/bin/varnishtest/tests/f00010.vtc +@@ -0,0 +1,19 @@ ++varnishtest "Do not allow critical headers to be marked hop-by-hop" ++ ++varnish v1 -vcl { ++ backend default none; ++} -start ++ ++client c1 { ++ txreq -hdr "Connection: Content-Length" -body "asdf" ++ rxresp ++ expect resp.status == 400 ++ expect_close ++} -run ++ ++client c2 { ++ txreq -hdr "Connection: Host" ++ rxresp ++ expect resp.status == 400 ++ expect_close ++} -run diff --git a/varnish.spec b/varnish.spec index 7c7c066..9feec7b 100644 --- a/varnish.spec +++ b/varnish.spec @@ -3,7 +3,7 @@ Name: varnish Summary: A web application accelerator Version: 7.0.1 -Release: 8 +Release: 9 License: BSD URL: https://www.varnish-cache.org/ Source0: http://varnish-cache.org/_downloads/varnish-%{version}.tgz @@ -16,6 +16,8 @@ Patch0002: CVE-2022-23959.patch Patch0003: CVE-2022-38150.patch Patch0004: CVE-2022-45060.patch Patch0005: fix-varnish.service-reload-failed.patch +Patch0006: CVE-2022-45059-pre.patch +Patch0007: CVE-2022-45059.patch BuildRequires: python3-sphinx python3-docutils pkgconfig make graphviz nghttp2 systemd-units BuildRequires: ncurses-devel pcre2-devel libedit-devel gcc @@ -154,6 +156,9 @@ test -f /etc/varnish/secret || (uuidgen > /etc/varnish/secret && chmod 0600 /etc %{_mandir}/man7/*.7* %changelog +* Tue Dec 12 2023 wangkai <13474090681@163.com> - 7.0.1-9 +- Fix CVE-2022-45059 + * Tue Dec 06 2022 wangkai - 7.0.1-8 - Fix strip safe compile options -- Gitee