aiohttp icon indicating copy to clipboard operation
aiohttp copied to clipboard

Issues in Parsing HTTP Request "Host" Header

Open TUO-Wu opened this issue 9 months ago • 3 comments

Describe the bug

Aiohttp does not strictly validate the Host header in the HTTP request, rejects redundant Host headers but does not reject missing Host header.

To Reproduce

  1. Run aiohttp.
  2. Send the following requests.
POST / HTTP/1.1\r\n
Host: victim1.com\r\n
Host: victim2.com\r\n
\r\n

In this case, aiohttp will reject:

$ echo -ne "POST / HTTP/1.1\r\nHost: victim1.com\r\nHost: victim2.com\r\n\r\n" | nc 172.18.0.8 80
HTTP/1.0 400 Bad Request
Content-Type: text/plain; charset=utf-8
Content-Length: 30
Date: Wed, 19 Mar 2025 14:02:00 GMT
Server: Python/3.10 aiohttp/4.0.0a2.dev0

Duplicate 'Host' header found.

But if the Host header is missing:

POST / HTTP/1.1\r\n
Content-Length: 0\r\n
\r\n

Aiohttp accepted with 200 OK:

$ echo -ne "POST / HTTP/1.1\r\nContent-Length: 0\r\n\r\n" | nc 172.18.0.8 80
HTTP/1.1 200 OK
Content-Type: text/plain; charset=utf-8
Content-Length: 105
Date: Wed, 19 Mar 2025 14:08:55 GMT
Server: Python/3.10 aiohttp/4.0.0a2.dev0

{"headers":[["Q29udGVudC1MZW5ndGg=","MA=="]],"body":"","method":"UE9TVA==","uri":"Lw==","version":"MS4x"}

Expected behavior

Both cases should be rejected by the HTTP server with 400 (Bad Request), as RFC 9112 says:

A server MUST respond with a 400 (Bad Request) status code to any HTTP/1.1 request message that lacks a Host header field and to any request message that contains more than one Host header field line or a Host header field with an invalid field value.

Logs/tracebacks

/

Python Version

$ python --version
Python/3.10

aiohttp Version

$ python -m pip show aiohttp
aiohttp/4.0.0a2.dev0

multidict Version

$ python -m pip show multidict
/

propcache Version

$ python -m pip show propcache
/

yarl Version

$ python -m pip show yarl
/

OS

Ubuntu 11.4.0-1ubuntu1~22.04

Related component

Server

Additional context

I simply sent the requests above to the server directly.

Code of Conduct

  • [x] I agree to follow the aio-libs Code of Conduct

TUO-Wu avatar Mar 19 '25 15:03 TUO-Wu

Feel free to create a PR. We probably should reject it, but realistically, this will already have been handled by a reverse proxy or similar, otherwise it'd have no idea where to send the request.

Dreamsorcerer avatar Mar 19 '25 15:03 Dreamsorcerer

If this is changed to match the python parser, should that go

I guess the latter, as other HTTP parser usage might permit this (or at least disregard equivalent duplicates).

pajod avatar Mar 27 '25 16:03 pajod

Might be worth opening an issue with llhttp, they might be interested in it. They have strictness flags that could allow users to disable the check if needed.

Dreamsorcerer avatar Mar 27 '25 16:03 Dreamsorcerer