Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use sanitized URL as Location header in redirects #3613

Merged
merged 1 commit into from
Feb 17, 2019
Merged

Use sanitized URL as Location header in redirects #3613

merged 1 commit into from
Feb 17, 2019

Conversation

m-burst
Copy link
Contributor

@m-burst m-burst commented Feb 17, 2019

What do these changes do?

When performing HTTP redirects (e.g. using raise HTTPFound(location)), the URL in the Location header is now passed through URL constructor and thus sanitized. Most importantly, any CRLF in the location will be escaped, which will prevent HTTP Response Splitting attacks.

Are there changes in behavior for the user?

None unless the user's code is vulnerable.

Related issue number

None

Checklist

  • I think the code is well written
  • Unit tests for the changes exist
  • Documentation reflects the changes
  • If you provide code modification, please add yourself to CONTRIBUTORS.txt
    • The format is <Name> <Surname>.
    • Please keep alphabetical order, the file is sorted by names.
  • Add a new news fragment into the CHANGES folder
    • name it <issue_id>.<type> for example (588.bugfix)
    • if you don't have an issue_id change it to the pr id after creating the pr
    • ensure type is one of the following:
      • .feature: Signifying a new feature.
      • .bugfix: Signifying a bug fix.
      • .doc: Signifying a documentation improvement.
      • .removal: Signifying a deprecation or removal of public API.
      • .misc: A ticket has been closed, but it is not of interest to users.
    • Make sure to use full sentences with correct case and punctuation, for example: "Fix issue with non-ascii contents in doctest text files."

@m-burst
Copy link
Contributor Author

m-burst commented Feb 17, 2019

More details about the issue:

Given the following sample aiohttp app:

from aiohttp import web


def test_view(request):
    param = request.query.get('param')
    raise web.HTTPFound(f'http://example.com?param={param}')


def create_app():
    app = web.Application()
    app.router.add_get('/', test_view)
    return app


if __name__ == '__main__':
    web.run_app(create_app(), port=5000)

Sending a request with a urlencoded CRLF in the query parameter results in the following:

$ curl -v localhost:5000/?param=%0d%0aContent-Length:3%0d%0a%0d%0axxx
*   Trying 127.0.0.1...
* Connected to localhost (127.0.0.1) port 5000 (#0)
> GET /?param=%0d%0aContent-Length:3%0d%0a%0d%0axxx HTTP/1.1
> Host: localhost:5000
> User-Agent: curl/7.47.0
> Accept: */*
>
< HTTP/1.1 302 Found
< Content-Type: text/plain; charset=utf-8
< Location: http://example.com?param=
< Content-Length:3
<
* Excess found in a non pipelined read: excess = 95, size = 3, maxdownload = 3, bytecount = 0
* Connection #0 to host localhost left intact
xxx

Though the user's code itself needs to be vulnerable in order to exploit this bug, the case is pretty common and aiohttp should protect the users from this (as most other web frameworks do).

This PR fixes the issue by essentially setting the Location header to str(URL(location)) rather than plain location.

@codecov-io
Copy link

codecov-io commented Feb 17, 2019

Codecov Report

Merging #3613 into master will not change coverage.
The diff coverage is 100%.

Impacted file tree graph

@@          Coverage Diff           @@
##           master   #3613   +/-   ##
======================================
  Coverage    97.9%   97.9%           
======================================
  Files          43      43           
  Lines        8556    8556           
  Branches     1376    1376           
======================================
  Hits         8377    8377           
  Misses         74      74           
  Partials      105     105
Impacted Files Coverage Δ
aiohttp/web_exceptions.py 100% <100%> (ø) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 59ccf3a...9692487. Read the comment docs.

@webknjaz
Copy link
Member

@m-burst thanks! Would you mind sending a backport against the stable branch?

@webknjaz webknjaz merged commit cc4fffd into aio-libs:master Feb 17, 2019
@m-burst m-burst deleted the fix-redirect-url branch February 17, 2019 21:54
webknjaz pushed a commit that referenced this pull request Feb 17, 2019
@m-burst
Copy link
Contributor Author

m-burst commented Feb 17, 2019

@webknjaz Opened the backport PR in #3614.

@lock lock bot added the outdated label Feb 17, 2020
@lock lock bot locked as resolved and limited conversation to collaborators Feb 17, 2020
@psf-chronographer psf-chronographer bot added the bot:chronographer:provided There is a change note present in this PR label Feb 17, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
bot:chronographer:provided There is a change note present in this PR outdated
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants