Compare commits

...
Sign in to create a new pull request.

2 commits

Author SHA1 Message Date
Ingvar Hagelund
236d134bcd Picked upstream patches from 7.1 branch
Fixes CVE-2022-45059 aka VSV00010, rhbz#2141842
Fixes CVE-2022-45060 aka VSV00011, rhbz#2141847
Removed references to patches no longer needed
2022-11-14 15:36:01 +01:00
Ingvar Hagelund
b2330af66f New upstream release. A security release
Includes fix for CVE-2022-38150 aka VSV00009, rhbz#2117692
2022-08-12 11:50:30 +02:00
6 changed files with 528 additions and 36 deletions

1
.gitignore vendored
View file

@ -50,3 +50,4 @@ varnish-2.1.3.tar.gz
/varnish-7.0.0.tgz
/varnish-7.0.1.tgz
/varnish-7.0.2.tgz
/varnish-7.0.3.tgz

View file

@ -0,0 +1,235 @@
commit fcf5722af75fdbf58dd425dd68d0beaa49bab4f4
Author: Martin Blix Grydeland <martin@varnish-software.com>
Date: Thu Sep 29 14:38:05 2022 +0200
Add all well-known headers to the perfect hash lookup table
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
diff --git a/bin/varnishd/cache/cache_http.c b/bin/varnishd/cache/cache_http.c
index 194055c3c..827197ded 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 000000000..b381b5cf3
--- /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

View file

