Fix CVE-2019-16276
authorDr. Tobias Quathamer <toddy@debian.org>
Thu, 26 Sep 2019 09:46:46 +0000 (11:46 +0200)
committerDr. Tobias Quathamer <toddy@debian.org>
Thu, 26 Sep 2019 09:55:04 +0000 (10:55 +0100)
Cherry-picked from upstream:
https://github.com/golang/go/commit/6e6f4aaf70c8b1cc81e65a26332aa9409de03ad8

Gbp-Pq: Name 0007-Fix-CVE-2019-16276.patch

src/net/http/serve_test.go
src/net/http/transport_test.go
src/net/textproto/reader.go
src/net/textproto/reader_test.go

index a4385419d04b1b88f84527d12d43088476421ee5..18edf989e46b440431e436b1bf8819c999cfdb79 100644 (file)
@@ -4725,6 +4725,10 @@ func TestServerValidatesHeaders(t *testing.T) {
                {"foo\xffbar: foo\r\n", 400},                         // binary in header
                {"foo\x00bar: foo\r\n", 400},                         // binary in header
                {"Foo: " + strings.Repeat("x", 1<<21) + "\r\n", 431}, // header too large
+               // Spaces between the header key and colon are not allowed.
+               // See RFC 7230, Section 3.2.4.
+               {"Foo : bar\r\n", 400},
+               {"Foo\t: bar\r\n", 400},
 
                {"foo: foo foo\r\n", 200},    // LWS space is okay
                {"foo: foo\tfoo\r\n", 200},   // LWS tab is okay
index b2036dfc24efd354e7a0ac8ea8e066cc3576f3de..dff940ec5db001e8cfab093420857a466077a6ab 100644 (file)
@@ -4838,3 +4838,30 @@ func TestClientTimeoutKillsConn_AfterHeaders(t *testing.T) {
                t.Fatal("timeout")
        }
 }
+
+func TestInvalidHeaderResponse(t *testing.T) {
+       setParallel(t)
+       defer afterTest(t)
+       cst := newClientServerTest(t, h1Mode, HandlerFunc(func(w ResponseWriter, r *Request) {
+               conn, buf, _ := w.(Hijacker).Hijack()
+               buf.Write([]byte("HTTP/1.1 200 OK\r\n" +
+                       "Date: Wed, 30 Aug 2017 19:09:27 GMT\r\n" +
+                       "Content-Type: text/html; charset=utf-8\r\n" +
+                       "Content-Length: 0\r\n" +
+                       "Foo : bar\r\n\r\n"))
+               buf.Flush()
+               conn.Close()
+       }))
+       defer cst.close()
+       res, err := cst.c.Get(cst.ts.URL)
+       if err != nil {
+               t.Fatal(err)
+       }
+       defer res.Body.Close()
+       if v := res.Header.Get("Foo"); v != "" {
+               t.Errorf(`unexpected "Foo" header: %q`, v)
+       }
+       if v := res.Header.Get("Foo "); v != "bar" {
+               t.Errorf(`bad "Foo " header value: %q, want %q`, v, "bar")
+       }
+}
index feb464b2f284ec1b8db79319084f9ff71b13deaa..6a37b2d2c453aefef738a53f7f9d9dee5c0c9eea 100644 (file)
@@ -492,18 +492,12 @@ func (r *Reader) ReadMIMEHeader() (MIMEHeader, error) {
                        return m, err
                }
 
-               // Key ends at first colon; should not have trailing spaces
-               // but they appear in the wild, violating specs, so we remove
-               // them if present.
+               // Key ends at first colon.
                i := bytes.IndexByte(kv, ':')
                if i < 0 {
                        return m, ProtocolError("malformed MIME header line: " + string(kv))
                }
-               endKey := i
-               for endKey > 0 && kv[endKey-1] == ' ' {
-                       endKey--
-               }
-               key := canonicalMIMEHeaderKey(kv[:endKey])
+               key := canonicalMIMEHeaderKey(kv[:i])
 
                // As per RFC 7230 field-name is a token, tokens consist of one or more chars.
                // We could return a ProtocolError here, but better to be liberal in what we
index 7cff7b457975407b68df03579bd553f43ac2e5c3..3af77d20c13cb88560b865517120a90dce5a7d1d 100644 (file)
@@ -188,11 +188,10 @@ func TestLargeReadMIMEHeader(t *testing.T) {
        }
 }
 
-// Test that we read slightly-bogus MIME headers seen in the wild,
-// with spaces before colons, and spaces in keys.
+// TestReadMIMEHeaderNonCompliant checks that we don't normalize headers
+// with spaces before colons, and accept spaces in keys.
 func TestReadMIMEHeaderNonCompliant(t *testing.T) {
-       // Invalid HTTP response header as sent by an Axis security
-       // camera: (this is handled by IE, Firefox, Chrome, curl, etc.)
+       // These invalid headers will be rejected by net/http according to RFC 7230.
        r := reader("Foo: bar\r\n" +
                "Content-Language: en\r\n" +
                "SID : 0\r\n" +
@@ -202,9 +201,9 @@ func TestReadMIMEHeaderNonCompliant(t *testing.T) {
        want := MIMEHeader{
                "Foo":              {"bar"},
                "Content-Language": {"en"},
-               "Sid":              {"0"},
-               "Audio Mode":       {"None"},
-               "Privilege":        {"127"},
+               "SID ":             {"0"},
+               "Audio Mode ":      {"None"},
+               "Privilege ":       {"127"},
        }
        if !reflect.DeepEqual(m, want) || err != nil {
                t.Fatalf("ReadMIMEHeader =\n%v, %v; want:\n%v", m, err, want)