def test_null_cipher_suites(self):
        # Given a server to scan that supports NULL cipher suites
        server_location = ServerNetworkLocation("null.badssl.com", 443)
        server_info = check_connectivity_to_server_and_return_info(
            server_location)

        # When scanning for cipher suites, it succeeds
        result: CipherSuitesScanResult = Tlsv12ScanImplementation.scan_server(
            server_info)

        # And the NULL/Anon cipher suites were detected
        expected_ciphers = {
            "TLS_ECDH_anon_WITH_AES_256_CBC_SHA",
            "TLS_DH_anon_WITH_AES_256_CBC_SHA256",
            "TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA",
            "TLS_DH_anon_WITH_AES_256_GCM_SHA384",
            "TLS_DH_anon_WITH_AES_256_CBC_SHA",
            "TLS_ECDH_anon_WITH_AES_128_CBC_SHA",
            "TLS_DH_anon_WITH_AES_128_CBC_SHA256",
            "TLS_DH_anon_WITH_AES_128_CBC_SHA",
            "TLS_DH_anon_WITH_AES_128_GCM_SHA256",
            "TLS_DH_anon_WITH_SEED_CBC_SHA",
            "TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA",
            "TLS_ECDHE_RSA_WITH_NULL_SHA",
            "TLS_ECDH_anon_WITH_NULL_SHA",
            "TLS_RSA_WITH_NULL_SHA256",
            "TLS_RSA_WITH_NULL_SHA",
        }
        assert expected_ciphers == {
            accepted_cipher.cipher_suite.name
            for accepted_cipher in result.accepted_cipher_suites
        }
Beispiel #2
0
    def test_works_when_client_auth_succeeded(self):
        # Given a server that requires client authentication
        with LegacyOpenSslServer(
                client_auth_config=ClientAuthConfigEnum.REQUIRED) as server:
            server_location = ServerNetworkLocation(
                hostname=server.hostname,
                ip_address=server.ip_address,
                port=server.port)
            # And sslyze provides a client certificate
            network_config = ServerNetworkConfiguration(
                tls_server_name_indication=server.hostname,
                tls_client_auth_credentials=ClientAuthenticationCredentials(
                    certificate_chain_path=server.get_client_certificate_path(
                    ),
                    key_path=server.get_client_key_path()),
            )
            server_info = check_connectivity_to_server_and_return_info(
                server_location, network_config)

            # When scanning for HTTP headers, it succeeds
            result: HttpHeadersScanResult = HttpHeadersImplementation.scan_server(
                server_info)

            assert not result.strict_transport_security_header
            assert not result.expect_ct_header
    def test_works_when_client_auth_succeeded(self):
        # Given a server that requires client authentication
        with ModernOpenSslServer(
                client_auth_config=ClientAuthConfigEnum.REQUIRED) as server:
            server_location = ServerNetworkLocation(
                hostname=server.hostname,
                ip_address=server.ip_address,
                port=server.port)
            # And sslyze provides a client certificate
            network_config = ServerNetworkConfiguration(
                tls_server_name_indication=server.hostname,
                tls_client_auth_credentials=ClientAuthenticationCredentials(
                    certificate_chain_path=server.get_client_certificate_path(
                    ),
                    key_path=server.get_client_key_path()),
            )
            server_info = check_connectivity_to_server_and_return_info(
                server_location, network_config)

            # When testing for resumption, it succeeds
            result: SessionResumptionSupportScanResult = SessionResumptionSupportImplementation.scan_server(
                server_info)

        assert result.session_id_successful_resumptions_count
        assert result.session_id_resumption_result == TlsResumptionSupportEnum.FULLY_SUPPORTED
    def test_via_http_proxy(self):
        # Given an HTTP proxy
        proxy_port = 8123
        proxy_server = ThreadingHTTPServer(("", proxy_port), ProxyHandler)
        proxy_server_thread = threading.Thread(
            target=proxy_server.serve_forever)
        proxy_server_thread.start()

        # And a server location
        server_location = ServerNetworkLocation(
            hostname="www.google.com",
            port=443,
            # Configured with this proxy
            http_proxy_settings=HttpProxySettings("localhost", proxy_port),
        )

        # When testing connectivity
        try:
            tls_probing_result = check_connectivity_to_server(
                server_location=server_location,
                network_configuration=ServerNetworkConfiguration.
                default_for_server_location(server_location),
            )
        finally:
            proxy_server.shutdown()

        # It succeeds
        assert tls_probing_result.cipher_suite_supported
        assert tls_probing_result.highest_tls_version_supported
        assert tls_probing_result.client_auth_requirement

        # And the result can be converted to JSON
        tls_probing_result_as_json = _ServerTlsProbingResultAsJson.from_orm(
            tls_probing_result)
        assert tls_probing_result_as_json.json()
    def test_tlsv1_2_enabled(self):
        # Given a server to scan that supports TLS 1.2
        server_location = ServerNetworkLocation("www.google.com", 443)
        server_info = check_connectivity_to_server_and_return_info(
            server_location)

        # When scanning for cipher suites, it succeeds
        result: CipherSuitesScanResult = Tlsv12ScanImplementation.scan_server(
            server_info)

        # And the result confirms that TLS 1.2 is supported
        expected_ciphers = {
            "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
            "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA",
            "TLS_RSA_WITH_AES_256_GCM_SHA384",
            "TLS_RSA_WITH_AES_256_CBC_SHA",
            "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
            "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
            "TLS_RSA_WITH_AES_128_GCM_SHA256",
            "TLS_RSA_WITH_AES_128_CBC_SHA",
            "TLS_RSA_WITH_3DES_EDE_CBC_SHA",
            "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256",
            "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256",
        }
        assert expected_ciphers == {
            accepted_cipher.cipher_suite.name
            for accepted_cipher in result.accepted_cipher_suites
        }
Beispiel #6
0
    def test_works_when_client_auth_succeeded(self):
        # Given a server that does NOT support SCSV and that requires client authentication
        with LegacyOpenSslServer(
                client_auth_config=ClientAuthConfigEnum.REQUIRED) as server:
            server_location = ServerNetworkLocation(
                hostname=server.hostname,
                ip_address=server.ip_address,
                port=server.port)
            # And sslyze provides a client certificate
            network_config = ServerNetworkConfiguration(
                tls_server_name_indication=server.hostname,
                tls_client_auth_credentials=ClientAuthenticationCredentials(
                    certificate_chain_path=server.get_client_certificate_path(
                    ),
                    key_path=server.get_client_key_path()),
            )
            server_info = check_connectivity_to_server_and_return_info(
                server_location, network_config)

            # When testing for SCSV, it succeeds
            result: FallbackScsvScanResult = FallbackScsvImplementation.scan_server(
                server_info)

        # And the server is reported as NOT supporting SCSV
        assert not result.supports_fallback_scsv
Beispiel #7
0
    def test_http_error(self):
        # Given a server to scan
        with ModernOpenSslServer(
                # And the server will trigger an error when receiving an HTTP request
                should_reply_to_http_requests=False) as server:
            server_location = ServerNetworkLocation(
                hostname=server.hostname,
                ip_address=server.ip_address,
                port=server.port)
            server_info = check_connectivity_to_server_and_return_info(
                server_location)

            # When scanning for HTTP headers, it succeeds
            result: HttpHeadersScanResult = HttpHeadersImplementation.scan_server(
                server_info)

        # And the result mention the error returned by the server when sending an HTTP request
        assert result.http_error_trace
        assert result.http_request_sent

        # And the other result fields are not set
        assert not result.http_path_redirected_to
        assert not result.expect_ct_header

        # And a CLI output can be generated
        assert HttpHeadersImplementation.cli_connector_cls.result_to_console_output(
            result)

        # And the result can be converted to JSON
        result_as_json = HttpHeadersScanResultAsJson.from_orm(result).json()
        assert result_as_json
    def test_works_when_client_auth_succeeded(self):
        # Given a server that is vulnerable and that requires client authentication
        with LegacyOpenSslServer(
                client_auth_config=ClientAuthConfigEnum.REQUIRED) as server:
            server_location = ServerNetworkLocation(
                hostname=server.hostname,
                ip_address=server.ip_address,
                port=server.port)
            # And sslyze provides a client certificate
            network_config = ServerNetworkConfiguration(
                tls_server_name_indication=server.hostname,
                tls_client_auth_credentials=ClientAuthenticationCredentials(
                    certificate_chain_path=server.get_client_certificate_path(
                    ),
                    key_path=server.get_client_key_path()),
            )
            server_info = check_connectivity_to_server_and_return_info(
                server_location, network_config)

            # When testing for insecure reneg, it succeeds
            result: SessionRenegotiationScanResult = SessionRenegotiationImplementation.scan_server(
                server_info)

            # And the results are correct
            assert result.supports_secure_renegotiation
            assert result.is_vulnerable_to_client_renegotiation_dos
    def test_vulnerable_and_server_has_sni_bug(self):
        # Test for https://github.com/nabla-c0d3/sslyze/issues/202
        # Given a server that is vulnerable to Heartbleed and that requires the right SNI to be sent
        server_name_indication = "server.com"
        with LegacyOpenSslServer(
                require_server_name_indication_value=server_name_indication
        ) as server:
            server_location = ServerNetworkLocation(
                hostname=server_name_indication,
                ip_address=server.ip_address,
                port=server.port)
            server_info = check_connectivity_to_server_and_return_info(
                server_location)

            # But the server is buggy and returns a TLS alert when SNI is sent during the Hearbtleed check
            # We replicate this behavior by having SSLyze send a wrong value for SNI, instead of complicated server code
            # Use __setattr__ to bypass the dataclass' frozen=True setting
            object.__setattr__(server_info.network_configuration,
                               "tls_server_name_indication", "wrongvalue.com")

            # When testing for Heartbleed, it succeeds
            result = HeartbleedImplementation.scan_server(server_info)

        # And the server is reported as vulnerable even though it has the SNI bug
        assert result.is_vulnerable_to_heartbleed
Beispiel #10
0
 def create() -> ServerNetworkLocation:
     return ServerNetworkLocation(
         hostname="ûnicôdé." + fake.hostname(),
         port=123,
         http_proxy_settings=HttpProxySettings(hostname="prôxy." +
                                               fake.hostname(),
                                               port=456),
     )
Beispiel #11
0
    def test(self):
        # Given a completed scan for a CERTIFICATE_INFO scan command
        server_location = ServerNetworkLocation("www.facebook.com", 443)
        server_info = check_connectivity_to_server_and_return_info(
            server_location)
        plugin_result = CertificateInfoImplementation.scan_server(server_info)

        # When generating the CLI output for this result, it succeeds
        result_as_txt = CertificateInfoImplementation.cli_connector_cls.result_to_console_output(
            plugin_result)
        assert result_as_txt
Beispiel #12
0
    def test(self):
        # Given a completed scan for a cipher suites scan command
        server_location = ServerNetworkLocation("www.google.com", 443)
        server_info = check_connectivity_to_server_and_return_info(
            server_location)
        plugin_result = Tlsv12ScanImplementation.scan_server(server_info)

        # When generating the CLI output for this result, it succeeds
        result_as_txt = Tlsv12ScanImplementation.cli_connector_cls.result_to_console_output(
            plugin_result)
        assert result_as_txt
Beispiel #13
0
    def test_via_direct_connection_but_server_rejected_connection(self):
        # Given a server location for a server that's offline
        server_location = ServerNetworkLocation(hostname="localhost",
                                                port=1234)

        # When testing connectivity, it fails with the right error
        with pytest.raises(ServerRejectedConnection):
            check_connectivity_to_server(
                server_location=server_location,
                network_configuration=ServerNetworkConfiguration.
                default_for_server_location(server_location),
            )
    def test_follows_client_cipher_suite_preference(self):
        # Given a server to scan that follows client cipher suite preference
        server_location = ServerNetworkLocation("www.hotmail.com", 443)
        server_info = check_connectivity_to_server_and_return_info(
            server_location)

        # When scanning for cipher suites, it succeeds
        result: CipherSuitesScanResult = Tlsv12ScanImplementation.scan_server(
            server_info)

        # And the server is detected as following the client's preference
        assert result.cipher_suite_preferred_by_server
Beispiel #15
0
    def test_via_direct_connection_but_server_tls_config_not_supported(self):
        # Given a server location for a server that only supports DH settings that SSLyze can't use
        server_location = ServerNetworkLocation(hostname="dh480.badssl.com",
                                                port=443)

        # When testing connectivity, it fails with the right error
        with pytest.raises(ServerTlsConfigurationNotSupported):
            check_connectivity_to_server(
                server_location=server_location,
                network_configuration=ServerNetworkConfiguration.
                default_for_server_location(server_location),
            )
