hypercorn icon indicating copy to clipboard operation
hypercorn copied to clipboard

Misuse of the CONNECT Method

Open TUO-Wu opened this issue 10 months ago • 1 comments

Summary

Hypercorn does not support proxy functionality, while the CONNECT method is not properly rejected, enabling attackers to exploit it for HTTP request smuggling attacks.

Details

RFC 9110 says this:

The CONNECT method requests that the recipient establish a tunnel to the destination origin server identified by the request target and, if successful, thereafter restrict its behavior to blind forwarding of data, in both directions, until the tunnel is closed.

This means that the CONNECT method is intended solely for establishing a tunnel to the server identified by the target resource, and its usage is strictly confined to proxy environments. Hypercorn does not support proxy functionality and fails to reject CONNECT method requests. An attacker can craft a malicious HTTP request which causes HTTP Request Smuggling.

Example

CONNECT victim.com:443 HTTP/1.1\r\n
Host: victim.com\r\n
\r\n

Suggested action HTTP servers that do not support proxy functionality should strictly reject any CONNECT method requests and respond with an appropriate error (e.g., 405 Method Not Allowed or 400 Bad Request).

PoC

The example request is embedded in the previous section. Send the request to the server, e.g. by echo -ne into nc.

Impact

This bug enables attackers to use HTTP request smuggling techniques to bypass front-end proxy security checks, thereby delivering malicious requests to the backend server. This may result in unauthorized access to or leakage of sensitive resources, potentially leading to more severe security risks.

The version we tested was 84d06b8.

TUO-Wu avatar Mar 11 '25 01:03 TUO-Wu

Hello, my above explanation is not rigorous enough. Here is my new explanation.

RFC 9112 says this:

A server MUST reject a CONNECT request that targets an empty or invalid port number, typically by responding with a 400 (Bad Request) status code.

However, hypercorn does not reject such CONNECT request, and does not establish a proxy connection. It responses with 200 OK. For example:

CONNECT victim.com HTTP/1.1\r\n
Host: victim.com\r\n
\r\n
$ echo -ne "CONNECT victim.com HTTP/1.1\r\nHost: victim.com\r\n\r\n" | nc 172.18.0.10 80
HTTP/1.1 200 
content-length: 121
date: Thu, 20 Mar 2025 09:12:56 GMT
server: hypercorn-h11

Here are some logs:

 [2025-03-20 09:12:56 +0000] [10] [ERROR] Error in ASGI Framework
 Traceback (most recent call last):
   File "/usr/local/lib/python3.10/dist-packages/hypercorn/asyncio/task_group.py", line 27, in _handle
     await app(scope, receive, send, sync_spawn, call_soon)
   File "/usr/local/lib/python3.10/dist-packages/hypercorn/app_wrappers.py", line 34, in __call__
     await self.app(scope, receive, send)
   File "/app/server.py", line 32, in app
     await send({
   File "/usr/local/lib/python3.10/dist-packages/hypercorn/protocol/http_stream.py", line 192, in app_send
     await self.send(
   File "/usr/local/lib/python3.10/dist-packages/hypercorn/protocol/h11.py", line 142, in stream_send
     await self._send_h11_event(h11.Data(data=event.data))
   File "/usr/local/lib/python3.10/dist-packages/hypercorn/protocol/h11.py", line 249, in _send_h11_event
     data = self.connection.send(event)
   File "/usr/local/lib/python3.10/dist-packages/h11/_connection.py", line 512, in send
     data_list = self.send_with_data_passthrough(event)
   File "/usr/local/lib/python3.10/dist-packages/h11/_connection.py", line 537, in send_with_data_passthrough
     self._process_event(self.our_role, event)
   File "/usr/local/lib/python3.10/dist-packages/h11/_connection.py", line 272, in _process_event
     self._cstate.process_event(role, type(event), server_switch_event)
   File "/usr/local/lib/python3.10/dist-packages/h11/_state.py", line 293, in process_event
     self._fire_event_triggered_transitions(role, _event_type)
   File "/usr/local/lib/python3.10/dist-packages/h11/_state.py", line 311, in _fire_event_triggered_transitions
     raise LocalProtocolError(
 h11._util.LocalProtocolError: can't handle event type Data when role=SERVER and state=SWITCHED_PROTOCOL

TUO-Wu avatar Mar 20 '25 09:03 TUO-Wu