HTTP/2 Security Testing: Request Smuggling, Header Injection, and Protocol Attacks
HTTP/2 now carries the majority of web traffic. Most major applications, CDNs, and reverse proxies support it by default. But the same features that make HTTP/2 faster — binary framing, stream multiplexing, header compression — introduce a new class of vulnerabilities that don't exist in HTTP/1.1. The most severe is HTTP/2 request smuggling, which allows attackers to poison shared connection state between a front-end proxy and a back-end server, leading to request hijacking, cache poisoning, and authentication bypass.
This guide covers the practical mechanics of HTTP/2 security testing: how the protocol differs from HTTP/1.1, where the attack surface lives, and how to test it systematically.
HTTP/2 Protocol Fundamentals for Security Testers
Understanding the attack surface requires understanding what HTTP/2 changed from HTTP/1.1:
| Feature | HTTP/1.1 | HTTP/2 | Security Implication |
|---|---|---|---|
| Framing | Text-based | Binary frames | Harder to inspect manually; proxy translation bugs |
| Multiplexing | Sequential or pipelined | Multiple streams per connection | Stream state confusion; cross-stream data leakage |
| Header compression | None | HPACK compression | CRIME-like compression oracle attacks |
| Content-Length | Required for body size | Determined by framing | H2.CL desync when proxies downgrade to HTTP/1.1 |
| Transfer-Encoding | Chunked encoding valid | Forbidden in spec | H2.TE desync if back-end accepts it |
| Pseudo-headers | Not applicable | :method, :path, :authority, :scheme | Header injection via malformed pseudo-headers |
The most important architectural fact for security testing: most HTTP/2 deployments use a TLS-terminating front-end that speaks HTTP/2 to clients, then translates to HTTP/1.1 for back-end communication. This translation layer is where the most critical vulnerabilities live.
HTTP/2 Request Smuggling
HTTP/2 request smuggling exploits discrepancies between how a front-end proxy interprets the end of one HTTP/2 request and how a back-end server (receiving a translated HTTP/1.1 request) interprets the same boundary. James Kettle's research (PortSwigger, 2021) revealed that this class of attack is significantly more prevalent than HTTP/1.1 smuggling.
H2.CL (HTTP/2 with Content-Length)
The HTTP/2 spec forbids Content-Length from mismatching frame length, but many implementations accept it anyway. When the front-end translates to HTTP/1.1, it forwards the Content-Length header to the back-end. If the values differ, the back-end interprets the remaining bytes as the start of the next request.
Content-Length header smaller than the actual body. The front-end uses HTTP/2 framing (correct length); the back-end uses the forwarded Content-Length (short), treating the remaining body bytes as the beginning of the next request on the connection.
Testing with Burp Suite's HTTP/2 support:
POST / HTTP/2
Host: target.com
Content-Length: 0
GET /admin HTTP/1.1
Host: target.com
Foo: bar
If the back-end interprets the smuggled prefix, the next legitimate request on that connection will have the GET /admin prefix prepended to it — potentially giving the attacker's path or headers precedence.
H2.TE (HTTP/2 with Transfer-Encoding)
The HTTP/2 spec explicitly prohibits Transfer-Encoding headers, but some front-ends pass them through anyway when translating to HTTP/1.1. If the back-end processes chunked transfer encoding, a desync becomes possible:
POST / HTTP/2
Host: target.com
Transfer-Encoding: chunked
0
GET /admin HTTP/1.1
Host: internal.target.com
Test for H2.TE by injecting Transfer-Encoding: chunked directly in Burp's HTTP/2 editor. Check whether the front-end strips, passes, or rejects it.
CRLF Injection via HTTP/2 Header Values
HTTP/2 binary framing means header values can contain bytes that would be illegal in HTTP/1.1 — including CR (\r) and LF (\n). When a front-end translates these to HTTP/1.1 headers without sanitization, an attacker can inject additional HTTP/1.1 headers or terminate the header block early:
:method: GET
:path: /
:authority: target.com
foo: bar\r\nTransfer-Encoding: chunked
After translation to HTTP/1.1, this becomes:
GET / HTTP/1.1
Host: target.com
foo: bar
Transfer-Encoding: chunked
Burp Suite's HTTP/2 editor allows sending raw CRLF sequences in header values. Test systematically across all user-controllable headers.
HPACK Header Compression Attacks
HPACK is HTTP/2's header compression scheme. It maintains a dynamic table of previously seen header name-value pairs and references them by index in subsequent requests. This creates a compression oracle: if an attacker can inject controlled data alongside a secret value in the same compressed block, they can infer the secret by observing compressed size differences — the same principle as CRIME (against TLS compression) but applied at the HTTP layer.
Practical HPACK Oracle Conditions
For a HPACK oracle attack to work:
- The application must compress headers containing attacker-controlled data alongside secret data in the same HPACK context
- The attacker must be able to observe compressed payload sizes (e.g., via a side channel or direct network access)
- TLS must not be used, OR the attacker controls the TLS layer (e.g., testing from the network layer)
In practice, HPACK oracles are most relevant in server-to-server HTTP/2 communication over non-TLS transports, or in environments where an attacker has network-level access to observe packet sizes.
Server Push Security Issues
HTTP/2 server push allows a server to proactively send resources to the client before they are requested. Chrome and other major browsers deprecated and removed support for server push in 2022, but server-side implementations remain in many frameworks. Server push creates several potential security issues:
- Cache poisoning via pushed responses: If a proxy caches pushed resources, an attacker who can trigger a server push with a controlled URL may be able to poison the cache with malicious content.
- Information disclosure: A server misconfigured to push sensitive resources (internal API responses, auth tokens) to all clients on a connection can leak data.
- CSRF with push: In some configurations, pushed resources are processed without the browser's normal CORS/SameSite protections.
Test server push by inspecting HTTP/2 frames directly with h2spec, Wireshark with SSL key logging, or Burp's HTTP/2 tools. Look for PUSH_PROMISE frames and evaluate what's being pushed and to whom.
Stream Multiplexing and State Confusion
HTTP/2 multiplexes multiple logical streams over a single TCP connection. Each stream has independent state (headers, flow control windows, priority). Bugs in stream state management can create cross-stream data leakage:
Stream Reset Abuse (CVE-2023-44487 — HTTP/2 Rapid Reset)
The Rapid Reset vulnerability, disclosed in October 2023, exploited the ability to send a stream and immediately cancel it with RST_STREAM. By sending hundreds of thousands of rapid stream-open/cancel sequences, an attacker could exhaust server resources without completing requests — a highly efficient application-layer DoS that bypassed rate limiting based on completed requests.
Testing for Rapid Reset exposure:
- Check server version against known-patched releases (nginx ≥1.25.3, Apache ≥2.4.58, nghttp2 ≥1.57.0)
- Test whether the server enforces limits on
RST_STREAMframe rate - Review
http2_max_concurrent_streamsand similar configuration settings
Flow Control Window Abuse
HTTP/2 uses flow control windows to prevent a fast sender from overwhelming a slow receiver. Misconfigurations in window sizes can be exploited for resource exhaustion or to create timing side channels. Test by inspecting WINDOW_UPDATE frame behavior under load.
Protocol Downgrade and Negotiation Attacks
HTTP/2 is negotiated via ALPN (Application-Layer Protocol Negotiation) during TLS handshake, or via the Upgrade header for non-TLS connections (h2c). Forcing a downgrade to HTTP/1.1 can bypass HTTP/2-specific security controls:
Testing ALPN Negotiation
# Check what protocols the server supports
openssl s_client -connect target.com:443 -alpn h2 2>&1 | grep -E "(ALPN|Protocol)"
# Enumerate via nmap
nmap -sV --script ssl-enum-ciphers -p 443 target.com
# h2spec for HTTP/2 compliance testing
h2spec -h target.com -p 443 -t
h2c Upgrade Security
Cleartext HTTP/2 (h2c) using the HTTP Upgrade mechanism should not be enabled on production endpoints. It exposes all the HTTP/2 attack surface without TLS protection:
GET / HTTP/1.1
Host: target.com
Connection: Upgrade, HTTP2-Settings
Upgrade: h2c
HTTP2-Settings: AAMAAABkAAQAAP__
If the server responds with 101 Switching Protocols, h2c is enabled. This should be flagged unless there's a specific technical justification (e.g., internal load balancer communication).
Testing HTTP/2 with Burp Suite
Burp Suite Pro (from version 2021.9) includes first-class HTTP/2 support. Key capabilities:
- HTTP/2 editor: Send requests over HTTP/2 directly; inject raw bytes in header values
- HTTP Request Smuggler extension: Automated scanning for H2.CL, H2.TE, and H2.0 smuggling variants
- Inspector panel: View raw HTTP/2 frames; toggle between HTTP/1.1 and HTTP/2 views
- Turbo Intruder: Race condition and timing attacks over HTTP/2 multiplexed streams
# Manual H2.CL test in Burp HTTP/2 editor
# Add Content-Length header with value shorter than body
# Body: [prefix of smuggled request]
# HTTP Request Smuggler automated scan
# Extensions > HTTP Request Smuggler > Active Scan
# Covers: CL.TE, TE.CL, H2.CL, H2.TE, H2.0
HTTP/3 (QUIC) Security Considerations
HTTP/3 replaces TCP with QUIC (UDP-based). The attack surface shifts:
| Attack Class | HTTP/2 (TCP) | HTTP/3 (QUIC) |
|---|---|---|
| Request smuggling | H2.CL, H2.TE via proxy translation | Different framing reduces classic vectors; new variants emerging |
| Connection-level DoS | TCP reset, SYN flood | UDP amplification, QUIC Initial packet flooding |
| Protocol confusion | HTTP/1.1 downgrade | Alt-Svc header spoofing to redirect to attacker-controlled h3 endpoint |
| Connection migration abuse | Not applicable | QUIC connection migration can be abused to hijack sessions |
HTTP/3 tooling is less mature. Use curl --http3, quiche (Cloudflare), or ngtcp2 for protocol-level testing.
HTTP/2 Security Testing Checklist
- Test for H2.CL request smuggling via
Content-Lengthheader injection - Test for H2.TE request smuggling via forbidden
Transfer-Encodingheader - Test CRLF injection in HTTP/2 header values (CR/LF as literal bytes in name and value fields)
- Check for server push and evaluate cache poisoning potential
- Verify Rapid Reset (CVE-2023-44487) patches are applied
- Test h2c (cleartext HTTP/2) — should not be exposed on production
- Verify ALPN negotiation enforces expected protocol versions
- Test HTTP/2 to HTTP/1.1 translation layer for header injection
- Check pseudo-header injection (
:path,:authority,:methodwith injected CRLF) - Review server stream concurrency limits (
SETTINGS_MAX_CONCURRENT_STREAMS) - Validate flow control window configuration
- Run
h2specfor RFC 7540 compliance testing
Ironimo runs Kali Linux-grade security scanning — including protocol-level HTTP/2 vulnerability detection — on demand. No manual proxy setup, no custom scripts.
Start free scan