Beispiel #16
0
    def test_robot_attack_good(self):
        # Validate the bug fix for https://github.com/nabla-c0d3/sslyze/issues/282
        # Given a server to scan that is not vulnerable to ROBOT
        server_location = ServerNetworkLocation("guide.duo.com", 443)
        server_info = check_connectivity_to_server_and_return_info(
            server_location)

        result: RobotScanResult = RobotImplementation.scan_server(server_info)
        assert result.robot_result == RobotScanResultEnum.NOT_VULNERABLE_NO_ORACLE

        # And a CLI output can be generated
        assert RobotImplementation.cli_connector_cls.result_to_console_output(
            result)
    def test_sslv3_disabled(self):
        # Given a server to scan that does not support SSL 3.0
        server_location = ServerNetworkLocation("www.google.com", 443)
        server_info = check_connectivity_to_server_and_return_info(
            server_location)

        # When scanning for cipher suites, it succeeds
        result: CipherSuitesScanResult = Sslv30ScanImplementation.scan_server(
            server_info)

        # And the result confirms that SSL 3.0 is not supported
        assert not result.accepted_cipher_suites
        assert result.rejected_cipher_suites
    def test_tlsv1_0_disabled(self):
        # Given a server to scan that does NOT support TLS 1.0
        server_location = ServerNetworkLocation("success.trendmicro.com", 443)
        server_info = check_connectivity_to_server_and_return_info(
            server_location)

        # When scanning for cipher suites, it succeeds
        result: CipherSuitesScanResult = Tlsv10ScanImplementation.scan_server(
            server_info)

        # And the result confirms that TLS 1.0 is not supported
        assert not result.accepted_cipher_suites
        assert result.rejected_cipher_suites
    def test_not_vulnerable_and_server_has_cloudfront_bug(self):
        # Test for https://github.com/nabla-c0d3/sslyze/issues/437
        # Given a server that is NOT vulnerable to CCS injection and that is hosted on Cloudfront with the SNI bug
        server_location = ServerNetworkLocation(hostname="amazon.com",
                                                port=443,
                                                ip_address="13.35.126.17")
        server_info = check_connectivity_to_server_and_return_info(
            server_location)

        # When testing for CCS injection, it succeeds
        result = HeartbleedImplementation.scan_server(server_info)

        # And the server is reported as not vulnerable
        assert not result.is_vulnerable_to_heartbleed
    def test_smtp(self):
        # Given an SMTP server to scan
        hostname = "smtp.gmail.com"
        server_location = ServerNetworkLocation(hostname, 587)
        network_configuration = ServerNetworkConfiguration(
            tls_server_name_indication=hostname,
            tls_opportunistic_encryption=ProtocolWithOpportunisticTlsEnum.SMTP)
        server_info = check_connectivity_to_server_and_return_info(
            server_location, network_configuration)

        # When scanning for cipher suites, it succeeds
        result: CipherSuitesScanResult = Tlsv12ScanImplementation.scan_server(
            server_info)
        assert result.accepted_cipher_suites
Beispiel #21
0
    def test_via_direct_connection_but_server_timed_out(self):
        # Given a server location for a server that's offline
        server_location = ServerNetworkLocation(
            hostname="notarealdomain.not.real.notreal.not",
            port=1234,
            ip_address="123.123.123.123")

        # When testing connectivity, it fails with the right error
        with pytest.raises(ConnectionToServerTimedOut):
            check_connectivity_to_server(
                server_location=server_location,
                network_configuration=ServerNetworkConfiguration.
                default_for_server_location(server_location),
            )
Beispiel #22
0
    def test_fails_when_client_auth_failed(self):
        # Given a server that does NOT support SCSV and that requires client authentication
        with LegacyOpenSslServer(
                client_auth_config=ClientAuthConfigEnum.REQUIRED) as server:
            # And sslyze does NOT provide a client certificate
            server_location = ServerNetworkLocation(
                hostname=server.hostname,
                ip_address=server.ip_address,
                port=server.port)
            server_info = check_connectivity_to_server_and_return_info(
                server_location)

            # When testing for SCSV, it fails as a client cert was not supplied
            with pytest.raises(ClientCertificateRequested):
                FallbackScsvImplementation.scan_server(server_info)
    def test_not_vulnerable(self):
        # Given a server that is NOT vulnerable to Heartbleed
        server_location = ServerNetworkLocation("www.google.com", 443)
        server_info = check_connectivity_to_server_and_return_info(
            server_location)

        # When testing for Heartbleed, it succeeds
        result = HeartbleedImplementation.scan_server(server_info)

        # And the server is reported as not vulnerable
        assert not result.is_vulnerable_to_heartbleed

        # And a CLI output can be generated
        assert HeartbleedImplementation.cli_connector_cls.result_to_console_output(
            result)
