-
Notifications
You must be signed in to change notification settings - Fork 18k
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: readRequest fails to handle URIs ending with space characters #63598
Comments
cc @neild |
Ideally, it would be nice to optionally have the functionality like this, to allow them to pass through, but escaped. |
Generally Go's |
It's a tricky one - It isn't commonly used and virtually any client in the past 15+ years shouldn't ever do this, but we're finding incorrect use of it in some Adobe Shockwave games, games closer to 20-25 years old. The behavior is reflected in every other software I've tried - Fiddler, Python, Apache etc all handle it fine (in fact the http://go.dev/ site itself considers it valid). I've really struggled to find documentation for why they support it in the first place, the only thing I could dig up was this section of the URI Generic Syntax RFC from 1998 under 'Syntax Notation and Common Elements', but it was removed by the time the current RFC from 2005 appears.
Obviously having this supported is something I'd like considering our use case, but I'm understanding of why you might also choose not to. |
Just to add some more samples of it working Using OpenSSL to test, go.dev worked with any number of spaces
I tried to find other examples of nginx and apache, but I couldn't get any request to work openssl with nginx.org or facebook.com, everything was rejected, I am sure I am doing something wrong. All sites rejected anything starting with a space, but every site I tried that I could get to work normally worked with multiple spaces between Method and URI and URI and Protocol and Protocol to end. |
We use Golang to parse raw http request in cybersecurity, and there is an easy sql inject example, which can't be parsed by http.ReadRequest.
Of cause, this is not a Generally http request, but we want to use Go do more 😁 |
cc @golang/security sounds like we should reject making the parser any laxer |
I mean we need more laxer to make Golang can be used to parse these no generally request. 😂 |
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
)?go env
OutputWhat did you do?
I work with particularly old software, which in some cases will send HTTP requests without stripping whitespace from the Request URI. After changing our proxy to be Go based, these requests just weren't being received by the proxy between the application and the file server.
When putting a Python or Fiddler proxy between the application and Go proxy server the requests would suddenly start working. The only idea I could come up with is that they're sanitizing the requests are they pass through.
I went digging and found that when reading the request,
parseRequestLine
works on the assumption that each element of the request line is seperated by a single space character, as defined in the RFC. When it splits, the HTTP proto gets an extra space before it. This means it'll error as a malformed proto. I know this behaviour isn't strictly supported by the RFC but I'd like to see it reflect how other software handles it.The easiest way to test this is to send variants of
GET /test HTTP/1.0
andGET /test HTTP/1.0
with something like telnet to a Go HTTP server, where the latter will return 400 Bad Request.For demonstration just to display where the space prefixing the proto comes from, I took a copy of the current
parseRequestLine
and then fed the proto intoParseHTTPVersion
https://go.dev/play/p/8F2Q9A5Fhx1
What did you expect to see?
What did you see instead?
The text was updated successfully, but these errors were encountered: