HTTP Request Smuggling
HTTP Request Smuggling
in 2020
Amit Klein
Safebreach Labs
About Me
• 29 years in InfoSec
• VP Security Research Safebreach (2015-Present)
• 30+ Papers, dozens of advisories against high profile products
• Presented in BlackHat (3 times), DefCon (twice), Usenix, NDSS, HITB, InfoCom,
DSN, RSA, CertConf, Bluehat, OWASP Global (keynote), OWASP EU, AusCERT
(keynote) and more
• http://www.securitygalore.com
Introduction
What is HTTP Request Smuggling?
• 3 Actors
• Attacker (client)
• Proxy/firewall
• Web server (or another proxy/firewall)
• Attack
• Attacker connects (80/tcp) to the proxy, sends ABC
• Proxy interprets as AB, C, forwards to the web server
• Web server interprets as A, BC, responds with r(A), r(BC)
• Proxy caches r(A) for AB, r(BC) for C.
• AKA “HTTP desync Attack”
Different interpretations of the TCP stream
POST /hello.php HTTP/1.1
...
Content-Length: 0
Content-Length: 44
• Still a problem – rule 932150 is triggered… (Unix direct command execution), but
this can be worked around too:
POST /hello.php HTTP/1.1
…
Content-Length: 65
Content-Length abcde: 3
[UPDATE July 17th, 2020] For Variants 1 and 5, Squid Team assigned
CVE-2020-15810 to these issues and suggested the following (configuration)
workaround:
relaxed_header_parser=off
A fix is expected on August 3rd (Squid security advisory SQUID-2020:10)
Part 2
New Defenses
Flawed Approach #1
Normalization of outbound HTTP headers (for proxy servers)
• Good for HTTP devices behind the proxy
• Not effective at all for attacks happening between the proxy and devices in front
of it.
• You are P2 in the sequence: Client → P1 → P2 → WS
• P1 uses (say) the first CL, P2 uses the last CL.
• HTTP Request Smuggling can happen between P1 and P2.
• Blame game?
• Think of P2 → WS as an abstraction for a web server WS’:
Client → P1 → WS’
• WS’ accepts multiple CL headers, uses the last one.
• Is WS’ vulnerable to HTTP Request Smuggling?
• If you answered “Yes”, then P2 is vulnerable to HTTP Request Smuggling.
Flawed Approach #2
One (new) TCP connection per outbound request (proxy servers)
• Good for HTTP devices behind the proxy
• Not effective at all for attacks happening between the proxy and devices in front
of it.
• Same as previous slide.
mod_security + CRS?
• Pros:
• True WAF
• Free
• open source
• Cons
• Only supports IIS, Apache, nginx
• Rudimentary defense (only) against HTTP Request Smuggling
Library: https://github.com/SafeBreach-Labs/RSFW
Part 3
New Research
Challenges
New Research Challenges
• Promising/suspicious anomalies in an HTTP device
• I can describe a “matching” behavior that leads to HTTP Request Smuggling
• No “matching” behavior found (so far)
• Naïve example (2005…):
• I notice a web server which takes the first header in a double CL
• A matching behavior: a proxy which takes the last CL header (but keep both headers)
• But in my lab, I can only find proxy servers that either take the first header, or reject
the request
CR in a header name is a hyphen
• Content\rLength– treated by one web server as “Content-Length”.
• Why? I suspect a quick-and-dirty “uppercasing”, using OR with 0x20:
(‘\r’ | 0x20) == ‘-’
• Sought matching proxy behavior: ignore (forward as-is)
• Attack: the web server expects a body (but using a GET request, the web server
will immediately forward the request to the application without a body!, and will
later discard the body data sent by the proxy)
• But: All proxy servers I have either reject (400) or modify.
“Signed” Content-Length
• Content-Length: +1234
• Non-RFC
• Some proxy implementations use API a-la atoi() which accepts a sign
• Sought matching web server behavior: ignore
• Attack: obvious (the web server has de-facto CL=0)
• NOTE: doesn’t work if the proxy normalizes the CL header.
• But: All web servers I have either reject (400) or honor.
• Vendor status: fixed by Squid (CVE-2020-15049), Abyss, Go.
Content-Length value with SP
• Content-Length: 12 34
• Non RFC
• Nginx (as a web server) ignores the header
• Sought behavior: a proxy that uses the value (as 1234/12/34) and forwards the
header as-is
• Attack: obvious (nginx sees de-facto CL=0)
• But: all proxy servers I have either reject (400) or remove the header
• Reported to nginx. WONTFIX (“this doesn't
look like a vulnerability in nginx, as the request in question
cannot be passed through a complaint HTTP proxy with the header
intepreted as a Content-Length header”)
Chunky Monkey Business
• One web server simply ignores Transfer-Encoding (i.e. doesn’t support
chunking)
• Non RFC
• Sought behavior: a proxy server that prefers TE over CL (but does not modify)
• Attack: TE+CL.
• But: all proxy servers I have normalize the request (either per CL or per TE)
Conclusions
Take-Aways
• HTTP Request Smuggling is still a thing (in 2020, in COTS SW)
• Existing open source solutions are lacking
• There is a more robust approach for defending against HTTP Request
Smuggling, and it is feasible
• There are still some interesting challenges in this area!
Thank You!