-
Notifications
You must be signed in to change notification settings - Fork 17
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
Discrepancies in the Parsing of Content Length header leading to http request smuggling #56
Comments
Thanks for this!
Although I understand why this is suboptimal, as far as I can tell, there's no spec which forbids this. There is a switch for this in https://metacpan.org/release/OALDERS/HTTP-Message-6.36/source/lib/HTTP/Headers.pm#L10-12 |
But accepting multiple content length headers with different values is pretty bad, as it was previosly exploited using http request smuggling by combining a proxy , which treats content_length and content-length as different header and forwards them . But http-daemon treats both of them as same and also multiple content-length with different values were also accepted . RFC About multiple Content-length with different values in the 4th point , the server must reject it with 400 error . |
Right, I'm not saying we shouldn't address this -- I just wasn't aware of any RFC forbidding the use of underscores. Thanks for the link. |
Will there be any CVE for this , as multiple content-length and instead of hyphen , underscore get accepted in content-length . References for HRSPrevious CVE's
Possible Attack Scenarios
|
Just to add some context for the underscore thing. This was well before my time, but I did some digging to find out how we got here:
Previously it had read:
That documentation was removed almost exactly 18 years ago. It looks like the context for this behaviour was around not wanted to quote keys in Setting |
But accepting multiple content length header with different field value is really bad and prone to HRS . |
I'm not arguing that the current behaviour great. So far I'm just providing context for why the code is in its current state. |
Still Investigating... The The The latter behaviour is extremely dubious when dealing with incoming requests, According to the RFC, those are just different headers (unlike case-folding). One such use case is when working with good ole CGI base applications where you do not want to trip over CGI defined Environment Variables. The translation is super helpful when creating a However, it does not hurt most of the times, and I doubt it would lead to any more risks of smuggling... as long as we ensure that both values are the same. As part of the remedy, I would suggest to introduce a new Unless there are other vulnerabilities know related to other headers, I think translating the GIVEN that we do fix the other
|
GET / HTTP/1.1
host: localhost
Content_Length: 3
Content-Length: 22
abcGET /admin HTTP/1.1 The above mentioned request is a potential candidate of HRS . when a proxy thinks content_length as a X header and content-length as RFC standard CL header and downstream the request with a body of 22 bytes . But HTTP Daemon treats the first content_length as the RFC standard header with length of 3 bytes , thus leading to HRS . |
This is currently true because of the way my $len = $r->header('Content-Length'); results in a string value of my $missing = $len - length($buf); the value As I mentioned:
and
In other words: we should fix how we compute |
Will there be any CVE for this , as this falls under CWE 444
Possible attack scenarios are explained in CWE 444 |
I will have a look into that in the morning, I'm unfamiliar with that process, but one it should be your first, right ? |
Yeah , This is my first CVE . I found this while testing on various proxies and servers for parsing discrepancies which may lead to several security considerations for a course in my undergraduate degree . I created a protocol fuzzer tool namely BuzzShock for finding these kinds of discrepancies bugs . |
using Github builtin Security Advisories tool, a new CVE is requested |
It looks like I forgot to include some testing of how things should behave: https://gist.github.com/genio/24c76f2ceab91f7509fb72415aafbd09 @vanHoesel While we should be wanting a positive integer, things like |
@genio, the commits in the Private Repo for the Security Advisory will only accept what is in the RFC, and reject anything else than a unsigned non negative number... as it shows in the RFC Content-Length: 1*DIGIT. As much as I do hate causing breakage rejecting 'something positive' with the plus-sign ( From the set of test you have done for Mojolicious, it looks to me that only the third block is doing the right thing. Tomorrow, I'll try to figure out how to add tests to the new changes. |
there is a fix for it available, and I created a Merge Request. However, I do not know how this all works with Dzil and git-hooks and other nice streamlined deployments. @oalders can you take it from here ? please ? |
@blessingcharles I am trying to understand why your POC 7 (FormFeed \x0c , BackSpace \x08 , Vertical tab \x0b got accepted before and after content-length values) would become an issue once we handle multiple
Perl solutions in general have a history of being lenient towards what they accept as input (and mostly) strict on what is produced as output. Accepting these 'whitespace' characters, being part of the I can easily make the handling of incoming requests more strict by changing the delimiters used when extracting HTTP-Header files from at line 166: /^([^:\s]+)\s*:\s*(.*)/ to /^([^:\s]+):[ \t]*(.*)/ This will be more in line with RFC, where there is no space allowed between the header-field name and the colon ( When doing so, I could then eventually check what has been passed in as Header-field value and deal with the other However, I do not feel comfortable doing so, because that would mean that |
The Transfer-Encoding header also accepting \x09 , \x0c and \x08 with the chunked value , these quirks might lead to HRS if both the server and downstreaming proxy disagree with this . You can refer to this research article https://portswigger.net/research/http-desync-attacks-request-smuggling-reborn , where they mention about this discrepancy problem . Another interesting thing I noted , between header fieldname and colon multiple whitespaces are accepted but in RFC headers no whitespaces should be allowed between them . RFC grammar
header-field = field-name ":" OWS field-value OWS
field-name = token
token = 1*tchar
tchar = "!" / "#" / "$" / "%" / "&" / "'" / "*" / "+" / "-" / "." /
"^" / "_" / "`" / "|" / "~" / DIGIT / ALPHA POCecho -ne "GET / HTTP/1.1\r\nHost: localhost\r\nTransfer-Encoding : \x0cchunked\r\n\r\n3\r\naaa\r\n0\r\n\r\n" | nc 192.168.1.21 8008
echo -ne "GET / HTTP/1.1\r\nHost: localhost\r\nTransfer-Encoding : \x09chunked\r\n\r\n3\r\naaa\r\n0\r\n\r\n" | nc 192.168.1.19 8008
echo -ne "GET / HTTP/1.1\r\nHost: localhost\r\nTransfer-Encoding : \x0bchunked\r\n\r\n3\r\naaa\r\n0\r\n\r\n" | nc 192.168.1.18 8008
Yeah , There is no TE CL attacks are possible but CL CL attacks are currently possible which falls under CWE 444 , but after fixing [by rejecting multiple CL with different values and treating content_length as X header] it ,I think the major issue will be resolved from my point of view . |
I was reading that, and would be very unpleasantly surprised to see HTTP-Header field names show up like |
Waiting for approval from @simbabque and guidance from @oalders to get this issue sorted. |
Yeah it is surprise , but most of the webservers are parsing like it eg: nodejs , golang , actix . Accepting the above mentioned header field-name , but they are rejecting if a space is encountered between header-field name and colon with 400 status code according to the RFC . POCOn nodejs , golang , actix for different tchar characters , they are accepting it but rejecting if space presents Random-header = fru.*\!*'&%.brf\t: nfrunib
echo -ne "GET / HTTP/1.1\r\nHost : localhost\r\nfru.*\!*'&%.brf\t: nfrunib\r\n\r\n" | nc localhost 8003 |
The work is going on in the background. 😄 |
Poor parsing of content-length header in httpdaemon will lead to http request smuggling
RFC security considerations
Libwwwperl parses poorly the content-length header , if a proxy downstream a request to Libwwwperl which violates RFC in parsing
the content-length header will lead to http request smuggling , as it ambigiously parse the incoming request and contradicts with
the downstreaming proxy
Examples:
content_length header it will lead to http request smuggling
Reference for http request smuggling
POC
Below here I attached all the poc for the discrepancies occured in httpdaemon in parsing the request which will lead to http request
smuggling
Discrepancy in Parsing
1. Multiple Content-Length with different values got accepted , which is violation according to RFC ,and can lead to http request smuggling
POC
2. Failed to parse the Content-Length correctly
Eg : Content-Length: 3 3 , Content-Length: 3\r\n 1
POC
3. negative content-length field values got mapped to positive values differently
Eg : -3 = 1 , -2 = 2 , -1 = 3
POC
4. +ve sign got accepted before content-length field value
5. Content_Length header got accepted as content-length , this will definitely lead to http request smuggling
6. decimal values got accepted in content-length values
7. FormFeed \x0c , BackSpace \x08 , Vertical tab \x0b got accepted before and after content-length values
Content-Length: [prefix]3[suffix]
version 6.14
Code to Reproduce
The text was updated successfully, but these errors were encountered: