CL.TE Request Smuggling on a Payment Platform
HTTP request smuggling exploits a disagreement between a reverse proxy and its
backend over where one HTTP request ends and the next begins. When the two servers
parse conflicting framing headers differently — one using Content-Length,
one using Transfer-Encoding — the attacker can plant bytes at the end
of one request that the backend processes as the start of the next. CL.TE desync was
confirmed on a payment processing platform: the proxy used Content-Length,
the Apache PHP backend used Transfer-Encoding, and the affected path was
the payment task endpoint.
The confirmation
An HTTP request smuggling scan was run against /tasks.php.
The CL.TE timing probe sent a request where Content-Length covered the
entire body — including a chunked zero-terminator and a smuggled GET prefix. The
front-end forwarded the complete payload; the back-end read the chunked body, saw the
terminator, and left the remainder in the TCP buffer. The probe returned after a 10-second
delay followed by a 404 for the non-existent smuggled path — the back-end had processed
it as a separate request:
# CL.TE timing probe — lab host
POST /tasks.php HTTP/1.1
Host: pay.acme-lab.test
Content-Type: application/x-www-form-urlencoded
Content-Length: 35
Transfer-Encoding: chunked
0
GET /nonexistent-path HTTP/1.1
X-Foo: x
# response (after 10.4 second delay):
HTTP/1.1 404 Not Found
X-Powered-By: PHP/7.x
Server: Apache
# 404 on the smuggled path — back-end processed it as an independent request
# CL.TE desync confirmed: front-end = Content-Length, back-end = chunked
What it enables on a payment endpoint
HTTP request smuggling on a static server is a lower-severity finding. On a payment task processor — a PHP script handling queued financial jobs, transaction status updates, and payment callbacks — three exploitation paths are relevant.
First, front-end security bypass: the reverse proxy implements WAF rules and access controls that the Apache backend trusts implicitly. A smuggled prefix targeting a backend-only endpoint can reach the application without proxy ACLs applying. Second, request capture: any backend endpoint that reflects request content can capture arriving headers from the next user's request — on a payment platform, that includes session tokens and payment reference identifiers. Third, cache poisoning: if the proxy caches by URL without Vary-keying on session identifiers, a smuggled request can poison payment status pages for other users.
No live exploitation was performed to avoid impact on real users or in-flight transactions. The confirmed desync and documented exploitation paths were sufficient for a Medium severity finding.
The test timeline
Server header identifies Apache backend. Server: Apache in responses. Reverse proxy in front confirmed by timing difference. CL.TE candidate architecture identified.
CL.TE timing probe launched against payment endpoint. Timing probe sent to /tasks.php. Response delayed 10.4 seconds — back-end waiting for additional chunked data never sent.
404 returned for smuggled path. Timing probe followed by 404 on the injected path. Back-end processed the smuggled suffix as a separate request — CL.TE desync confirmed.
Three exploitation paths scoped. Front-end bypass, request capture, and cache poisoning — all applicable given the payment platform context. No live exploitation performed.
Finding documented as Medium. Desync confirmed with timing evidence. Exploitation paths documented with PoC payloads for a lab-equivalent setup.
Closing the desync
- Normalize conflicting framing headers at the reverse proxy before forwarding. Strip
Content-Lengthfrom requests that carryTransfer-Encoding: chunked, and vice versa. Never forward both headers simultaneously to the backend. Both nginx and HAProxy support this configuration. - Use HTTP/2 end-to-end between client, proxy, and backend. HTTP/2 has a single, unambiguous framing mechanism. The CL.TE attack surface exists only in HTTP/1.1 connections. An end-to-end HTTP/2 pipeline eliminates this variant.
- Disable server banner disclosure. The
Server: Apacheheader identifies the backend stack to any external observer, enabling targeted CVE research. SetServerTokens ProdandServerSignature Offin Apache configuration. - Set the Secure flag on all session and payment cookies and enforce HSTS. A session cookie without the Secure flag is transmittable over HTTP. HSTS with a long max-age prevents protocol downgrade and closes the path that would allow session token interception in transit.
The takeaway
Request smuggling is not a code bug — neither server is wrong in isolation. The vulnerability exists in the combination. On a payment task processor, "confirmed desync" should trigger immediate triage: which backend endpoints can the smuggling reach that the proxy was blocking, and how quickly can the front-end normalization be configured?