@ -0,0 +1,201 @@
commit 515a93df894430767073ccd8265497b6b25b54b5
Author: Asad Sajjad Ahmed <asadsa@varnish-software.com>
Date: Fri Sep 30 14:42:53 2022 +0200
hpack: fix pseudo-headers handling
We should apply the same restrictions on the list of allowed characters inside
H/2 pseudo-headers as we do for H/1. This error is translated into the
headers we send to a backend over H/1.
Failure to do so could permit various exploits against a backend not handling
malformed H/1 requests.
Signed-off-by: Asad Sajjad Ahmed <asadsa@varnish-software.com>
diff --git a/bin/varnishd/http2/cache_http2_hpack.c b/bin/varnishd/http2/cache_http2_hpack.c
index 6e67b55c5..f58788b12 100644
--- a/bin/varnishd/http2/cache_http2_hpack.c
+++ b/bin/varnishd/http2/cache_http2_hpack.c
@@ -96,13 +96,18 @@ h2h_addhdr(struct http *hp, char *b, size_t namelen, size_t len)
{
/* XXX: This might belong in cache/cache_http.c */
const char *b0;
+ int disallow_empty;
unsigned n;
+ char *p;
+ int i;
CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
AN(b);
assert(namelen >= 2); /* 2 chars from the ': ' that we added */
assert(namelen <= len);
+ disallow_empty = 0;
+
if (len > UINT_MAX) { /* XXX: cache_param max header size */
VSLb(hp->vsl, SLT_BogoHeader, "Header too large: %.20s", b);
return (H2SE_ENHANCE_YOUR_CALM);
@@ -117,10 +122,24 @@ h2h_addhdr(struct http *hp, char *b, size_t namelen, size_t len)
b += namelen;
len -= namelen;
n = HTTP_HDR_METHOD;
+ disallow_empty = 1;
+
+ /* First field cannot contain SP or CTL */
+ for (p = b, i = 0; i < len; p++, i++) {
+ if (vct_issp(*p) || vct_isctl(*p))
+ return (H2SE_PROTOCOL_ERROR);
+ }
} else if (!strncmp(b, ":path: ", namelen)) {
b += namelen;
len -= namelen;
n = HTTP_HDR_URL;
+ disallow_empty = 1;
+
+ /* Second field cannot contain LWS or CTL */
+ for (p = b, i = 0; i < len; p++, i++) {
+ if (vct_islws(*p) || vct_isctl(*p))
+ return (H2SE_PROTOCOL_ERROR);
+ }
} else if (!strncmp(b, ":scheme: ", namelen)) {
/* XXX: What to do about this one? (typically
"http" or "https"). For now set it as a normal
@@ -128,6 +147,15 @@ h2h_addhdr(struct http *hp, char *b, size_t namelen, size_t len)
b++;
len-=1;
n = hp->nhd;
+
+ for (p = b + namelen, i = 0; i < len-namelen;
+ p++, i++) {
+ if (vct_issp(*p) || vct_isctl(*p))
+ return (H2SE_PROTOCOL_ERROR);
+ }
+
+ if (!i)
+ return (H2SE_PROTOCOL_ERROR);
} else if (!strncmp(b, ":authority: ", namelen)) {
b+=6;
len-=6;
@@ -164,6 +192,13 @@ h2h_addhdr(struct http *hp, char *b, size_t namelen, size_t len)
hp->hd[n].b = b;
hp->hd[n].e = b + len;
+ if (disallow_empty && !Tlen(hp->hd[n])) {
+ VSLb(hp->vsl, SLT_BogoHeader,
+ "Empty pseudo-header %.*s",
+ (int)namelen, b0);
+ return (H2SE_PROTOCOL_ERROR);
+ }
+
return (0);
}
diff --git a/bin/varnishtest/tests/t02023.vtc b/bin/varnishtest/tests/t02023.vtc
new file mode 100644
index 000000000..cfd843da3
--- /dev/null
+++ b/bin/varnishtest/tests/t02023.vtc
@@ -0,0 +1,48 @@
+varnishtest "Empty pseudo-headers"
+
+server s1 {
+ rxreq
+ txresp
+} -start
+
+varnish v1 -arg "-p feature=+http2" -vcl+backend {
+} -start
+
+client c1 {
+ txreq -url ""
+ rxresp
+ expect resp.status == 400
+} -run
+
+client c1 {
+ txreq -req ""
+ rxresp
+ expect resp.status == 400
+} -run
+
+client c1 {
+ txreq -proto ""
+ rxresp
+ expect resp.status == 400
+} -run
+
+client c1 {
+ stream 1 {
+ txreq -url ""
+ rxrst
+ } -run
+} -run
+
+client c1 {
+ stream 1 {
+ txreq -scheme ""
+ rxrst
+ } -run
+} -run
+
+client c1 {
+ stream 1 {
+ txreq -req ""
+ rxrst
+ } -run
+} -run
diff --git a/bin/varnishtest/tests/t02024.vtc b/bin/varnishtest/tests/t02024.vtc
new file mode 100644
index 000000000..0d0a1abc5
--- /dev/null
+++ b/bin/varnishtest/tests/t02024.vtc
@@ -0,0 +1,48 @@
+varnishtest "Garbage pseudo-headers"
+
+server s1 {
+ rxreq
+ txresp
+} -start
+
+varnish v1 -arg "-p feature=+http2" -vcl+backend {
+} -start
+
+client c1 {
+ txreq -url " "
+ rxresp
+ expect resp.status == 400
+} -run
+
+client c1 {
+ txreq -req " "
+ rxresp
+ expect resp.status == 400
+} -run
+
+client c1 {
+ txreq -proto " "
+ rxresp
+ expect resp.status == 400
+} -run
+
+client c1 {
+ stream 1 {
+ txreq -url " "
+ rxrst
+ } -run
+} -run
+
+client c1 {
+ stream 1 {
+ txreq -scheme " "
+ rxrst
+ } -run
+} -run
+
+client c1 {
+ stream 1 {
+ txreq -req " "
+ rxrst
+ } -run
+} -run

View file

@ -1,2 +1,2 @@
SHA512 (varnish-7.0.2.tgz) = 5eb08345c95152639266b7ad241185188477f8fd04e88e4dfda1579719a1a413790a0616f25d70994f6d3b8f7640ea80926ece7c547555dad856fd9f6960c9a3
SHA512 (pkg-varnish-cache-d3e6a3f.tar.gz) = 01a133e10bc88e115255839de9ce394fa232b21341c1712773cf6e4633112301890cdc5155fce51afc6456324b84a7dd82a8544b7e9e598841ea1c5dccd3b4e3
SHA512 (varnish-7.0.3.tgz) = 515d5a60120228de381af5f78cd0b712ee77430c59c8760a1a027c5f5759c8f20f3ab79f4d3785f9f4ca3b1b62b0abb59d9e0b29010a879b6f93fa65e6b6f84d

View file

@ -0,0 +1,68 @@
commit 31a157cc8470cdc44db0ca299c4c246bd54e2d1c
Author: Asad Sajjad Ahmed <asadsa@varnish-software.com>
Date: Mon Oct 3 16:08:30 2022 +0200
h2: add vtc for VSV00011
Check for correct handling of missing pseudo-headers, and invalid
characters.
Signed-off-by: Asad Sajjad Ahmed <asadsa@varnish-software.com>
diff --git a/bin/varnishtest/tests/f00011.vtc b/bin/varnishtest/tests/f00011.vtc
new file mode 100644
index 000000000..810918028
--- /dev/null
+++ b/bin/varnishtest/tests/f00011.vtc
@@ -0,0 +1,51 @@
+varnishtest "H2: Malformed pseudo-headers"
+
+server s1 {
+ rxreq
+ txresp
+} -start
+
+varnish v1 -arg "-p feature=+http2" -vcl+backend {
+} -start
+
+client c1 {
+ stream 1 {
+ txreq -url ""
+ rxrst
+ } -run
+} -run
+
+client c1 {
+ stream 1 {
+ txreq -url " \t"
+ rxrst
+ } -run
+} -run
+
+client c1 {
+ stream 1 {
+ txreq -scheme ""
+ rxrst
+ } -run
+} -run
+
+client c1 {
+ stream 1 {
+ txreq -scheme " \t"
+ rxrst
+ } -run
+} -run
+
+client c1 {
+ stream 1 {
+ txreq -req ""
+ rxrst
+ } -run
+} -run
+
+client c1 {
+ stream 1 {
+ txreq -req " \t"
+ rxrst
+ } -run
+} -run

View file

@ -12,7 +12,7 @@
%global __provides_exclude_from ^%{_libdir}/varnish/vmods
%global abi 9b5f68e19ca0ab60010641e305fd12822f18d42c
%global abi 6a4c6a5c7e66a664b140278c209f0b18c544cab8
%global vrt 14.0
# Package scripts are now external
@ -22,47 +22,21 @@
Summary: High-performance HTTP accelerator
Name: varnish
Version: 7.0.2
Release: 1%{?dist}
Version: 7.0.3
Release: 2%{?dist}
License: BSD
URL: https://www.varnish-cache.org/
Source0: http://varnish-cache.org/_downloads/%{name}-%{version}.tgz
Source1: https://github.com/varnishcache/pkg-varnish-cache/archive/%{commit1}.tar.gz#/pkg-varnish-cache-%{shortcommit1}.tar.gz
# Patches:
# Patch 001: Because of Fedora's libtool no-rpath requirement, it is still
# necessary to add LD_LIBRARY_PATH when building the documentation
# (Fixed by using LT_SYS_LIBRARY_PATH)
#Patch1: varnish-6.1.1_fix_ld_library_path_in_doc_build.patch
# Patch 004: varnish selinux support for el6
#Patch4: varnish-4.0.3_fix_varnish4_selinux.el6.patch
# Upstream fix for VSV00010 aka CVE-2022-45059
Patch19: fix_for_VSV00010_fcf5722a.patch
# Patch 009: Hard code older python support in configure for older el releases
#Patch9: varnish-5.1.1.fix_python_version.patch
# Patch 012: Fix test for variants of ncurses, based on upstream commit 9bdc5f75, upstream issue #2668
#Patch12: varnish-6.0.1_fix_bug2668.patch
# Patch 013: Just a simple format error
#Patch13: varnish-6.1.0_fix_testu00008.patch
# Patch 014: Another formatting error fixed upstream, issue 2879
#Patch14: varnish-6.1.1_fix_upstrbug_2879.patch
# Patch 015: pcre-jit fixed upstream, issue #2912
#Patch15: varnish-6.1.1_fix_issue_2912.patch
# Patch 016: Fix some warnings that prohibited clean -Werror compilation
# on el6. Will not be fixed upstream. Patch grows more stupid
# for each iteration :-(
#Patch16: varnish-6.5.0_el6_fix_warning_from_old_gcc.patch
# Patch 017: Fix stack size on ppc64 in test c_00057, upstream commit 88948d9
#Patch17: varnish-6.2.0_fix_ppc64_for_test_c00057.patch
# Patch 018: gcc-10.0.1/s390x compilation fix, upstream commit b0af060
#Patch18: varnish-6.3.2_fix_s390x.patch
# Upstream fixes for VSV00011 aka CVE-2022-45060
Patch20: fix_for_VSV00011_515a93d.patch
Patch21: test_for_VSV00011_31a157cc.patch
%if 0%{?fedora} > 29
Provides: varnish%{_isa} = %{version}-%{release}
@ -76,7 +50,7 @@ Provides: vmod(purge)%{_isa} = %{version}-%{release}
Provides: vmod(std)%{_isa} = %{version}-%{release}
Provides: vmod(unix)%{_isa} = %{version}-%{release}
Provides: vmod(vtc)%{_isa} = %{version}-%{release}
Provides: vmod_purge.so%{_isa} = %{version}-%{release}
Provides: vmod(purge)%{_isa} = %{version}-%{release}
%endif
@ -155,6 +129,9 @@ ln -s pkg-varnish-cache-%{commit1}/redhat redhat
ln -s pkg-varnish-cache-%{commit1}/debian debian
cp redhat/find-provides .
sed -i 's,rst2man-3.6,rst2man-3.4,g; s,rst2html-3.6,rst2html-3.4,g; s,phinx-build-3.6,phinx-build-3.4,g' configure
%patch19 -p1
%patch20 -p1
%patch21 -p1
%build
# https://gcc.gnu.org/wiki/FAQ#PR323
@ -300,6 +277,16 @@ test -f /etc/varnish/secret || (uuidgen > /etc/varnish/secret && chmod 0600 /etc
%changelog
* Mon Nov 14 2022 Ingvar Hagelund <ingvar@redpill-linpro.com> - 7.0.3-2
- Picked upstream patches from 7.1 branch
- Fixes CVE-2022-45059 aka VSV00010, rhbz#2141842
- Fixes CVE-2022-45060 aka VSV00011, rhbz#2141847
- Removed references to patches no longer needed
* Fri Aug 12 2022 Ingvar Hagelund <ingvar@redpill-linpro.com> - 7.0.3-1
- New upstream release. A security release
- Includes fix for CVE-2022-38150 aka VSV00009, rhbz#2117692
* Wed Jan 26 2022 Ingvar Hagelund <ingvar@redpill-linpro.com> - 7.0.2-1
- New upstream release. A security release
- Includes fix for CVE-2022-23959 aka VSV00008, rhbz#2045033