Live data from Hacker News

Practical HTTP Header Smuggling: Sneaking Past Reverse Proxies to Attack AWS

intruder.io

11–20 of 27 posts

Re: Practical HTTP Header Smuggling: Sneaking Past Reverse Proxies to Attack AWS

#11
post #4

Earlier quoted context omitted.

More 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?

More 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 = val…

Note 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.

Re: Practical HTTP Header Smuggling: Sneaking Past Reverse Proxies to Attack AWS

#12
post #4

Earlier quoted context omitted.

More 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?

I'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 want…

> 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.

Re: Practical HTTP Header Smuggling: Sneaking Past Reverse Proxies to Attack AWS

#13
post #7

Earlier quoted context omitted.

Note that the spec is stricter for field-name than for field-value. Field names are ASCII, while field values are latin1 (or mime encoded but no one cares about mime encoding). And yes I have seen bytes in both names and values in the wild (where bytes in names are invalid but need to be handled gracefully, while bytes in values are effectively valid latin1 if only for legacy reasons) Looking at the bug you linked to…

With HTTP/2 you can theoretically even transmit bytes with all binary values inside them in both names and values - since the values are length-delimited. Based on that, some implementations seem to restrict allowed values to the rules that you describe, while others don't.

Yeah, and really the moral of the story shouldn't be (just) to get good at parsing, but to assume that any two parsers may disagree on how to parse a piece of data as part of your security model.

Re: Practical HTTP Header Smuggling: Sneaking Past Reverse Proxies to Attack AWS

#14

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.

The 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

[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.

Re: Practical HTTP Header Smuggling: Sneaking Past Reverse Proxies to Attack AWS

#15

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.

The 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 [1] A single byte is sufficient --- there have been far less than 255 hea…

so 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).

Re: Practical HTTP Header Smuggling: Sneaking Past Reverse Proxies to Attack AWS

#16
post #4

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.

More 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?

Probably 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.

Re: Practical HTTP Header Smuggling: Sneaking Past Reverse Proxies to Attack AWS

#17

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.

The 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 [1] A single byte is sufficient --- there have been far less than 255 hea…

That'd be nice - no uppercase/lowercase mixups (or the need to support Referer and Referrer).

Re: Practical HTTP Header Smuggling: Sneaking Past Reverse Proxies to Attack AWS

#18

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.

The 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 [1] A single byte is sufficient --- there have been far less than 255 hea…

> [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.

Re: Practical HTTP Header Smuggling: Sneaking Past Reverse Proxies to Attack AWS

#19
post #4

Earlier quoted context omitted.

More 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?

More 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 = val…

You 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.

Re: Practical HTTP Header Smuggling: Sneaking Past Reverse Proxies to Attack AWS

#20
post #4

Earlier quoted context omitted.

More 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?

More 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 = val…

> 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
Post reply on HN