-
Notifications
You must be signed in to change notification settings - Fork 17.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
net/http: accepts invalid empty Content-Length header #61679
Comments
The Content-Length must be a valid numeric value, empty values should not be accepted. See: https://www.rfc-editor.org/rfc/rfc9110.html#name-content-length Fixes golang#61679
I'm investigating this issue and I'm not sure what is the proper way to handle this. Most places read the Content-Length header from |
The Content-Length must be a valid numeric value, empty values should not be accepted. See: https://www.rfc-editor.org/rfc/rfc9110.html#name-content-length Fixes golang#61679
In general, That said, probably the simplest fix is to have var laxContentLength = godebug.New("httplaxcontentlength")
func parseContentLength(clHeaders []string) (int64, error) {
if len(clHeaders) == 0 {
return -1, nil
}
cl := textproto.TrimString(clHeaders[0])
if cl == "" {
if laxContentLength.Value() == "1" {
return -1, nil
}
return 0, badStringError(…)
}
…
} Then the call site in if len(contentLens) > 0 {
n, err := parseContentLength(contentLens)
if err != nil {
return -1, err
}
return n, nil
} And the call in if n, err := parseContentLength(t.Header["Content-Length"]); err != nil {
return err
} else {
t.ContentLength = n
} |
The Content-Length must be a valid numeric value, empty values should not be accepted. See: https://www.rfc-editor.org/rfc/rfc9110.html#name-content-length Fixes golang#61679
Change https://go.dev/cl/517336 mentions this issue: |
The Content-Length must be a valid numeric value, empty values should not be accepted. See: https://www.rfc-editor.org/rfc/rfc9110.html#name-content-length Fixes golang#61679
The Content-Length must be a valid numeric value, empty values should not be accepted. See: https://www.rfc-editor.org/rfc/rfc9110.html#name-content-length Fixes golang#61679
The Content-Length must be a valid numeric value, empty values should not be accepted. See: https://www.rfc-editor.org/rfc/rfc9110.html#name-content-length Fixes golang#61679
I don't think this is correct. Given that, this doesn't look like a viable request smuggling vector to me. Without a Is it worth rejecting requests with an empty |
This is not the correct behavior either. From RFC 9112:
Thus, ignoring the empty This is a problem because other servers (and proxies...) interpret the empty CL header in exactly the way you described (by consuming the remaining bytes on the line). This discrepancy is a request smuggling vector. The empty header value should not be allowed at all. It should be rejected when encountered, along with all other malformed CL headers. This is what all of the large web servers do, and this is what net/http should do as well. |
I assert that close to zero users will be affected, because any HTTP client generating requests with empty CL headers would be incompatible with the vast majority of the web. (Apache and Nginx both reject all messages containing empty CL headers) Thus, it seems likely to me that their only use case is request smuggling. |
Right, I'd forgotten that request and response behave differently when Content-Length is missing. I'm convinced, rejecting invalid values is the right thing to do. |
The Content-Length must be a valid numeric value, empty values should not be accepted. See: https://www.rfc-editor.org/rfc/rfc9110.html#name-content-length Fixes golang#61679
The Content-Length must be a valid numeric value, empty values should not be accepted. See: https://www.rfc-editor.org/rfc/rfc9110.html#name-content-length Fixes golang#61679
The Content-Length must be a valid numeric value, empty values should not be accepted. See: https://www.rfc-editor.org/rfc/rfc9110.html#name-content-length Fixes golang#61679
Change https://go.dev/cl/549198 mentions this issue: |
For #51971 For #61679 Change-Id: Ie7b44201a9c40f5563c6d6051d22ae807ad0480d Reviewed-on: https://go-review.googlesource.com/c/go/+/549198 LUCI-TryBot-Result: Go LUCI <[email protected]> Auto-Submit: Damien Neil <[email protected]> Reviewed-by: Mauri de Souza Meneguzzo <[email protected]> Reviewed-by: Roland Shoemaker <[email protected]>
For golang#51971 For golang#61679 Change-Id: Ie7b44201a9c40f5563c6d6051d22ae807ad0480d Reviewed-on: https://go-review.googlesource.com/c/go/+/549198 LUCI-TryBot-Result: Go LUCI <[email protected]> Auto-Submit: Damien Neil <[email protected]> Reviewed-by: Mauri de Souza Meneguzzo <[email protected]> Reviewed-by: Roland Shoemaker <[email protected]>
What version of Go are you using (
go version
)?Does this issue reproduce with the latest release?
Yes.
What operating system and processor architecture are you using (
go env
)?What did you do?
net/http
.What did you expect to see?
A 400 response informing me that the request is invalid beacuse its Content-Length header does not conform to the grammar rule from the relevant RFCs.
Section 8.6 of RFC 9110 defines the acceptable values in a
Content-Length
field value as follows:DIGIT
is defined as follows in RFC 5234:What did you see instead?
A 200 response. The server interpreted the empty
Content-Length
header as though it wereContent-Length: 0
. This is potentially of use in a request smuggling exploit chain, because the semantics of an empty CL header are not defined, as far as I am aware.Suggested fix
AIOHTTP, Apache httpd, Boost::Beast, Gunicorn, H2O, IIS, jetty, lighttpd, NGINX, Node.js, Apache Tomcat, and Tornado all reject requests containing empty CL headers. I suggest that
net/http
do the same.The text was updated successfully, but these errors were encountered: