diff -Nru varnish-3.0.5/debian/changelog varnish-3.0.5/debian/changelog --- varnish-3.0.5/debian/changelog 2014-03-24 15:37:58.000000000 -0500 +++ varnish-3.0.5/debian/changelog 2017-08-07 13:57:07.000000000 -0500 @@ -1,3 +1,12 @@ +varnish (3.0.5-2ubuntu0.1) trusty-security; urgency=medium + + * SECURITY UPDATE: HTTP Smuggling issues: Double Content Length and bad EOL + (LP: #1709153). + - fix-HTTP-Smuggling-CVE-2015-8852.patch + - CVE-2015-8852 + + -- Simon Quigley Mon, 07 Aug 2017 13:57:07 -0500 + varnish (3.0.5-2) unstable; urgency=medium [ Mattia Rizzolo ] diff -Nru varnish-3.0.5/debian/control varnish-3.0.5/debian/control --- varnish-3.0.5/debian/control 2014-03-24 15:37:58.000000000 -0500 +++ varnish-3.0.5/debian/control 2017-08-07 13:57:07.000000000 -0500 @@ -1,7 +1,8 @@ Source: varnish Section: web Priority: optional -Maintainer: Varnish Package Maintainers +Maintainer: Ubuntu Developers +XSBC-Original-Maintainer: Varnish Package Maintainers Uploaders: Jan Wagner , Lars Bahner , diff -Nru varnish-3.0.5/debian/patches/fix-HTTP-Smuggling-CVE-2015-8852.patch varnish-3.0.5/debian/patches/fix-HTTP-Smuggling-CVE-2015-8852.patch --- varnish-3.0.5/debian/patches/fix-HTTP-Smuggling-CVE-2015-8852.patch 1969-12-31 18:00:00.000000000 -0600 +++ varnish-3.0.5/debian/patches/fix-HTTP-Smuggling-CVE-2015-8852.patch 2017-08-07 13:57:07.000000000 -0500 @@ -0,0 +1,229 @@ +Description: HTTP Smuggling issues: Double Content Length and bad EOL + Varnish 3.x before 3.0.7, when used in certain stacked installations, allows + remote attackers to inject arbitrary HTTP headers and conduct HTTP response + splitting attacks via a header line terminated by a \r (carriage return) + character in conjunction with multiple Content-Length headers in an HTTP + request. + . + This fixes CVE-2015-8852. +Author: Martin Blix Grydeland +Origin: upstream +Bug-Ubuntu: https://pad.lv/1709153 +Applied-Upstream: 85e8468, 29870c8 +Last-Update: 2017-08-07 +--- a/bin/varnishd/cache_http.c ++++ b/bin/varnishd/cache_http.c +@@ -502,7 +502,7 @@ http_dissect_hdrs(struct worker *w, stru + /* Find end of next header */ + q = r = p; + while (r < t.e) { +- if (!vct_iscrlf(*r)) { ++ if (!vct_iscrlf(r)) { + r++; + continue; + } +@@ -611,8 +611,8 @@ http_splitline(struct worker *w, int fd, + + /* Third field is optional and cannot contain CTL */ + q = p; +- if (!vct_iscrlf(*p)) { +- for (; !vct_iscrlf(*p); p++) ++ if (!vct_iscrlf(p)) { ++ for (; !vct_iscrlf(p); p++) + if (!vct_issep(*p) && vct_isctl(*p)) + return (400); + } +@@ -639,10 +639,12 @@ http_splitline(struct worker *w, int fd, + /*--------------------------------------------------------------------*/ + + static int +-htc_request_check_host_hdr(struct http *hp) ++htc_request_check_hdrs(struct sess *sp, struct http *hp) + { + int u; + int seen_host = 0; ++ int seen_cl = 0; ++ + for (u = HTTP_HDR_FIRST; u < hp->nhd; u++) { + if (hp->hd[u].b == NULL) + continue; +@@ -650,10 +652,19 @@ htc_request_check_host_hdr(struct http * + AN(hp->hd[u].e); + if (http_IsHdr(&hp->hd[u], H_Host)) { + if (seen_host) { ++ WSP(sp, SLT_Error, "Duplicated Host header"); + return (400); + } + seen_host = 1; + } ++ if (http_IsHdr(&hp->hd[u], H_Content_Length)) { ++ if (seen_cl) { ++ WSP(sp, SLT_Error, ++ "Duplicated Content-Length header"); ++ return (400); ++ } ++ seen_cl = 1; ++ } + } + return (0); + } +@@ -698,11 +709,7 @@ http_DissectRequest(struct sess *sp) + } + http_ProtoVer(hp); + +- retval = htc_request_check_host_hdr(hp); +- if (retval != 0) { +- WSP(sp, SLT_Error, "Duplicated Host header"); +- return (retval); +- } ++ retval = htc_request_check_hdrs(sp, hp); + return (retval); + } + +--- /dev/null ++++ b/bin/varnishtest/tests/b00040.vtc +@@ -0,0 +1,24 @@ ++varnishtest "Do not consider CR as a valid line separator" ++ ++server s1 { ++ rxreq ++ txresp ++} -start ++ ++varnish v1 -vcl+backend { ++ sub vcl_deliver { ++ if (req.http.foo) { ++ set resp.http.Foo = req.http.foo; ++ } ++ if (req.http.bar) { ++ set resp.http.Bar = req.http.bar; ++ } ++ } ++} -start ++ ++client c1 { ++ send "GET / HTTP/1.1\r\nFoo: foo\rBar: bar\r\n\r\n" ++ rxresp ++ expect resp.http.foo == "foo\rBar: bar" ++ expect resp.http.bar == "" ++} -run +--- a/bin/varnishtest/vtc_http.c ++++ b/bin/varnishtest/vtc_http.c +@@ -283,17 +283,17 @@ http_splitheader(struct http *hp, int re + hh[n++] = p; + while (!vct_islws(*p)) + p++; +- assert(!vct_iscrlf(*p)); ++ assert(!vct_iscrlf(p)); + *p++ = '\0'; + + /* URL/STATUS */ + while (vct_issp(*p)) /* XXX: H space only */ + p++; +- assert(!vct_iscrlf(*p)); ++ assert(!vct_iscrlf(p)); + hh[n++] = p; + while (!vct_islws(*p)) + p++; +- if (vct_iscrlf(*p)) { ++ if (vct_iscrlf(p)) { + hh[n++] = NULL; + q = p; + p += vct_skipcrlf(p); +@@ -304,7 +304,7 @@ http_splitheader(struct http *hp, int re + while (vct_issp(*p)) /* XXX: H space only */ + p++; + hh[n++] = p; +- while (!vct_iscrlf(*p)) ++ while (!vct_iscrlf(p)) + p++; + q = p; + p += vct_skipcrlf(p); +@@ -314,10 +314,10 @@ http_splitheader(struct http *hp, int re + + while (*p != '\0') { + assert(n < MAX_HDR); +- if (vct_iscrlf(*p)) ++ if (vct_iscrlf(p)) + break; + hh[n++] = p++; +- while (*p != '\0' && !vct_iscrlf(*p)) ++ while (*p != '\0' && !vct_iscrlf(p)) + p++; + q = p; + p += vct_skipcrlf(p); +@@ -408,11 +408,11 @@ http_rxchunk(struct http *hp) + } + l = hp->prxbuf; + (void)http_rxchar(hp, 2, 0); +- if(!vct_iscrlf(hp->rxbuf[l])) ++ if(!vct_iscrlf(&hp->rxbuf[l])) + vtc_log(hp->vl, hp->fatal, + "Wrong chunk tail[0] = %02x", + hp->rxbuf[l] & 0xff); +- if(!vct_iscrlf(hp->rxbuf[l + 1])) ++ if(!vct_iscrlf(&hp->rxbuf[l + 1])) + vtc_log(hp->vl, hp->fatal, + "Wrong chunk tail[1] = %02x", + hp->rxbuf[l + 1] & 0xff); +--- a/include/vct.h ++++ b/include/vct.h +@@ -54,7 +54,6 @@ vct_is(unsigned char x, uint16_t y) + + #define vct_issp(x) vct_is(x, VCT_SP) + #define vct_ishex(x) vct_is(x, VCT_HEX) +-#define vct_iscrlf(x) vct_is(x, VCT_CRLF) + #define vct_islws(x) vct_is(x, VCT_LWS) + #define vct_isctl(x) vct_is(x, VCT_CTL) + #define vct_isdigit(x) vct_is(x, VCT_DIGIT) +@@ -64,5 +63,7 @@ vct_is(unsigned char x, uint16_t y) + #define vct_isxmlnamestart(x) vct_is(x, VCT_XMLNAMESTART) + #define vct_isxmlname(x) vct_is(x, VCT_XMLNAMESTART | VCT_XMLNAME) + ++#define vct_iscrlf(p) (((p)[0] == '\r' && (p)[1] == '\n') || (p)[0] == '\n') ++ + /* NB: VCT always operate in ASCII, don't replace 0x0d with \r etc. */ + #define vct_skipcrlf(p) (p[0] == 0x0d && p[1] == 0x0a ? 2 : 1) +--- /dev/null ++++ b/bin/varnishtest/tests/b00041.vtc +@@ -0,0 +1,23 @@ ++varnishtest "Fail request on duplicate Content-Length headers in requests" ++ ++server s1 { ++ rxreq ++ txresp ++} -start ++ ++varnish v1 -vcl+backend { ++ sub vcl_deliver { ++ if (req.http.foo) { ++ set resp.http.Foo = req.http.foo; ++ } ++ if (req.http.bar) { ++ set resp.http.Bar = req.http.bar; ++ } ++ } ++} -start ++ ++client c1 { ++ txreq -req POST -hdr "Content-Length: 5" -body "12345" ++ rxresp ++ expect resp.status == 400 ++} -run +--- a/bin/varnishtest/tests/r00102.vtc ++++ b/bin/varnishtest/tests/r00102.vtc +@@ -17,14 +17,12 @@ varnish v1 -vcl+backend { + + client c1 { + txreq -req POST -url "/" \ +- -hdr "Content-Length: 10" \ + -body "123456789\n" + rxresp + expect resp.status == 200 + expect resp.http.X-Varnish == "1001" + + txreq -req POST -url "/" \ +- -hdr "Content-Length: 10" \ + -body "123456789\n" + rxresp + expect resp.status == 200 diff -Nru varnish-3.0.5/debian/patches/series varnish-3.0.5/debian/patches/series --- varnish-3.0.5/debian/patches/series 1969-12-31 18:00:00.000000000 -0600 +++ varnish-3.0.5/debian/patches/series 2017-08-07 13:45:14.000000000 -0500 @@ -0,0 +1 @@ +fix-HTTP-Smuggling-CVE-2015-8852.patch