CRLF Powered Desyncs
This blogpost is really important to us, it is the culmination of over a year of research carried out by Tobia Righi and PortSwigger researcher Thomas Stacey. rember to mention black hat and defcon
In this blogpost we will show how HTTP Header Injection can be turned into really powerful desync attacks, allowing you to take over victim accounts without user interaction, cause mass-PII leaks, access internal sensitive data, gain XSS out of thin air and a lot more. All the attacks showcased in this blogpost are from real world applications running bug bounty or vulnerability disclosure programs.
The origin story
Around 1 year ago, we came across this post on Bluesky which mentioned an attack technique we’d heard of, but never come across in the wild. This post bothered us, as it claimed the attack was “not that uncommon” in spite of our failure to ever find it. On top of this, we knew of at least two other research papers on the same topic (both of which were in their respective year’s Top 10 Web Hacking Techniques).
The first, Making HTTP header injection critical via response queue poisoning by James Kettle explains how you can achieve HTTP request smuggling using request splitting, citing a single case study as evidence. The second, HTTP Request Splitting Vulnerabilities Exploitation by Sergey Bobrov explores how common request splitting actually is, due to a common Nginx misconfiguration, but only briefly mentions the potential for desyncs.
This got us thinking. What would happen if we took James’ desync techniques, and applied them to everything that seemed vulnerable to HTTP header injection. After our first encounter, we quickly realized the technique’s potential and started to spot gaps in its current understanding.
Nginx’s fatal flaw
Sergey’s research showed us that when the $uri variable is included in a proxy_pass directive nginx will normalize the request path before it is used. This includes CRLF sequences %0d%0a, allowing us to inject new lines into the request forwarded by nginx allowing us to for example inject arbitrary headers which will get processed by the application upstream of nginx.
| |
The above is an example of a vulnerable configuration. If you’re a developer and you recognize this from your own app you may go and patch before finishing this post, but promise to come back :).
GET /%20HTTP/1.1%0d%0aContent-Length:%20-1%0d%0aX:%20x HTTP/1.1 GET / HTTP/1.1
Host: example.com --[normalize]--> Content-Length: -1
X: x HTTP/1.1
Host: example.com
In the example above, we inject an invalid Content-Length header resulting in the application returning a 400 Bad Request response, telling us that our injected header was in fact processed.
For the rest of this post we will be using Hackvertor notation to represent our payloads as it is clearer and easier on the eyes:
GET /<@urlencode_all> HTTP/1.1
Content-Length: -1
X: x</@urlencode_all> HTTP/1.1
Host: example.comDetection
All detection tech
Request splitting
Theory
Response Queue Poisoning
- Theory
- Why we can do it with our CRLF injection
RQP inside a CDN
Case
RQP in a major telecom provider
Case
CRLF-Powered CL.TE Desync Attacks
Ok lots of confusing words:
- Explain CL.TE
- Explain it in context of CRLF
The CL.TE desync disaster
- Clothing store
- Shopping cart crazyness
- ATO
Pwning phones across the world
- Intro
- Blind xss
- ATO via qr code
Browser-Powered CRLF Desync Attacks
- Browser spec
- Browser powered desync worm
Request Tunneling
- Explaination
- Bypasses with Expect header
Exploiting desyncs in the browser
- Connection locked and ip locked is why we need the browser
Browser-Powered 0.CL in a streaming service
Case XSS OUT OF THIN AIR
Browser-Powered Desync using iframes
Case
Bypassing HttpOnly with Browser-Powered desync
Case
Response header injection
- Next logical steps
- Nginx configuration
- Location problems
Cookie tossing
Case
XSS on a Redirect Response
- Hunting for origin to edge headers
- Other impacts that can be achieved
- Case -> mention johan
Reverse desyncs
Theory