Request Smuggling with Api Keys
How Request Smuggling Manifests in API Keys
Request smuggling exploits inconsistencies between how a front‑end proxy (e.g., a load balancer, API gateway, or CDN) and the back‑end application parse HTTP requests. When the two entities disagree on where one request ends and the next begins, an attacker can inject a second request that is interpreted differently by each component. In the context of API keys, this can lead to the key being leaked, duplicated, or used to bypass authentication.
The classic smuggling techniques are CL.TE (Content‑Length vs. Transfer‑Encoding), TE.CL (Transfer‑Encoding vs. Content‑Length), and CL.CL (duplicate Content‑Length headers). An attacker crafts a request such that the front‑end uses one header to determine the body length while the back‑end uses the other. For example:
POST /v1/resource HTTP/1.1
Host: api.example.com
Content-Length: 13
Transfer-Encoding: chunked
0
GET /admin HTTP/1.1
Host: api.example.com
X-API-Key: legitimate_key
A front‑end that prioritizes Transfer‑Encoding will see a single request ending after the zero‑length chunk, while a back‑end that falls back to Content‑Length will treat the data after the chunk as a second request. The second request carries the API key in a header that the back‑end may log, echo in error messages, or use to authorize subsequent operations, inadvertently exposing the key.
Real‑world CVEs illustrate the impact: CVE-2020-10193 (Apache Tomcat) and CVE-2020-9484 (NGINX) both allowed request smuggling that could lead to header injection, including API‑key leakage. The OWASP API Security Top 10 2023 maps this weakness to API8: Security Misconfiguration, because the root cause is an improperly configured HTTP parsing layer.
API Keys‑Specific Detection
middleBrick’s Input Validation check actively probes for ambiguous header combinations that enable smuggling. When you submit a URL, the scanner sends a series of crafted requests that include conflicting Content‑Length and Transfer‑Encoding headers, then observes whether the backend responds differently to the front‑end’s interpretation.
If the API under test expects an API key in a custom header (e.g., X-API-Key), middleBrick checks whether that header can be duplicated or shifted into a smuggled request. The scanner looks for:
- Responses that contain the API key in error bodies, debug output, or reflected headers when only the smuggled request should have been processed.
- Changes in status code or response body that indicate the backend processed a second request with a different key.
- Presence of both Content‑Length and Transfer‑Encoding in the same request, which is a strong indicator of a smuggling‑prone configuration.
You can run the check from the CLI:
middlebrick scan https://api.example.com/v1/resource --output json
The resulting JSON includes a findings array where each entry has:
category: "Input Validation"severity: "high" (or "critical" if the key is reflected)description: details of the conflicting headers observed.remediation: guidance to normalize header parsing.
Because middleBrick works unauthenticated and black‑box, it detects the issue without needing any API key or credentials, making it suitable for scanning staging or production endpoints early in the CI/CD pipeline.
API Keys‑Specific Remediation
The primary defense is to eliminate the ambiguity that allows the front‑end and back‑end to disagree on request boundaries. This is done at the edge (proxy, load balancer, API gateway) and reinforced in the application layer.
1. **Normalize headers at the edge** – Ensure that the front‑end either rejects requests that contain both Content-Length and Transfer-Encoding or rewrites them to a single, unambiguous length. Most modern gateways have a setting like "reject ambiguous transfer encoding" or "strict HTTP parsing".
2. **Add defensive middleware in the application** – Even if the edge is misconfigured, a strict middleware can drop suspicious requests before they reach your API‑key validation logic.
Example for an Express.js service that expects an API key in the X-API-Key header:
const express = require('express');
const app = express();
// Middleware to reject ambiguous header combinations
app.use((req, res, next) => {
const hasCL = req.headers['content-length'] !== undefined;
const hasTE = req.headers['transfer-encoding'] !== undefined;
if (hasCL && hasTE) {
// 400 Bad Request – ambiguous length
return res.status(400).send('Invalid request: conflicting Content-Length and Transfer-Encoding');
}
next();
});
// Middleware to ensure the API key appears exactly once
app.use((req, res, next) => {
const key = req.headers['x-api-key'];
if (Array.isArray(key)) {
// Header appeared multiple times – treat as invalid
return res.status(400).send('Duplicate API‑Key header');
}
if (!key || typeof key !== 'string' || key.trim() === '') {
return res.status(401).send('Missing or invalid API‑Key');
}
// Optional: verify key against a store
// if (!validKeys.has(key)) return res.status(403).send('Invalid API‑Key');
next();
});
app.get('/v1/resource', (req, res) => {
res.json({ message: 'success' });
});
app.listen(3000);
3. **Use HTTP/1.0 or disable keep‑alive** – If you cannot guarantee edge safety, forcing the connection to close after each response eliminates the chance for a smuggled second request to reuse the same socket.
4. **Log and alert on header anomalies** – Capture requests with both Content-Length and Transfer-Encoding or duplicated custom headers, and trigger alerts via your SIEM or the middleBrick dashboard.
By applying these controls, you ensure that the API key is only ever read from a single, unambiguous header, preventing request smuggling from leaking or misusing the credential.