diff --git a/mitmproxy/proxy2/layers/tls.py b/mitmproxy/proxy2/layers/tls.py index 41d680fc5..42974b846 100644 --- a/mitmproxy/proxy2/layers/tls.py +++ b/mitmproxy/proxy2/layers/tls.py @@ -85,7 +85,10 @@ def parse_client_hello(data: bytes) -> Optional[net_tls.ClientHello]: # Check if ClientHello is complete client_hello = get_client_hello(data) if client_hello: - return net_tls.ClientHello(client_hello[4:]) + try: + return net_tls.ClientHello(client_hello[4:]) + except EOFError as e: + raise ValueError("Invalid ClientHello") from e return None diff --git a/test/mitmproxy/proxy2/conftest.py b/test/mitmproxy/proxy2/conftest.py index 17b91494a..055206f6f 100644 --- a/test/mitmproxy/proxy2/conftest.py +++ b/test/mitmproxy/proxy2/conftest.py @@ -1,4 +1,7 @@ +import os + import pytest +from hypothesis import settings from mitmproxy import options from mitmproxy.addons.core import Core @@ -21,3 +24,8 @@ def tctx() -> context.Context: ), opts ) + + +settings.register_profile("fast", max_examples=10) +settings.register_profile("deep", max_examples=100_000, deadline=None) +settings.load_profile(os.getenv("HYPOTHESIS_PROFILE", "fast")) \ No newline at end of file diff --git a/test/mitmproxy/proxy2/layers/http/test_http_fuzz.py b/test/mitmproxy/proxy2/layers/http/test_http_fuzz.py index 0d7929524..d018f038f 100644 --- a/test/mitmproxy/proxy2/layers/http/test_http_fuzz.py +++ b/test/mitmproxy/proxy2/layers/http/test_http_fuzz.py @@ -1,9 +1,8 @@ -import os from typing import Tuple, Dict, Any import pytest from h2.settings import SettingCodes -from hypothesis import example, given, settings +from hypothesis import example, given from hypothesis.strategies import binary, booleans, composite, dictionaries, integers, lists, sampled_from, sets, text, \ data @@ -21,10 +20,6 @@ from test.mitmproxy.proxy2.layers.http.test_http2 import make_h2, example_respon start_h2_client from test.mitmproxy.proxy2.tutils import Placeholder, Playbook, reply, _TracebackInPlaybook, _eq -settings.register_profile("fast", max_examples=10) -settings.register_profile("deep", max_examples=100_000, deadline=None) -settings.load_profile(os.getenv("HYPOTHESIS_PROFILE", "fast")) - opts = options.Options() Proxyserver().load(opts) diff --git a/test/mitmproxy/proxy2/layers/test_tls_fuzz.py b/test/mitmproxy/proxy2/layers/test_tls_fuzz.py new file mode 100644 index 000000000..f7903f6c9 --- /dev/null +++ b/test/mitmproxy/proxy2/layers/test_tls_fuzz.py @@ -0,0 +1,26 @@ +from hypothesis import given, example +from hypothesis.strategies import binary, integers + +from mitmproxy.net.tls import ClientHello +from mitmproxy.proxy2.layers.tls import parse_client_hello + +client_hello_with_extensions = bytes.fromhex( + "16030300bb" # record layer + "010000b7" # handshake layer + "03033b70638d2523e1cba15f8364868295305e9c52aceabda4b5147210abc783e6e1000022c02bc02fc02cc030" + "cca9cca8cc14cc13c009c013c00ac014009c009d002f0035000a0100006cff0100010000000010000e00000b65" + "78616d706c652e636f6d0017000000230000000d00120010060106030501050304010403020102030005000501" + "00000000001200000010000e000c02683208687474702f312e3175500000000b00020100000a00080006001d00" + "170018" +) + + +@given(i=integers(0, len(client_hello_with_extensions)), data=binary()) +@example(i=183, data=b'\x00\x00\x00\x00\x00\x00\x00\x00\x00') +def test_fuzz_h2_request_chunks(i, data): + try: + ch = parse_client_hello(client_hello_with_extensions[:i] + data) + except ValueError: + pass + else: + assert ch is None or isinstance(ch, ClientHello)