CRLF-Powered Desync Attacks: Beheading HTTP Streams

chillax1 pts0 comments

CRLF-Powered Desync Attacks: Beheading HTTP Streams | PortSwigger Research

CRLF-Powered Desync Attacks: Beheading HTTP Streams

Tom Stacey

Researcher

@t0xodile

Published: Wednesday, 5 August 2026 at 23:30 UTC

Updated: Wednesday, 5 August 2026 at 23:30 UTC

Abstract

In this paper we’ll show that HTTP Header Injection is severely underestimated. Forget open redirects or Cross-Site Scripting and instead, embrace the catastrophic potential of the CRLF-Powered Desync Worm.

We’ll begin by teaching you how to take a simple header injection primitive and transform it into a full-blown desync worm. Next, we’ll introduce novel methods to detect and exploit IP and connection-locked desyncs which prevent cross-network exploitation by shifting the desync’s execution into the victim's browser to generate an XSS out of thin air and steal HTTPOnly cookies.

Along the way, we’ll help you avoid accidental desync disasters like logging every active user of your target into your own account causing your shopping cart to be overwritten with random users’ items on every refresh.

Collaboration

This paper was co-authored with Tobia Righi from TurtleSec. Over the last year, we've collaborated on this research in order to ensure that every single technique was pushed to its absolute limit. This went rather well, and we ended up co-presenting the results at BHUSA and DEFCON. You can read his own version of the paper on TurtleSec’s blog.

Research Origins<br>HTTP Request Smuggling<br>Request Header Injection<br>Detecting Request Header Injection<br>HTTP Request Splitting<br>Response Queue Poisoning via Request Splitting<br>RQP Inside the Infrastructure of a CDN<br>Header Injection via Custom Upstream Header<br>Header Injection via Non-Path Insertion Points<br>AI-Generated Detection Techniques<br>CRLF-Powered CL.TE Desync Attacks<br>The Desync Disaster<br>The Nested Response Mystery<br>Cache Poisoning & AI-Generated HEAD Gadget<br>Browser-Powered CRLF Desync Attacks<br>CRLF-Powered Desync Worms<br>HTTP Request Tunnelling<br>Bypassing Blind Request Tunnelling<br>Bypassing Access Controls via Request Tunnelling<br>Browser-Powered Connection-Locked Desyncs<br>Browser-Powered 0.CL<br>Browser-Powered IP-Locked Desyncs<br>Browser-Powered Request Splitting - HEAD + Range<br>Browser-Powered Request Splitting - Stealing HTTPOnly Cookies<br>Bypassing Response Header Removal<br>Response Header Injection<br>Cookie Tossing - TikTok<br>XSS on a Redirect<br>Reverse Desync Attacks<br>Defence<br>Tooling<br>Further Research<br>Key Takeaways<br>Conclusion

Research Origins

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 realised the technique’s potential and started to spot gaps in its current understanding.

HTTP Request Smuggling

This entire paper will talk extensively about request smuggling, and therefore we highly recommend going through our free Web Security Academy resources if you’re not already familiar.

Request Header Injection

In Nginx configurations (an extremely popular web server) if the $uri variable is included in the proxy_pass directive, Nginx will normalise the request path before use, url-decoding any encoded characters including CRLF sequences (%0d%0a). This allows us to inject new lines into the request that is forwarded upstream of Nginx, giving us full control over the structure of that request.

# nginx.conf<br>http {<br>upstream backend {<br>server backend.internal.com:8000;<br>server {<br>location / {<br>proxy_pass http://backend$uri;

For example, here we inject an invalid Content-Length header whilst maintaining the syntax of the request and produce an expected 400 response.

GET /%20HTTP/1.1%0d%0aContent-Length:%20X%0d%0aX:%20x HTTP/1.1<br>Host: example.com<br>GET / HTTP/1.1<br>Content-Length: X<br>X: x HTTP/1.1<br>Host: example.com<br>HTTP/1.1 400 Bad Request<br>To better represent the structure of these injections, we’ll use the following Hackvertor syntax, which is extremely helpful when it comes to working with these kinds of vulnerabilities inside Burp Suite.

GET / HTTP/1.1<br>Content-Length: X<br>X: x HTTP/1.1<br>Host: example.com<br>Detecting Request Header...

request http header desync powered injection

Related Articles