From: Eric Wong Date: Tue, 19 Oct 2021 21:26:15 +0000 (+0000) Subject: httpd: reject requests with spaces in header names X-Git-Tag: v1.7.0~97 X-Git-Url: http://www.git.stargrave.org/?p=public-inbox.git;a=commitdiff_plain;h=49e653848f34a179f38c1738f537f69c1205e92a httpd: reject requests with spaces in header names Malicious clients may attempt HTTP request smuggling this way. This doesn't affect our current code as we only look for exact matches, but it could affect other servers behind a to-be-implemented reverse proxy built around our -httpd. This doesn't affect users behind varnish at all, nor the HTTPS/HTTP reverse proxy I use (I don't know about nginx), but could be passed through by other reverse proxies. This change is only needed for HTTP::Parser::XS which most users probably use. Users of the pure Perl parser (via PLACK_HTTP_PARSER_PP=1) already hit 400 errors in this case, so this makes the common XS case consistent with the pure Perl case. cf. https://www.mozilla.org/en-US/security/advisories/mfsa2006-33/ --- diff --git a/lib/PublicInbox/HTTP.pm b/lib/PublicInbox/HTTP.pm index 0f4b5047..18a19250 100644 --- a/lib/PublicInbox/HTTP.pm +++ b/lib/PublicInbox/HTTP.pm @@ -91,6 +91,7 @@ sub event_step { # called by PublicInbox::DS } $self->do_read($rbuf, 8192, length($$rbuf)) or return; } + return quit($self, 400) if grep(/\s/, keys %env); # stop smugglers $$rbuf = substr($$rbuf, $r); my $len = input_prepare($self, \%env) // return write_err($self, undef); # EMFILE/ENFILE diff --git a/t/httpd-corner.t b/t/httpd-corner.t index cec754c9..0a613a9e 100644 --- a/t/httpd-corner.t +++ b/t/httpd-corner.t @@ -82,7 +82,12 @@ if ('test worker death') { like($body, qr/\A[0-9]+\z/, '/pid response'); isnt($body, $pid, 'respawned worker'); } - +{ + my $conn = conn_for($sock, 'Header spaces bogus'); + $conn->write("GET /empty HTTP/1.1\r\nSpaced-Out : 3\r\n\r\n"); + $conn->read(my $buf, 4096); + like($buf, qr!\AHTTP/1\.[0-9] 400 !, 'got 400 response on bad request'); +} { my $conn = conn_for($sock, 'streaming callback'); $conn->write("GET /callback HTTP/1.0\r\n\r\n");