Beispiel #24
0
    def test_fails_when_client_auth_failed(self):
        # Given a server that requires client authentication
        with LegacyOpenSslServer(
                client_auth_config=ClientAuthConfigEnum.REQUIRED) as server:
            # And sslyze does NOT provide a client certificate
            server_location = ServerNetworkLocation(
                hostname=server.hostname,
                ip_address=server.ip_address,
                port=server.port)
            server_info = check_connectivity_to_server_and_return_info(
                server_location)

            # When scanning for HTTP headers, it fails
            with pytest.raises(ClientCertificateRequested):
                HttpHeadersImplementation.scan_server(server_info)
    def test_via_http_proxy_but_proxy_timed_out(self):
        # Given a server location
        server_location = ServerNetworkLocation(
            hostname="www.google.com",
            port=443,
            # Configured with a proxy that will time out
            http_proxy_settings=HttpProxySettings("1.2.3.4", 80),
        )

        # When testing connectivity, it fails with the right error
        with pytest.raises(ConnectionToHttpProxyTimedOut):
            check_connectivity_to_server(
                server_location=server_location,
                network_configuration=ServerNetworkConfiguration.
                default_for_server_location(server_location),
            )
Beispiel #26
0
    def test_fallback_good(self):
        # Given a server that supports SCSV
        server_location = ServerNetworkLocation("www.google.com", 443)
        server_info = check_connectivity_to_server_and_return_info(
            server_location)

        # When testing for SCSV, it succeeds
        result: FallbackScsvScanResult = FallbackScsvImplementation.scan_server(
            server_info)

        # And the server is reported as supporting SCSV
        assert result.supports_fallback_scsv

        # And a CLI output can be generated
        assert FallbackScsvImplementation.cli_connector_cls.result_to_console_output(
            result)
Beispiel #27
0
    def test_fallback_bad(self):
        # Given a server that does NOT support SCSV
        with LegacyOpenSslServer() as server:
            server_location = ServerNetworkLocation(
                hostname=server.hostname,
                ip_address=server.ip_address,
                port=server.port)
            server_info = check_connectivity_to_server_and_return_info(
                server_location)

            # When testing for SCSV, it succeeds
            result: FallbackScsvScanResult = FallbackScsvImplementation.scan_server(
                server_info)

        # And the server is reported as NOT supporting SCSV
        assert not result.supports_fallback_scsv
    def test_via_http_proxy_but_proxy_rejected_http_connect(self):
        # Given a server location
        server_location = ServerNetworkLocation(
            hostname="www.google.com",
            port=443,
            # Configured with a proxy that is going to reject the HTTP CONNECT request
            http_proxy_settings=HttpProxySettings("www.hotmail.com", 443),
        )

        # When testing connectivity, it fails with the right error
        with pytest.raises(HttpProxyRejectedConnection):
            check_connectivity_to_server(
                server_location=server_location,
                network_configuration=ServerNetworkConfiguration.
                default_for_server_location(server_location),
            )
    def test_via_http_proxy_but_proxy_rejected_connection(self):
        # Given a server location
        server_location = ServerNetworkLocation(
            hostname="www.google.com",
            port=443,
            # Configured with a proxy that's offline
            http_proxy_settings=HttpProxySettings("localhost", 1234),
        )

        # When testing connectivity, it fails with the right error
        with pytest.raises(HttpProxyRejectedConnection):
            check_connectivity_to_server(
                server_location=server_location,
                network_configuration=ServerNetworkConfiguration.
                default_for_server_location(server_location),
            )
Beispiel #30
0
    def test_early_data_disabled(self):
        # Given a server to scan that does NOT support early data because it it is disabled
        with ModernOpenSslServer(max_early_data=None) as server:
            server_location = ServerNetworkLocation(
                hostname=server.hostname,
                ip_address=server.ip_address,
                port=server.port)
            server_info = check_connectivity_to_server_and_return_info(
                server_location)

            # When testing for early data support, it succeeds
            result: EarlyDataScanResult = EarlyDataImplementation.scan_server(
                server_info)

            # And the right result is returned
        assert not result.supports_early_data