Skip to content

Commit 26049f6

Browse files
jeddenlearsc
authored andcommitted
net/http: close server conn after broken trailers
Prior to this change, broken trailers would be handled by body.Read, and an error would be returned to its caller (likely a Handler), but that error would go completely unnoticed by the rest of the server flow allowing a broken connection to be reused. This is a possible request smuggling vector. Fixes #12027. Change-Id: I077eb0b8dff35c5d5534ee5f6386127c9954bd58 Reviewed-on: https://go-review.googlesource.com/13148 Reviewed-by: Russ Cox <rsc@golang.org>
1 parent f51b7fb commit 26049f6

File tree

2 files changed

+40
-0
lines changed

2 files changed

+40
-0
lines changed

src/net/http/serve_test.go

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1373,6 +1373,40 @@ func TestRequestBodyReadErrorClosesConnection(t *testing.T) {
13731373
}
13741374
}
13751375

1376+
func TestInvalidTrailerClosesConnection(t *testing.T) {
1377+
defer afterTest(t)
1378+
for _, handler := range testHandlerBodyConsumers {
1379+
conn := new(testConn)
1380+
conn.readBuf.WriteString("POST /public HTTP/1.1\r\n" +
1381+
"Host: test\r\n" +
1382+
"Trailer: hack\r\n" +
1383+
"Transfer-Encoding: chunked\r\n" +
1384+
"\r\n" +
1385+
"3\r\n" +
1386+
"hax\r\n" +
1387+
"0\r\n" +
1388+
"I'm not a valid trailer\r\n" +
1389+
"GET /secret HTTP/1.1\r\n" +
1390+
"Host: test\r\n" +
1391+
"\r\n")
1392+
1393+
conn.closec = make(chan bool, 1)
1394+
ln := &oneConnListener{conn}
1395+
var numReqs int
1396+
go Serve(ln, HandlerFunc(func(_ ResponseWriter, req *Request) {
1397+
numReqs++
1398+
if strings.Contains(req.URL.Path, "secret") {
1399+
t.Errorf("Handler %s, Request for /secret encountered, should not have happened.", handler.name)
1400+
}
1401+
handler.f(req.Body)
1402+
}))
1403+
<-conn.closec
1404+
if numReqs != 1 {
1405+
t.Errorf("Handler %s: got %d reqs; want 1", handler.name, numReqs)
1406+
}
1407+
}
1408+
}
1409+
13761410
// slowTestConn is a net.Conn that provides a means to simulate parts of a
13771411
// request being received piecemeal. Deadlines can be set and enforced in both
13781412
// Read and Write.

src/net/http/transfer.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -637,6 +637,12 @@ func (b *body) readLocked(p []byte) (n int, err error) {
637637
if b.hdr != nil {
638638
if e := b.readTrailer(); e != nil {
639639
err = e
640+
// Something went wrong in the trailer, we must not allow any
641+
// further reads of any kind to succeed from body, nor any
642+
// subsequent requests on the server connection. See
643+
// golang.org/issue/12027
644+
b.sawEOF = false
645+
b.closed = true
640646
}
641647
b.hdr = nil
642648
} else {

0 commit comments

Comments
 (0)