I know we (or most of us) are volunteers working on Debian. But I have
to admit I'm a bit worried that we haven't patched this critical
cache-poisoning vulnerability in Varnish for one month (except in Debian
Stretch LTS).
Attached patches containing the fixes for CVE-2022-23959.
For Debian Buster I took them from the Varnish 6.0 LTS branch:
https://github.com/varnishcache/varnish-cache/commit/dcbe8b9ebf5b352e2534fc5645afa1d9747e9647
https://github.com/varnishcache/varnish-cache/commit/b8351f7f6231315f0fe00410b91893235eb29f57
For Debian Bullseye from the Varnish 6.6 branch:
https://github.com/varnishcache/varnish-cache/commit/9ed39d1f796369caafb647fe37b729c07f332327
https://github.com/varnishcache/varnish-cache/commit/ec531e16b9cd139bbf8971c5b306561c669681f4
Cheers,
Andreas
Index: varnish-6.6.1/bin/varnishd/cache/cache_req_body.c
===================================================================
--- varnish-6.6.1.orig/bin/varnishd/cache/cache_req_body.c
+++ varnish-6.6.1/bin/varnishd/cache/cache_req_body.c
@@ -251,6 +251,8 @@ VRB_Ignore(struct req *req)
if (req->req_body_status->avail > 0)
(void)VRB_Iterate(req->wrk, req->vsl, req,
httpq_req_body_discard, NULL);
+ if (req->req_body_status == BS_ERROR)
+ req->doclose = SC_RX_BODY;
return (0);
}
Index: varnish-6.6.1/bin/varnishtest/tests/f00008.vtc
===================================================================
--- /dev/null
+++ varnish-6.6.1/bin/varnishtest/tests/f00008.vtc
@@ -0,0 +1,56 @@
+varnishtest "VRB_Ignore and connection close"
+
+server s1 {
+ rxreq
+ txresp -body HIT
+} -start
+
+varnish v1 -arg "-p timeout_idle=1" -vcl+backend {
+ sub vcl_recv {
+ if (req.url == "/synth") {
+ return (synth(200, "SYNTH"));
+ }
+ }
+} -start
+
+# Prime an object
+client c1 {
+ txreq -url /hit
+ rxresp
+ expect resp.status == 200
+ expect resp.body == HIT
+} -run
+
+# Test synth
+client c2 {
+ txreq -req POST -url /synth -hdr "Content-Length: 2"
+ # Send 1 byte
+ send a
+ # Wait timeout_idle
+ delay 1.1
+ # Send 1 byte
+ send b
+ rxresp
+ expect resp.status == 200
+ expect resp.reason == SYNTH
+ expect resp.http.connection == close
+ timeout 0.5
+ expect_close
+} -run
+
+# Test cache hit
+client c3 {
+ txreq -req GET -url /hit -hdr "Content-Length: 2"
+ # Send 1 byte
+ send a
+ # Wait timeout_idle
+ delay 1.1
+ # Send 1 byte
+ send b
+ rxresp
+ expect resp.status == 200
+ expect resp.body == HIT
+ expect resp.http.connection == close
+ timeout 0.5
+ expect_close
+} -run
Index: varnish-6.1.1/bin/varnishd/cache/cache_req_body.c
===================================================================
--- varnish-6.1.1.orig/bin/varnishd/cache/cache_req_body.c
+++ varnish-6.1.1/bin/varnishd/cache/cache_req_body.c
@@ -247,6 +247,8 @@ VRB_Ignore(struct req *req)
if (req->req_body_status == REQ_BODY_WITH_LEN ||
req->req_body_status == REQ_BODY_WITHOUT_LEN)
(void)VRB_Iterate(req, httpq_req_body_discard, NULL);
+ if (req->req_body_status == REQ_BODY_FAIL)
+ req->doclose = SC_RX_BODY;
return(0);
}
Index: varnish-6.1.1/bin/varnishtest/tests/f00008.vtc
===================================================================
--- /dev/null
+++ varnish-6.1.1/bin/varnishtest/tests/f00008.vtc
@@ -0,0 +1,56 @@
+varnishtest "VRB_Ignore and connection close"
+
+server s1 {
+ rxreq
+ txresp -body HIT
+} -start
+
+varnish v1 -arg "-p timeout_idle=1" -vcl+backend {
+ sub vcl_recv {
+ if (req.url == "/synth") {
+ return (synth(200, "SYNTH"));
+ }
+ }
+} -start
+
+# Prime an object
+client c1 {
+ txreq -url /hit
+ rxresp
+ expect resp.status == 200
+ expect resp.body == HIT
+} -run
+
+# Test synth
+client c2 {
+ txreq -req POST -url /synth -hdr "Content-Length: 2"
+ # Send 1 byte
+ send a
+ # Wait timeout_idle
+ delay 1.1
+ # Send 1 byte
+ send b
+ rxresp
+ expect resp.status == 200
+ expect resp.reason == SYNTH
+ expect resp.http.connection == close
+ timeout 0.5
+ expect_close
+} -run
+
+# Test cache hit
+client c3 {
+ txreq -req GET -url /hit -hdr "Content-Length: 2"
+ # Send 1 byte
+ send a
+ # Wait timeout_idle
+ delay 1.1
+ # Send 1 byte
+ send b
+ rxresp
+ expect resp.status == 200
+ expect resp.body == HIT
+ expect resp.http.connection == close
+ timeout 0.5
+ expect_close
+} -run