5 ms·
I think the real problem here is that people are writing web servers that don't enforce spec. As soon as a space in a header name is found, a 400 Bad Request n
by Sohcahtoa82 5y ago
I think the real problem here is that people are writing web servers that don't enforce spec.
As soon as a space in a header name is found, a 400 Bad Request needs to be thrown. "Content-Length abcd: 0" is invalid and should never be accepted.
- rini17 5y agoMore interesting is why Content-Length abcd: is treated same as Content-Length: at all? Someone overoptimized the header lookup? Then perhaps other kinds of extensions like Content-Length-abcd are possible, not only with space?
- kingcharles 5y agoI'm guessing they just check what each line starts with. Then they probably split the line on the : to get the value. That would produce the results seen. It shows just how careful you have to be when writing code that is Internet-facing, and especially on the scale of AWS where you have half the world's hackers trying to find exploits. I'm not even looking for exploits and I find them every day. For instance, I wanted to read some magazines the other day but they were behind a paywall. Just to see what was behind the wall I checked for a sitemap file. 35MB sitemap.xml contains direct links to the full downloads of every item with no auth needed.
- thephyber 5y ago> It shows just how careful you have to be when writing code that is Internet-facing All code. “Internet facing” is not the only relevant qualification. Any code where user-generated code is parsed should be carefully written, tested, and documented. Edge cases should be identified and described in specs. Non-compliant software should be identified and shamed (or preferably PRed). I know that AWS has already patched some HTTP Smuggling attacks maybe 3 years ago, but I don’t remember if is was the same AWS feature (the previous one might have been CloudFront) and the parsing error might have been a little different.
- Sohcahtoa82 5y agoMore likely, they're stopping on the first space OR colon to parse the header name since "Content-Length : 0" is valid. Personally, if I were writing a HTTP request parser while being lazy about enforcing spec, I'd split ONLY on the colon, then just strip the white space on either side of both the header name and value. In Python: header, value = line.split(':', maxsplit=1) header = header.strip().lower() value = value.strip() After that, `header` should ALWAYS be checked via equality, and never `.startswith(...)`.
- andrius4669 5y agoYou definitely shouldn't strip left side of header, as space preceding that is syntax for header splitting over multiple lines at least in email. Not sure if this applies to http though, but some parsers may do that anyway, and some don't. Just shows how easy it is to be wrong by being lazy with http parsing.
- thephyber 5y agoNote that parsing is likely more complicated than your code because you have assumed that your “line” has already been identified before parsing the line. AFAIK there is an escape sequence for the header delineator (\r\n). Also, your code doesn’t fix the issue where a header name with a white space is accepted (which may violate expectations, depending on the server). Your pseudo code also doesn’t handle edge cases where 2 headers which normalize to the same stripped text collide. One HTTP smuggling vector is the front server keeping a different header value than the back server when 2 header names collide.
- gmfawcett 5y ago> since "Content-Length : 0" is valid. According to which spec? RFC 7230 allows optional whitespace (OWS) after the colon, but not before it: header-field = field-name ":" OWS field-value OWS
- lamontcg 5y agoProbably backwards compatibility with some ancient webserver from the dawn of HTTP which became frozen into the protocol forever and everyone who proposes fixes that runs into some grey hair who is worried about xkcd-spacebar'ing someone out there, even though its probably no longer relevant, but standards bodies being what they are it is difficult to accept any risk.
- legulere 5y agoLike so many web technologies http headers are a big complicated ad-hoc mess (some headers are specified in a way that’s not standard compliant), so it’s to be expected that there things like this happening.
- thephyber 5y agoThere is something more than that. HTTP Content smuggling has already been identified as a significant issue and the largest cloud providers and Reverse Proxy server software should have already fixed these issues. I started a GitHub repo to run integration tests for popular combinations of reverse proxy to popular language web servers to identify these gaps in expectations (how duplicates, capitalization, white space, etc affect HTTP headers in different servers)
- userbinator 5y agoThe real problem is text-based protocols, which are naturally quite flexible (and rather inefficient to parse). If HTTP headers were simply a single-byte identifier[1], then e.g. 03 is Content-Length and there's no way to interpret that as anything else. I've made similar comments about such before: https://news.ycombinator.com/item?id=23582056 https://news.ycombinator.com/item?id=23582056 [1] A single byte is sufficient --- there have been far less than 255 headers defined since the beginnings of HTTP; maybe custom ones can be defined in an additional space, but a byte is actually already more than sufficient to convey the same information that would take dozens of bytes in the current text-based protocol.
- chii 5y agoso you're just describing what amounts to packets, which is basically like udp or tcp. The reason http is good is due to the text nature (along with whatever drawbacks associated with it being text).
- jamesfinlayson 5y agoThat'd be nice - no uppercase/lowercase mixups (or the need to support Referer and Referrer).
- tablespoon 5y ago> [1] A single byte is sufficient --- there have been far less than 255 headers defined since the beginnings of HTTP; maybe custom ones can be defined in an additional space, but a byte is actually already more than sufficient to convey the same information that would take dozens of bytes in the current text-based protocol. You're probably only talking about ones defined in something like an RFC. I'm pretty sure there are far more than 255 different HTTP headers in use just by my employer's in-house stuff. > more than sufficient to convey the same information that would take dozens of bytes in the current text-based protocol It's 2021, who cares about dozens of bytes? I'd wager that's far less than 1% of the size of most HTTP exchanges, and it means generic tooling can actually show you something useful for all that custom stuff it's guaranteed not to know the specifics of.
- 5y ago