golang / go

The Go programming language

Home Page:https://go.dev

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

net/http: Empty header names erroneously accepted

kenballus opened this issue · comments

Go version

go version devel go1.23-b3acaa8230 Tue Jan 23 20:08:07 2024 +0000 linux/amd64

Output of go env in your module/workspace:

GO111MODULE=''
GOARCH='amd64'
GOBIN=''
GOCACHE='/root/.cache/go-build'
GOENV='/root/.config/go/env'
GOEXE=''
GOEXPERIMENT=''
GOFLAGS=''
GOHOSTARCH='amd64'
GOHOSTOS='linux'
GOINSECURE=''
GOMODCACHE='/root/go/pkg/mod'
GONOPROXY=''
GONOSUMDB=''
GOOS='linux'
GOPATH='/root/go'
GOPRIVATE=''
GOPROXY='https://proxy.golang.org,direct'
GOROOT='/app/go'
GOSUMDB='sum.golang.org'
GOTMPDIR=''
GOTOOLCHAIN='auto'
GOTOOLDIR='/app/go/pkg/tool/linux_amd64'
GOVCS=''
GOVERSION='devel go1.23-b3acaa8230 Tue Jan 23 20:08:07 2024 +0000'
GCCGO='gccgo'
GOAMD64='v1'
AR='ar'
CC='gcc'
CXX='g++'
CGO_ENABLED='1'
GOMOD='/dev/null'
GOWORK=''
CGO_CFLAGS='-O2 -g'
CGO_CPPFLAGS=''
CGO_CXXFLAGS='-O2 -g'
CGO_FFLAGS='-O2 -g'
CGO_LDFLAGS='-O2 -g'
PKG_CONFIG='pkg-config'
GOGCCFLAGS='-fPIC -m64 -pthread -Wl,--no-gc-sections -fmessage-length=0 -ffile-prefix-map=/tmp/go-build965832195=/tmp/go-build -gno-record-gcc-switches'

What did you do?

Started a web server using net/http, and sent a request that contained a header with an empty name. (for example, GET / HTTP/1.1\r\n: ignored\r\nHost: whatever\r\n\r\n)

What did you see happen?

The server ignored the offending header (It was not available through the Request.Header interface)

What did you expect to see?

A 400 response. This is what Apache, Nginx, H2O, Node (with llhttp built from main), Lighttpd, and most other popular HTTP implementations do.

There are two reasons to reject messages with empty headers:

  1. The standard says that header names must be nonempty:
  field-name     = token
  token          = 1*tchar
  tchar          = "!" / "#" / "$" / "%" / "&" / "'" / "*"
                 / "+" / "-" / "." / "^" / "_" / "`" / "|" / "~"
                 / DIGIT / ALPHA
                 ; any VCHAR, except delimiters
  1. Some servers treat \r\n:\r\n as equivalent to \r\n\r\n. Those servers will then see the end of the message body where net/http sees (and ignores) an empty header. This is a potential HTTP request smuggling vector.

Thanks for the bug report, I'll take on this.

Change https://go.dev/cl/558095 mentions this issue: net/textproto: reject HTTP requests with empty header keys

It turns out that we had handled this kind of case in a previous CL 11242. Although it didn't seem like a good idea to skip it and do nothing about it in that CL, we unfortunately might break some existing HTTP clients if we submit CL 558095.

Not sure how this issue is going to be tackled eventually: remain doing nothing about it or reject empty header keys along with breaking a tiny backward compatibility (in that case, we may need a proposal?). @neild

This is very unlikely to break any existing clients, because all the other large HTTP implementations already reject requests containing empty keys, so any client producing empty header keys would be incompatible with nearly every web server out there.