From 4bc46001f542850c78a73ee39c391270fa5927dc Mon Sep 17 00:00:00 2001 From: Abhinav Singh Date: Mon, 12 Aug 2024 13:49:49 +0530 Subject: [PATCH] Use only `DEFAULT_SSL_CONTEXT_OPTIONS` to prevent `CRIME` attacks --- proxy/common/constants.py | 4 +++- proxy/http/client.py | 15 +++++++++++---- tests/http/test_client.py | 28 ++++++++++++++++++++++++++++ 3 files changed, 42 insertions(+), 5 deletions(-) create mode 100644 tests/http/test_client.py diff --git a/proxy/common/constants.py b/proxy/common/constants.py index 4e0da0be02..155c649ed5 100644 --- a/proxy/common/constants.py +++ b/proxy/common/constants.py @@ -161,7 +161,9 @@ def _env_threadless_compliant() -> bool: DEFAULT_WAIT_FOR_TASKS_TIMEOUT = 1 / 1000 DEFAULT_INACTIVE_CONN_CLEANUP_TIMEOUT = 1 # in seconds DEFAULT_SSL_CONTEXT_OPTIONS = ( - ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3 | ssl.OP_NO_TLSv1 | ssl.OP_NO_TLSv1_1 + ssl.OP_NO_COMPRESSION + if sys.version_info >= (3, 11) + else (ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3 | ssl.OP_NO_TLSv1 | ssl.OP_NO_TLSv1_1) ) DEFAULT_DEVTOOLS_DOC_URL = 'http://proxy' diff --git a/proxy/http/client.py b/proxy/http/client.py index 2537dc596f..60e420e68f 100644 --- a/proxy/http/client.py +++ b/proxy/http/client.py @@ -9,6 +9,7 @@ :license: BSD, see LICENSE for more details. """ import ssl +import logging from typing import Optional import certifi @@ -21,6 +22,9 @@ ) +logger = logging.getLogger(__name__) + + def client( host: bytes, port: int, @@ -30,21 +34,23 @@ def client( conn_close: bool = True, scheme: bytes = HTTPS_PROTO, timeout: float = DEFAULT_TIMEOUT, + content_type: bytes = b"application/x-www-form-urlencoded", ) -> Optional[HttpParser]: """Makes a request to remote registry endpoint""" request = build_http_request( method=method, url=path, headers={ - b'Host': host, - b'Content-Type': b'application/x-www-form-urlencoded', + b"Host": host, + b"Content-Type": content_type, }, body=body, conn_close=conn_close, ) try: conn = new_socket_connection((host.decode(), port)) - except ConnectionRefusedError: + except ConnectionRefusedError as exc: + logger.exception("Connection refused", exc_info=exc) return None sock: TcpOrTlsSocket = conn if scheme == HTTPS_PROTO: @@ -54,7 +60,8 @@ def client( ctx.verify_mode = ssl.CERT_REQUIRED ctx.load_verify_locations(cafile=certifi.where()) sock = ctx.wrap_socket(conn, server_hostname=host.decode()) - except Exception: + except Exception as exc: + logger.exception("Unable to wrap", exc_info=exc) conn.close() return None parser = HttpParser(httpParserTypes.RESPONSE_PARSER) diff --git a/tests/http/test_client.py b/tests/http/test_client.py new file mode 100644 index 0000000000..2aa2f8dd24 --- /dev/null +++ b/tests/http/test_client.py @@ -0,0 +1,28 @@ +# -*- coding: utf-8 -*- +""" + proxy.py + ~~~~~~~~ + ⚡⚡⚡ Fast, Lightweight, Pluggable, TLS interception capable proxy server focused on + Network monitoring, controls & Application development, testing, debugging. + + :copyright: (c) 2013-present by Abhinav Singh and contributors. + :license: BSD, see LICENSE for more details. +""" +import unittest + +from proxy.http.client import client + + +class TestClient(unittest.TestCase): + + def test_client(self) -> None: + response = client( + host=b"google.com", + port=443, + scheme=b"https", + path=b"/", + method=b"GET", + content_type=b"text/html", + ) + assert response is not None + self.assertEqual(response.code, b"301")