Skip to content

Host Header Attack: url_for() should not trust unvalidated Host header #1855

@Kludex

Description

@Kludex

Discussed in #1854

Originally posted by lieryan September 9, 2022
This is somewhat related to ticket #843.

Currently, url_for() can be used to generate an absolute URL for a route and it uses Host header to do so. There is currently no validation in the value of the host header, which can be abused for some quite funky stuffs.

This behavior is a security issue because it opens up the application to Host Header Attack.

You can fix this issue in your application by adding a TrustedHostMiddleware and setting allowed_hosts=["yourdomain.com"], but I think most people aren't going to know that they must use TrustedHostMiddleware if they want to use url_for() securely.

To reproduce:

from starlette.applications import Starlette
from starlette.responses import RedirectResponse, JSONResponse
from starlette.routing import Route


async def main(request):
    return JSONResponse({

        "url_for": request.url_for("main"),
        "url_path_for": app.url_path_for("main"),
    })


async def redirect(request):
    return RedirectResponse(request.url_for("main"))


routes = [
    Route("/", endpoint=main),
    Route("/redirect", endpoint=redirect),
]

app = Starlette(routes=routes)


if __name__ == '__main__':
    import uvicorn
    uvicorn.run(app)

And on the shell do (note the funky looking Host header):

$ curl -L -v -H 'Host: www.google.com/search' localhost:8000/redirect
< HTTP/1.1 307 Temporary Redirect
< date: Fri, 09 Sep 2022 13:51:10 GMT
< server: uvicorn
< content-length: 0
< location: http://www.google.com/search/


$ $ curl -L -H 'Host: www.google.com/search' localhost:8000/ | jq
{
  "url_for": "http://www.google.com/search/",
  "url_path_for": "/"
}

Important

  • We're using Polar.sh so you can upvote and help fund this issue.
  • We receive the funding once the issue is completed & confirmed by you.
  • Thank you in advance for helping prioritize & fund our backlog.
Fund with Polar

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions