Пример #1
0
    def test_invalid_chain(self):
        server_test = ServerConnectivityTester(hostname='self-signed.badssl.com')
        server_info = server_test.perform()

        plugin = CertificateInfoPlugin()
        plugin_result = plugin.process_task(server_info, CertificateInfoScanCommand())

        self.assertIsNone(plugin_result.ocsp_response)
        self.assertEqual(len(plugin_result.certificate_chain), 1)

        self.assertGreaterEqual(len(plugin_result.path_validation_result_list), 5)
        for path_validation_result in plugin_result.path_validation_result_list:
            self.assertFalse(path_validation_result.is_certificate_trusted)

        self.assertEqual(plugin_result.certificate_included_scts_count, 0)

        self.assertEqual(len(plugin_result.path_validation_error_list), 0)
        self.assertEqual(plugin_result.certificate_matches_hostname, True)
        self.assertTrue(plugin_result.is_certificate_chain_order_valid)
        self.assertIsNone(plugin_result.has_anchor_in_certificate_chain)
        self.assertIsNone(plugin_result.has_sha1_in_certificate_chain)
        self.assertFalse(plugin_result.verified_certificate_chain)

        self.assertTrue(plugin_result.as_text())
        self.assertTrue(plugin_result.as_xml())

        # Ensure the results are pickable so the ConcurrentScanner can receive them via a Queue
        self.assertTrue(pickle.dumps(plugin_result))
Пример #2
0
    def test_tlsv1_2_enabled(self):
        server_test = ServerConnectivityTester(hostname='www.google.com')
        server_info = server_test.perform()

        plugin = OpenSslCipherSuitesPlugin()
        # Also do full HTTP connections
        plugin_result = plugin.process_task(server_info, Tlsv12ScanCommand(http_get=True))

        self.assertTrue(plugin_result.preferred_cipher)
        self.assertTrue(plugin_result.accepted_cipher_list)
        accepted_cipher_name_list = [cipher.name for cipher in plugin_result.accepted_cipher_list]

        self.assertEqual({'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'},
                         set(accepted_cipher_name_list))

        self.assertTrue(plugin_result.rejected_cipher_list)
        self.assertFalse(plugin_result.errored_cipher_list)

        self.assertTrue(plugin_result.as_text())
        self.assertTrue(plugin_result.as_xml())

        # Ensure the results are pickable so the ConcurrentScanner can receive them via a Queue
        self.assertTrue(pickle.dumps(plugin_result))
Пример #3
0
def init_sslyze(hostname, port, starttls_smtp, options, sync=False):
    global network_timeout, CA_FILE

    network_timeout = int(options.get("network_timeout", network_timeout))
    if options.get('ca_file'):
        CA_FILE = options['ca_file']

    tls_wrapped_protocol = TlsWrappedProtocolEnum.PLAIN_TLS
    if starttls_smtp:
        tls_wrapped_protocol = TlsWrappedProtocolEnum.STARTTLS_SMTP

    try:
        # logging.debug("\tTesting connectivity with timeout of %is." % network_timeout)
        server_tester = ServerConnectivityTester(hostname=hostname, port=port, tls_wrapped_protocol=tls_wrapped_protocol)
        server_info = server_tester.perform(network_timeout=network_timeout)
    except ServerConnectivityError:
        logging.warning("\tServer connectivity not established during test.")
        return None, None
    except Exception as err:
        utils.notify(err)
        logging.warning("\tUnknown exception when performing server connectivity info.")
        return None, None

    if sync:
        scanner = SynchronousScanner(network_timeout=network_timeout)
    else:
        scanner = ConcurrentScanner(network_timeout=network_timeout)

    return server_info, scanner
Пример #4
0
    def test_valid_chain_with_ev_cert(self):
        server_test = ServerConnectivityTester(hostname='www.comodo.com')
        server_info = server_test.perform()

        plugin = CertificateInfoPlugin()
        plugin_result = plugin.process_task(server_info, CertificateInfoScanCommand())

        self.assertTrue(plugin_result.is_leaf_certificate_ev)

        self.assertEqual(len(plugin_result.certificate_chain), 3)
        self.assertEqual(len(plugin_result.verified_certificate_chain), 3)
        self.assertFalse(plugin_result.has_anchor_in_certificate_chain)

        self.assertGreaterEqual(len(plugin_result.path_validation_result_list), 5)
        for path_validation_result in plugin_result.path_validation_result_list:
            self.assertTrue(path_validation_result.is_certificate_trusted)

        self.assertEqual(len(plugin_result.path_validation_error_list), 0)
        self.assertEqual(plugin_result.certificate_matches_hostname, True)
        self.assertTrue(plugin_result.is_certificate_chain_order_valid)

        self.assertTrue(plugin_result.as_text())
        self.assertTrue(plugin_result.as_xml())

        # Ensure the results are pickable so the ConcurrentScanner can receive them via a Queue
        self.assertTrue(pickle.dumps(plugin_result))
Пример #5
0
    def test_1000_sans_chain(self):
        # Ensure SSLyze can process a leaf cert with 1000 SANs
        server_test = ServerConnectivityTester(hostname='1000-sans.badssl.com')
        server_info = server_test.perform()

        plugin = CertificateInfoPlugin()
        plugin.process_task(server_info, CertificateInfoScanCommand())
Пример #6
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:
            # And the client provides a client certificate
            client_creds = ClientAuthenticationCredentials(
                client_certificate_chain_path=server.get_client_certificate_path(),
                client_key_path=server.get_client_key_path(),
            )

            server_test = ServerConnectivityTester(
                hostname=server.hostname,
                ip_address=server.ip_address,
                port=server.port,
                client_auth_credentials=client_creds,
            )
            server_info = server_test.perform()

            # The plugin works fine
            plugin = FallbackScsvPlugin()
            plugin_result = plugin.process_task(server_info, FallbackScsvScanCommand())

        self.assertFalse(plugin_result.supports_fallback_scsv)

        self.assertTrue(plugin_result.as_text())
        self.assertTrue(plugin_result.as_xml())
Пример #7
0
    def test_sslv2_enabled(self):
        with LegacyOpenSslServer() as server:
            server_test = ServerConnectivityTester(
                hostname=server.hostname,
                ip_address=server.ip_address,
                port=server.port
            )
            server_info = server_test.perform()

            plugin = OpenSslCipherSuitesPlugin()
            plugin_result = plugin.process_task(server_info, Sslv20ScanCommand())

        # The embedded server does not have a preference
        self.assertFalse(plugin_result.preferred_cipher)

        accepted_cipher_name_list = [cipher.name for cipher in plugin_result.accepted_cipher_list]
        self.assertEqual({'SSL_CK_RC4_128_EXPORT40_WITH_MD5', 'SSL_CK_IDEA_128_CBC_WITH_MD5',
                          'SSL_CK_RC2_128_CBC_EXPORT40_WITH_MD5', 'SSL_CK_DES_192_EDE3_CBC_WITH_MD5',
                          'SSL_CK_DES_192_EDE3_CBC_WITH_MD5', 'SSL_CK_RC4_128_WITH_MD5',
                          'SSL_CK_RC2_128_CBC_WITH_MD5', 'SSL_CK_DES_64_CBC_WITH_MD5'},
                         set(accepted_cipher_name_list))

        self.assertTrue(plugin_result.accepted_cipher_list)
        self.assertFalse(plugin_result.rejected_cipher_list)
        self.assertFalse(plugin_result.errored_cipher_list)

        self.assertTrue(plugin_result.as_text())
        self.assertTrue(plugin_result.as_xml())

        # Ensure the results are pickable so the ConcurrentScanner can receive them via a Queue
        self.assertTrue(pickle.dumps(plugin_result))
Пример #8
0
    def test_ca_file_bad_file(self):
        server_test = ServerConnectivityTester(hostname='www.hotmail.com')
        server_info = server_test.perform()

        plugin = CertificateInfoPlugin()
        with self.assertRaises(ValueError):
            plugin.process_task(server_info, CertificateInfoScanCommand(ca_file='doesntexist'))
Пример #9
0
    def test_synchronous_scanner(self):
        server_test = ServerConnectivityTester(hostname='www.google.com')
        server_info = server_test.perform()

        sync_scanner = SynchronousScanner()
        plugin_result = sync_scanner.run_scan_command(server_info, CompressionScanCommand())
        self.assertTrue(plugin_result.as_text())
        self.assertTrue(plugin_result.as_xml())
    def test_tls_1_3_cipher_suites(self):
        server_test = ServerConnectivityTester(hostname='www.cloudflare.com')
        server_info = server_test.perform()

        plugin = OpenSslCipherSuitesPlugin()
        plugin_result = plugin.process_task(server_info, Tlsv13ScanCommand())

        accepted_cipher_name_list = [cipher.name for cipher in plugin_result.accepted_cipher_list]
        assert {'TLS_CHACHA20_POLY1305_SHA256', 'TLS_AES_256_GCM_SHA384', 'TLS_AES_128_GCM_SHA256'} == \
            set(accepted_cipher_name_list)
Пример #11
0
    def test_optional_client_authentication(self):
        server_test = ServerConnectivityTester(hostname='client.badssl.com')
        server_info = server_test.perform()
        self.assertEqual(server_info.client_auth_requirement, ClientAuthenticationServerConfigurationEnum.OPTIONAL)

        plugin = CertificateInfoPlugin()
        plugin_result = plugin.process_task(server_info, CertificateInfoScanCommand())

        self.assertTrue(plugin_result.as_text())
        self.assertTrue(plugin_result.as_xml())
Пример #12
0
    def test_sha1_chain(self):
        server_test = ServerConnectivityTester(hostname='sha1-intermediate.badssl.com')
        server_info = server_test.perform()

        plugin = CertificateInfoPlugin()
        plugin_result = plugin.process_task(server_info, CertificateInfoScanCommand())

        self.assertTrue(plugin_result.has_sha1_in_certificate_chain)

        self.assertTrue(plugin_result.as_text())
        self.assertTrue(plugin_result.as_xml())
Пример #13
0
    def test_international_names(self):
        server_test = ServerConnectivityTester(hostname='www.sociétégénérale.com')
        server_info = server_test.perform()

        plugin = CertificateInfoPlugin()
        plugin_result = plugin.process_task(server_info, CertificateInfoScanCommand())

        self.assertGreaterEqual(len(plugin_result.certificate_chain), 1)

        self.assertTrue(plugin_result.as_text())
        self.assertTrue(plugin_result.as_xml())
Пример #14
0
    def test_ccs_injection_good(self):
        server_test = ServerConnectivityTester(hostname='www.google.com')
        server_info = server_test.perform()

        plugin = OpenSslCcsInjectionPlugin()
        plugin_result = plugin.process_task(server_info, OpenSslCcsInjectionScanCommand())

        self.assertFalse(plugin_result.is_vulnerable_to_ccs_injection)

        self.assertTrue(plugin_result.as_text())
        self.assertTrue(plugin_result.as_xml())
Пример #15
0
    def test_ipv6(self):
        server_test = ServerConnectivityTester(hostname='www.google.com', ip_address='2607:f8b0:4005:804::2004')
        server_info = server_test.perform()

        plugin = CertificateInfoPlugin()
        plugin_result = plugin.process_task(server_info, CertificateInfoScanCommand())

        self.assertGreaterEqual(len(plugin_result.certificate_chain), 1)

        self.assertTrue(plugin_result.as_text())
        self.assertTrue(plugin_result.as_xml())
    def test_optional_client_auth(self):
        # Given a server that supports optional client authentication
        with ModernOpenSslServer(client_auth_config=ClientAuthConfigEnum.OPTIONAL) as server:
            server_test = ServerConnectivityTester(
                hostname=server.hostname,
                ip_address=server.ip_address,
                port=server.port
            )
            server_info = server_test.perform()

        # SSLyze correctly detects that client auth is optional
        assert server_info.client_auth_requirement == ClientAuthenticationServerConfigurationEnum.OPTIONAL
    def test_required_client_auth_tls_1_2(self):
        # Given a TLS 1.2 server that requires client authentication
        with LegacyOpenSslServer(client_auth_config=ClientAuthConfigEnum.REQUIRED) as server:
            server_test = ServerConnectivityTester(
                hostname=server.hostname,
                ip_address=server.ip_address,
                port=server.port
            )
            server_info = server_test.perform()

        # SSLyze correctly detects that client auth is required
        assert server_info.client_auth_requirement == ClientAuthenticationServerConfigurationEnum.REQUIRED
    def test_required_client_auth_tls_1_3(self):
        # Given a TLS 1.3 server that requires client authentication
        with ModernOpenSslServer(client_auth_config=ClientAuthConfigEnum.REQUIRED) as server:
            server_test = ServerConnectivityTester(
                hostname=server.hostname,
                ip_address=server.ip_address,
                port=server.port
            )
            server_info = server_test.perform()

        # SSLyze correctly detects that client auth is required
        # TODO(AD): Fix this bug; it should be REQUIRED
        assert server_info.client_auth_requirement == ClientAuthenticationServerConfigurationEnum.OPTIONAL
Пример #19
0
    def test_smtp_post_handshake_response(self):
        server_test = ServerConnectivityTester(
            hostname='smtp.gmail.com',
            port=587,
            tls_wrapped_protocol=TlsWrappedProtocolEnum.STARTTLS_SMTP
        )
        server_info = server_test.perform()

        plugin = OpenSslCipherSuitesPlugin()
        plugin_result = plugin.process_task(server_info, Tlsv12ScanCommand())

        self.assertTrue(plugin_result.as_text())
        self.assertTrue(plugin_result.as_xml())
Пример #20
0
    def test_expect_ct_disabled(self):
        server_test = ServerConnectivityTester(hostname='hsts.badssl.com')
        server_info = server_test.perform()

        plugin = HttpHeadersPlugin()
        plugin_result = plugin.process_task(server_info, HttpHeadersScanCommand())

        assert not plugin_result.expect_ct_header

        assert plugin_result.as_text()
        assert plugin_result.as_xml()

        assert pickle.dumps(plugin_result)
Пример #21
0
    def test_heartbleed_good(self):
        server_test = ServerConnectivityTester(hostname='www.google.com')
        server_info = server_test.perform()

        plugin = HeartbleedPlugin()
        plugin_result = plugin.process_task(server_info, HeartbleedScanCommand())

        assert not plugin_result.is_vulnerable_to_heartbleed

        assert plugin_result.as_text()
        assert plugin_result.as_xml()

        # Ensure the results are pickable so the ConcurrentScanner can receive them via a Queue
        assert pickle.dumps(plugin_result)
Пример #22
0
    def test_ecdsa_certificate(self):
        server_test = ServerConnectivityTester(hostname='www.cloudflare.com')
        server_info = server_test.perform()

        plugin = CertificateInfoPlugin()
        plugin_result = plugin.process_task(server_info, CertificateInfoScanCommand())

        self.assertGreaterEqual(len(plugin_result.certificate_chain), 1)

        self.assertTrue(plugin_result.as_text())
        self.assertTrue(plugin_result.as_xml())

        # Ensure the results are pickable so the ConcurrentScanner can receive them via a Queue
        self.assertTrue(pickle.dumps(plugin_result))
Пример #23
0
    def test_certificate_with_no_subject(self):
        server_test = ServerConnectivityTester(hostname='no-subject.badssl.com')
        server_info = server_test.perform()

        plugin = CertificateInfoPlugin()
        plugin_result = plugin.process_task(server_info, CertificateInfoScanCommand())

        self.assertTrue(plugin_result.verified_certificate_chain)

        self.assertTrue(plugin_result.as_text())
        self.assertTrue(plugin_result.as_xml())

        # Ensure the results are pickable so the ConcurrentScanner can receive them via a Queue
        self.assertTrue(pickle.dumps(plugin_result))
Пример #24
0
    def test_certificate_with_scts(self):
        server_test = ServerConnectivityTester(hostname='www.apple.com')
        server_info = server_test.perform()

        plugin = CertificateInfoPlugin()
        plugin_result = plugin.process_task(server_info, CertificateInfoScanCommand())

        self.assertGreater(plugin_result.certificate_included_scts_count, 1)

        self.assertTrue(plugin_result.as_text())
        self.assertTrue(plugin_result.as_xml())

        # Ensure the results are pickable so the ConcurrentScanner can receive them via a Queue
        self.assertTrue(pickle.dumps(plugin_result))
Пример #25
0
    def test_early_data_enabled_online(self):
        server_test = ServerConnectivityTester(hostname='www.cloudflare.com')
        server_info = server_test.perform()

        plugin = EarlyDataPlugin()
        plugin_result = plugin.process_task(server_info, EarlyDataScanCommand())

        self.assertTrue(plugin_result.is_early_data_supported)

        self.assertTrue(plugin_result.as_text())
        self.assertTrue(plugin_result.as_xml())

        # Ensure the results are pickable so the ConcurrentScanner can receive them via a Queue
        self.assertTrue(pickle.dumps(plugin_result))
Пример #26
0
    def test_compression_disabled(self):
        server_test = ServerConnectivityTester(hostname='www.google.com')
        server_info = server_test.perform()

        plugin = CompressionPlugin()
        plugin_result = plugin.process_task(server_info, CompressionScanCommand())

        assert not plugin_result.compression_name

        assert plugin_result.as_text()
        assert plugin_result.as_xml()

        # Ensure the results are pickable so the ConcurrentScanner can receive them via a Queue
        assert pickle.dumps(plugin_result)
Пример #27
0
    def test_fallback_good(self):
        server_test = ServerConnectivityTester(hostname='www.google.com')
        server_info = server_test.perform()

        plugin = FallbackScsvPlugin()
        plugin_result = plugin.process_task(server_info, FallbackScsvScanCommand())

        self.assertTrue(plugin_result.supports_fallback_scsv)

        self.assertTrue(plugin_result.as_text())
        self.assertTrue(plugin_result.as_xml())

        # Ensure the results are pickable so the ConcurrentScanner can receive them via a Queue
        self.assertTrue(pickle.dumps(plugin_result))
Пример #28
0
    def test_not_trusted_by_mozilla_but_trusted_by_microsoft(self):
        server_test = ServerConnectivityTester(hostname='webmail.russia.nasa.gov')
        server_info = server_test.perform()

        plugin = CertificateInfoPlugin()
        plugin_result = plugin.process_task(server_info, CertificateInfoScanCommand())

        self.assertEqual(plugin_result.successful_trust_store.name, 'Windows')

        self.assertTrue(plugin_result.as_text())
        self.assertTrue(plugin_result.as_xml())

        # Ensure the results are pickable so the ConcurrentScanner can receive them via a Queue
        self.assertTrue(pickle.dumps(plugin_result))
Пример #29
0
    def test_ca_file(self):
        server_test = ServerConnectivityTester(hostname='www.hotmail.com')
        server_info = server_test.perform()

        ca_file_path = os.path.join(os.path.dirname(__file__), '..', 'utils', 'wildcard-self-signed.pem')
        plugin = CertificateInfoPlugin()
        plugin_result = plugin.process_task(server_info, CertificateInfoScanCommand(ca_file=ca_file_path))

        self.assertGreaterEqual(len(plugin_result.path_validation_result_list), 6)
        for path_validation_result in plugin_result.path_validation_result_list:
            if path_validation_result.trust_store.name == 'Custom --ca_file':
                self.assertFalse(path_validation_result.is_certificate_trusted)
            else:
                self.assertTrue(path_validation_result.is_certificate_trusted)
Пример #30
0
    def test_xmpp_to(self):
        server_test = ServerConnectivityTester(
            hostname='talk.google.com',
            tls_wrapped_protocol=TlsWrappedProtocolEnum.STARTTLS_XMPP,
            xmpp_to_hostname='gmail.com'
        )
        server_info = server_test.perform()

        plugin = CertificateInfoPlugin()
        plugin_result = plugin.process_task(server_info, CertificateInfoScanCommand())

        self.assertGreaterEqual(len(plugin_result.certificate_chain), 1)

        self.assertTrue(plugin_result.as_text())
        self.assertTrue(plugin_result.as_xml())
Пример #31
0
def get_cert(site_json):

    hostname = get_hostname(site_json['hostname'])

    try:
        server_tester = ServerConnectivityTester(hostname=hostname)
        server_info = server_tester.perform()
        command = CertificateInfoScanCommand()
        synchronous_scanner = SynchronousScanner()
        scan_result = synchronous_scanner.run_scan_command(
            server_info, command)
    except sslyze.server_connectivity_tester.ServerNotReachableError:
        return None
    except sslyze.server_connectivity_tester.ServerConnectivityError:  # plugin has very little documentation, keeping this here for now
        return None
    except OSError:
        return None
    except RuntimeError:
        return None
    except ValueError:
        return None

    return scan_result
    def test_sslv2_enabled(self):
        with VulnerableOpenSslServer() as server:
            server_test = ServerConnectivityTester(
                hostname=server.hostname,
                ip_address=server.ip_address,
                port=server.port)
            server_info = server_test.perform()

            plugin = OpenSslCipherSuitesPlugin()
            plugin_result = plugin.process_task(server_info,
                                                Sslv20ScanCommand())

        # The embedded server does not have a preference
        self.assertFalse(plugin_result.preferred_cipher)

        accepted_cipher_name_list = [
            cipher.name for cipher in plugin_result.accepted_cipher_list
        ]
        self.assertEqual(
            {
                'SSL_CK_RC4_128_EXPORT40_WITH_MD5',
                'SSL_CK_IDEA_128_CBC_WITH_MD5',
                'SSL_CK_RC2_128_CBC_EXPORT40_WITH_MD5',
                'SSL_CK_DES_192_EDE3_CBC_WITH_MD5',
                'SSL_CK_DES_192_EDE3_CBC_WITH_MD5', 'SSL_CK_RC4_128_WITH_MD5',
                'SSL_CK_RC2_128_CBC_WITH_MD5', 'SSL_CK_DES_64_CBC_WITH_MD5'
            }, set(accepted_cipher_name_list))

        self.assertTrue(plugin_result.accepted_cipher_list)
        self.assertFalse(plugin_result.rejected_cipher_list)
        self.assertFalse(plugin_result.errored_cipher_list)

        self.assertTrue(plugin_result.as_text())
        self.assertTrue(plugin_result.as_xml())

        # Ensure the results are pickable so the ConcurrentScanner can receive them via a Queue
        self.assertTrue(pickle.dumps(plugin_result))
Пример #33
0
    def test_https_tunneling(self):
        # Start a local proxy
        proxy_port = 8000
        p = multiprocessing.Process(target=proxy_worker, args=(proxy_port, ))
        p.start()

        # On Travis CI, the server sometimes is still not ready to accept connections when we get here
        # Wait a bit more to make the test suite less flaky
        time.sleep(0.5)

        try:
            # Run a scan through the proxy
            tunnel_settings = HttpConnectTunnelingSettings('localhost', proxy_port, basic_auth_user='******',
                                                           basic_auth_password='******')
            server_test = ServerConnectivityTester(hostname='www.google.com', http_tunneling_settings=tunnel_settings)

            # Try to connect to the proxy - retry if the proxy subprocess wasn't ready
            proxy_connection_attempts = 0
            while True:
                try:
                    server_info = server_test.perform()
                    break
                except ServerConnectivityError:
                    if proxy_connection_attempts > 3:
                        raise
                    proxy_connection_attempts += 1

            plugin = CertificateInfoPlugin()
            plugin_result = plugin.process_task(server_info, CertificateInfoScanCommand())

            assert len(plugin_result.received_certificate_chain) >= 1

            assert plugin_result.as_text()
            assert plugin_result.as_xml()
        finally:
            # Kill the local proxy - unclean
            p.terminate()
Пример #34
0
    def test_fallback_bad(self):
        try:
            with VulnerableOpenSslServer() as server:
                server_test = ServerConnectivityTester(
                    hostname=server.hostname,
                    ip_address=server.ip_address,
                    port=server.port)
                server_info = server_test.perform()

                plugin = FallbackScsvPlugin()
                plugin_result = plugin.process_task(server_info,
                                                    FallbackScsvScanCommand())
        except NotOnLinux64Error:
            # The test suite only has the vulnerable OpenSSL version compiled for Linux 64 bits
            logging.warning(
                'WARNING: Not on Linux - skipping test_fallback_bad() test')
            return

        self.assertFalse(plugin_result.supports_fallback_scsv)
        self.assertTrue(plugin_result.as_text())
        self.assertTrue(plugin_result.as_xml())

        # Ensure the results are pickable so the ConcurrentScanner can receive them via a Queue
        self.assertTrue(pickle.dumps(plugin_result))
    def test_works_when_client_auth_succeeded(self):
        # Given a server that requires client authentication
        try:
            with VulnerableOpenSslServer(
                    client_auth_config=
                    ClientAuthenticationServerConfigurationEnum.REQUIRED
            ) as server:
                # And the client provides a client certificate
                client_creds = ClientAuthenticationCredentials(
                    client_certificate_chain_path=server.
                    get_client_certificate_path(),
                    client_key_path=server.get_client_key_path(),
                )

                server_test = ServerConnectivityTester(
                    hostname=server.hostname,
                    ip_address=server.ip_address,
                    port=server.port,
                    client_auth_credentials=client_creds,
                )
                server_info = server_test.perform()

                # The plugin works fine
                plugin = SessionRenegotiationPlugin()
                plugin_result = plugin.process_task(
                    server_info, SessionRenegotiationScanCommand())

        except NotOnLinux64Error:
            logging.warning('WARNING: Not on Linux - skipping test')
            return

        self.assertTrue(plugin_result.accepts_client_renegotiation)
        self.assertTrue(plugin_result.supports_secure_renegotiation)

        self.assertTrue(plugin_result.as_text())
        self.assertTrue(plugin_result.as_xml())
Пример #36
0
    def test_works_when_client_auth_succeeded(self):
        # Given a server that requires client authentication
        with ModernOpenSslServer(client_auth_config=ClientAuthConfigEnum.REQUIRED) as server:
            # And the client provides a client certificate
            client_creds = ClientAuthenticationCredentials(
                client_certificate_chain_path=server.get_client_certificate_path(),
                client_key_path=server.get_client_key_path(),
            )

            server_test = ServerConnectivityTester(
                hostname=server.hostname,
                ip_address=server.ip_address,
                port=server.port,
                client_auth_credentials=client_creds,
            )
            server_info = server_test.perform()

            # The plugin works fine
            plugin = HttpHeadersPlugin()
            plugin_result = plugin.process_task(server_info, HttpHeadersScanCommand())

        self.assertIsNone(plugin_result.expect_ct_header)
        self.assertTrue(plugin_result.as_text())
        self.assertTrue(plugin_result.as_xml())
    def test_follows_client_cipher_suite_preference(self):
        # Google.com does not follow client cipher suite preference
        server_test = ServerConnectivityTester(hostname='www.google.com')
        server_info = server_test.perform()

        plugin = OpenSslCipherSuitesPlugin()
        plugin_result = plugin.process_task(server_info, Tlsv12ScanCommand())

        self.assertTrue(plugin_result.preferred_cipher)
        self.assertTrue(plugin_result.accepted_cipher_list)

        # Sogou.com follows client cipher suite preference
        server_test = ServerConnectivityTester(hostname='www.sogou.com')
        server_info = server_test.perform()

        plugin = OpenSslCipherSuitesPlugin()
        plugin_result = plugin.process_task(server_info, Tlsv12ScanCommand())

        self.assertIsNone(plugin_result.preferred_cipher)
        self.assertTrue(plugin_result.accepted_cipher_list)

        # Ensure the results are pickable so the ConcurrentScanner can receive them via a Queue
        self.assertTrue(pickle.dumps(plugin_result))
Пример #38
0
    def test_ssl_basic(self, hostname, port=443):
        '''
        Uses the `ServerConnectivityTester` functionality of SSlyze to perform a basic test.
        Port defaults to 443 unless provided otherwise
        hostname is mandatory

        | test ssl basic  | hostname  | port (optional |

        '''
        try:
            tester = ServerConnectivityTester(hostname=hostname, port=port)
            server_info = tester.perform()

            scanner = ConcurrentScanner()
            # scanner.queue_scan_command(info, certificate_info_plugin.CertificateInfoScanCommand())
            scanner.queue_scan_command(server_info, Sslv20ScanCommand())
            scanner.queue_scan_command(server_info, Sslv30ScanCommand())
            scanner.queue_scan_command(server_info, Tlsv10ScanCommand())
            scanner.queue_scan_command(server_info, Tlsv10ScanCommand())
            scanner.queue_scan_command(server_info, Tlsv11ScanCommand())
            scanner.queue_scan_command(server_info, Tlsv12ScanCommand())
            scanner.queue_scan_command(server_info, HeartbleedScanCommand())
            scanner.queue_scan_command(server_info, RobotScanCommand())
            # scanner.queue_scan_command(server_info, CertificateInfoScanCommand())

            for scan_result in scanner.get_results():
                # logger.info("Scan result for: {} on hostname: {}".format(scan_result.scan_command.__class__.__name__, scan_result.server_info.hostname))

                if isinstance(scan_result, PluginRaisedExceptionScanResult):
                    raise Exception("Scan Command Failed: {}".format(
                        scan_result.as_text()))

                if isinstance(scan_result.scan_command, Sslv20ScanCommand):
                    if scan_result.accepted_cipher_list:
                        logger.warn("SSLv2 ciphersuites accepted")
                        for suite in scan_result.accepted_cipher_list:
                            logger.info("\t{}".format(suite.name))
                    else:
                        logger.info("SSLv2 ciphersuites not accepted")

                if isinstance(scan_result.scan_command, Sslv30ScanCommand):
                    if scan_result.accepted_cipher_list:
                        logger.warn("SSLv3 Cipher Suites accepted")
                        for suite in scan_result.accepted_cipher_list:
                            logger.info("\t{}".format(suite.name))
                    else:
                        logger.info("SSLv3 ciphersuites not accepted")

                if isinstance(scan_result.scan_command, Tlsv10ScanCommand):
                    if scan_result.accepted_cipher_list:
                        logger.warn("TLSv1 Cipher Suites accepted")
                        for suite in scan_result.accepted_cipher_list:
                            logger.info("\t{}".format(suite.name))
                    else:
                        logger.info("TLSv1 ciphersuites not accepted")

                if isinstance(scan_result.scan_command, Tlsv11ScanCommand):
                    if scan_result.accepted_cipher_list:
                        logger.info("TLSv1.1 Cipher Suites accepted")
                        for suite in scan_result.accepted_cipher_list:
                            logger.info("\t{}".format(suite.name))
                    else:
                        logger.info("TLSv1.1 ciphersuites not accepted")

                if isinstance(scan_result.scan_command, Tlsv12ScanCommand):
                    if scan_result.accepted_cipher_list:
                        logger.info("TLSv1.2 Cipher Suites accepted")
                        for suite in scan_result.accepted_cipher_list:
                            logger.info("\t{}".format(suite.name))
                    else:
                        logger.info("TLSv1.2 ciphersuites not accepted")

                if isinstance(scan_result.scan_command, HeartbleedScanCommand):
                    if scan_result.is_vulnerable_to_heartbleed:
                        logger.warn(
                            "Server TLS implementation is vulnerable to Heartbleed"
                        )
                    else:
                        logger.info(
                            "Server TLS Implementation not vulnerable to Heartbleed"
                        )

                if isinstance(scan_result.scan_command, RobotScanCommand):
                    logger.info("Test for ROBOT Vulnerability")
                    if scan_result.robot_result_enum.NOT_VULNERABLE_NO_ORACLE:
                        logger.info(
                            "\tNot Vulnerable: The server supports RSA cipher suites but does not act as an oracle"
                        )
                    elif scan_result.robot_result_enum.VULNERABLE_WEAK_ORACLE:
                        logger.warn(
                            "\tVulnerable: The server is vulnerable but the attack would take too long"
                        )
                    elif scan_result.robot_result_enum.VULNERABLE_STRONG_ORACLE:
                        logger.warn(
                            "\tVulnerable: The server is vulnerable and real attacks are feasible"
                        )
                    elif scan_result.robot_result_enum.NOT_VULNERABLE_RSA_NOT_SUPPORTED:
                        logger.info(
                            "\tNot Vulnerable: The server does not supports RSA cipher suites"
                        )
                    else:
                        logger.info(
                            "\tUnable to determine if implementation is vulnerable"
                        )

                # if isinstance(scan_result.scan_command, CertificateInfoScanCommand):
                #     logger.info(u'Server Certificate CN: {}'.format(
                #         dict(scan_result.certificate_chain[0])[u'subject'][u'commonName']
                #     ))

        except ServerConnectivityError as e:
            logger.error('Error when trying to connect to {}: {}'.format(
                e.server_info.hostname, e.error_message))
Пример #39
0
def ssltlsscan(web):

    target = web.split('//')[1]
    print(R + '\n    ===============================')
    print(R + '     S S L   E N U M E R A T I O N')
    print(R + '    ===============================\n')
    print(GR + ' [*] Testing server SSL status...')
    try:
        req = requests.get('https://' + target)
        print(G + ' [+] SSL Working Properly...')
        time.sleep(0.6)
        print(O + " [!] Running SSL Enumeration...\n")
        try:
            server_tester = ServerConnectivityTester(hostname=target)
            server_info = server_tester.perform()
            scanner = SynchronousScanner()

            command = Tlsv10ScanCommand()
            scan_result = scanner.run_scan_command(server_info, command)
            print(G + " [+] Available TLS v1.0 Ciphers:")
            for cipher in scan_result.accepted_cipher_list:
                print(C + '    {}'.format(cipher.name))
            print('')

            command = Tlsv11ScanCommand()
            scan_result = scanner.run_scan_command(server_info, command)
            print(G + " [+] Available TLS v1.1 Ciphers:")
            for cipher in scan_result.accepted_cipher_list:
                print(C + '    {}'.format(cipher.name))
            print('')

            command = Tlsv12ScanCommand()
            scan_result = scanner.run_scan_command(server_info, command)
            print(G + " [+] Available TLS v1.2 Ciphers:")
            for cipher in scan_result.accepted_cipher_list:
                print(C + '    {}'.format(cipher.name))
            print('')

            command = CertificateInfoScanCommand()
            scan_result = scanner.run_scan_command(server_info, command)
            print(G + ' [+] Certificate Information:')
            for entry in scan_result.as_text():
                if entry != '':
                    if 'certificate information' in entry.lower():
                        pass
                    elif ':' in entry:
                        print(GR + '    [+] ' +
                              entry.strip().split(':', 1)[0].strip() + ' : ' +
                              C + entry.strip().split(':', 1)[1].strip())
                    else:
                        print(O + '\n  [+] ' + entry.strip())
            print('')

            command = HttpHeadersScanCommand()
            scan_result = scanner.run_scan_command(server_info, command)
            print(G + ' [+] HTTP Results:')
            for entry in scan_result.as_text():
                if 'http security' not in entry.strip().lower(
                ) and entry != '':
                    if '-' in entry:
                        print(GR + '    [+] ' +
                              entry.split('-', 1)[0].strip() + ' - ' + C +
                              entry.split('-', 1)[1].strip())
                    elif ':' in entry:
                        print(GR + '    [+] ' +
                              entry.strip().split(':', 1)[0].strip() + ' : ' +
                              C + entry.strip().split(':', 1)[1].strip())
                    else:
                        print(O + '\n  [+] ' + entry.strip())
            print('')

        except Exception as e:
            print(R + ' [-] Unhandled SSL Runtime Exception : ' + str(e))
            pass

    except requests.exceptions.SSLError as e:
        print(R + ' [-] Distant Server SSL not working : ' + str(e))

    print(G + ' [+] SSlScan Module Completed!')
Пример #40
0
def run(url):
    scan_result = {
        "name": __plugin__,
        "sequence": SEQUENCE,
        "result": [],
    }
    error_result = {
        "name": __plugin__,
        "sequence": SEQUENCE,
        "result": [],
    }
    error_result["result"] = [{
        "name":
        "Error",
        "result": [{
            "name": f"{__plugin__} can't scan this website"
        }]
    }]
    result_map = {
        "https": {
            "name": "Enabled HTTPS",
            "sequence": 0,
            "result": False
        },
        "effective": {
            "name": "Effective",
            "sequence": 1,
            "result": False
        },
        "match": {
            "name": "Leaf certificate subject matches hostname",
            "sequence": 2,
            "result": False
        },
        "signature": {
            "name": "Signature security (use SHA256)",
            "sequence": 3,
            "result": False
        },
        "public": {
            "name": "Public key security (use ECDSA_256+ or RSA_2048+)",
            "sequence": 4,
            "result": False,
        },
        "tls1_2": {
            "name": "Support TLS1.2",
            "sequence": 5,
            "result": False
        },
        "pfs": {
            "name": "Perfect Forward Secrecy (PFS)",
            "sequence": 6,
            "result": False
        },
        "ats": {
            "name": "App Transport Security (ATS)",
            "sequence": 7,
            "result": False
        },
        "ccs": {
            "name": "CCS Injection",
            "sequence": 8,
            "result": False
        },
        "heartbleed": {
            "name": "HeartBleed",
            "sequence": 9,
            "result": False
        },
    }
    mini_length = 256
    start_time = None
    end_time = None

    try:
        server_tester = ServerConnectivityTester(hostname=url.netloc,
                                                 port=url.port)
        server_info = server_tester.perform()
    except:
        return error_result

    synchronous_scanner = SynchronousScanner()
    certificate_result = synchronous_scanner.run_scan_command(
        server_info, CertificateInfoScanCommand())
    cipher_result = synchronous_scanner.run_scan_command(
        server_info, Tlsv12ScanCommand())
    ccs_result = synchronous_scanner.run_scan_command(
        server_info, OpenSslCcsInjectionScanCommand())
    heartbleed_result = synchronous_scanner.run_scan_command(
        server_info, HeartbleedScanCommand())

    if certificate_result.leaf_certificate_subject_matches_hostname:
        result_map["match"]["result"] = True

    for result in certificate_result.as_text():
        result_list = [x.strip() for x in result.split(": ")]
        if len(result_list) == 2:
            result_map["https"]["result"] = True
            if result_list[0] == "Public Key Algorithm":
                if result_list[1] == "_RSAPublicKey":
                    mini_length = 2048
            if result_list[0] == "Key Size":
                if int(result_list[1]) >= mini_length:
                    result_map["public"]["result"] = True
            if result_list[0] == "Signature Algorithm":
                if result_list[1] == "sha256":
                    result_map["signature"]["result"] = True
            if result_list[0] == "Not Before":
                start_time = result_list[1]
            if result_list[0] == "Not After":
                end_time = result_list[1]

    if start_time and end_time:
        if (datetime.strptime(start_time, "%Y-%m-%d %H:%M:%S") <
                datetime.now() and datetime.strptime(
                    end_time, "%Y-%m-%d %H:%M:%S") > datetime.now()):
            result_map["effective"]["result"] = True
    cipher_list = [
        cipher.name for cipher in cipher_result.accepted_cipher_list
    ]
    if cipher_list:
        result_map["tls1_2"]["result"] = True
        for cipher in cipher_list:
            if "DHE" in cipher:
                result_map["pfs"]["result"] = True
        if set(cipher_list).intersection(ATS_CIPHER_SET):
            result_map["ats"]["result"] = True
    if not ccs_result.is_vulnerable_to_ccs_injection:
        result_map["ccs"]["result"] = True
    if not heartbleed_result.is_vulnerable_to_heartbleed:
        result_map["heartbleed"]["result"] = True

    scan_result["result"] = sorted([item for item in result_map.values()],
                                   key=lambda x: x.get("sequence", 0))

    return scan_result
Пример #41
0
    def parse_command_line(
        self
    ) -> Tuple[List[ServerConnectivityTester], List[ServerStringParsingError],
               Any]:
        """Parses the command line used to launch SSLyze.
        """
        (args_command_list, args_target_list) = self._parser.parse_args()

        if args_command_list.update_trust_stores:
            # Just update the trust stores and do nothing
            TrustStoresRepository.update_default()
            raise TrustStoresUpdateCompleted()

        # Handle the --targets_in command line and fill args_target_list
        if args_command_list.targets_in:
            if args_target_list:
                raise CommandLineParsingError(
                    "Cannot use --targets_list and specify targets within the command line."
                )

            try:  # Read targets from a file
                with open(args_command_list.targets_in) as f:
                    for target in f.readlines():
                        if target.strip():  # Ignore empty lines
                            if not target.startswith(
                                    "#"):  # Ignore comment lines
                                args_target_list.append(target.strip())
            except IOError:
                raise CommandLineParsingError(
                    "Can't read targets from input file '{}.".format(
                        args_command_list.targets_in))

        if not args_target_list:
            raise CommandLineParsingError("No targets to scan.")

        # Handle the --regular command line parameter as a shortcut
        if self._parser.has_option("--regular"):
            if getattr(args_command_list, "regular"):
                setattr(args_command_list, "regular", False)
                for cmd in self.REGULAR_CMD:
                    setattr(args_command_list, cmd, True)

        # Sanity checks on the command line options
        # Prevent --quiet and --xml_out -
        if args_command_list.xml_file and args_command_list.xml_file == "-" and args_command_list.quiet:
            raise CommandLineParsingError(
                "Cannot use --quiet with --xml_out -.")

        # Prevent --quiet and --json_out -
        if args_command_list.json_file and args_command_list.json_file == "-" and args_command_list.quiet:
            raise CommandLineParsingError(
                "Cannot use --quiet with --json_out -.")

        # Prevent --xml_out - and --json_out -
        if (args_command_list.json_file and args_command_list.json_file == "-"
                and args_command_list.xml_file
                and args_command_list.xml_file == "-"):
            raise CommandLineParsingError(
                "Cannot use --xml_out - with --json_out -.")

        # Sanity checks on the client cert options
        client_auth_creds = None
        if bool(args_command_list.cert) ^ bool(args_command_list.key):
            raise CommandLineParsingError(
                "No private key or certificate file were given. See --cert and --key."
            )

        elif args_command_list.cert:
            # Private key formats
            if args_command_list.keyform == "DER":
                key_type = OpenSslFileTypeEnum.ASN1
            elif args_command_list.keyform == "PEM":
                key_type = OpenSslFileTypeEnum.PEM
            else:
                raise CommandLineParsingError(
                    "--keyform should be DER or PEM.")

            # Let's try to open the cert and key files
            try:
                client_auth_creds = ClientAuthenticationCredentials(
                    args_command_list.cert, args_command_list.key, key_type,
                    args_command_list.keypass)
            except ValueError as e:
                raise CommandLineParsingError(
                    "Invalid client authentication settings: {}.".format(
                        e.args[0]))

        # HTTP CONNECT proxy
        http_tunneling_settings = None
        if args_command_list.https_tunnel:
            try:
                http_tunneling_settings = HttpConnectTunnelingSettings.from_url(
                    args_command_list.https_tunnel)
            except ValueError as e:
                raise CommandLineParsingError(
                    "Invalid proxy URL for --https_tunnel: {}.".format(
                        e.args[0]))

        # STARTTLS
        tls_wrapped_protocol = TlsWrappedProtocolEnum.PLAIN_TLS
        if args_command_list.starttls:
            if args_command_list.starttls not in self.START_TLS_PROTOCOLS:
                raise CommandLineParsingError(self.START_TLS_USAGE)
            else:
                # StartTLS was specified
                if args_command_list.starttls in self.STARTTLS_PROTOCOL_DICT.keys(
                ):
                    # Protocol was given in the command line
                    tls_wrapped_protocol = self.STARTTLS_PROTOCOL_DICT[
                        args_command_list.starttls]

        # Create the server connectivity tester for each specified servers
        # A limitation when using the command line is that only one client_auth_credentials and http_tunneling_settings
        # can be specified, for all the servers to scan
        good_server_list = []
        bad_server_list = []
        for server_string in args_target_list:
            try:
                hostname, ip_address, port = CommandLineServerStringParser.parse_server_string(
                    server_string)
            except ServerStringParsingError as e:
                # Will happen if the server string is malformed
                bad_server_list.append(e)
                continue

            try:
                # TODO(AD): Unicode hostnames may fail on Python2
                # hostname = hostname.decode('utf-8')
                server_info = ServerConnectivityTester(
                    hostname=hostname,
                    port=port,
                    ip_address=ip_address,
                    tls_wrapped_protocol=tls_wrapped_protocol,
                    tls_server_name_indication=args_command_list.sni,
                    xmpp_to_hostname=args_command_list.xmpp_to,
                    client_auth_credentials=client_auth_creds,
                    http_tunneling_settings=http_tunneling_settings,
                )
                good_server_list.append(server_info)
            except ValueError as e:
                # Will happen for example if xmpp_to is specified for a non-XMPP connection
                raise CommandLineParsingError(e.args[0])

        # Command line hacks
        # Handle --starttls=auto now that we parsed the server strings
        if args_command_list.starttls == "auto":
            for server_info in good_server_list:
                # We use the port number to deduce the protocol
                if server_info.port in self.STARTTLS_PROTOCOL_DICT.keys():
                    server_info.tls_wrapped_protocol = self.STARTTLS_PROTOCOL_DICT[
                        server_info.port]

        # Handle --http_get now that we parsed the server strings
        # Doing it here is hacky as the option is defined within PluginOpenSSLCipherSuites
        if args_command_list.http_get:
            for server_info in good_server_list:
                if server_info.port == 443:
                    server_info.tls_wrapped_protocol = TlsWrappedProtocolEnum.HTTPS

        return good_server_list, bad_server_list, args_command_list
    def test_sslv3_enabled(self):
        try:
            with VulnerableOpenSslServer() as server:
                server_test = ServerConnectivityTester(
                    hostname=server.hostname,
                    ip_address=server.ip_address,
                    port=server.port)
                server_info = server_test.perform()

                plugin = OpenSslCipherSuitesPlugin()
                plugin_result = plugin.process_task(server_info,
                                                    Sslv30ScanCommand())
        except NotOnLinux64Error:
            # The test suite only has the vulnerable OpenSSL version compiled for Linux 64 bits
            logging.warning('WARNING: Not on Linux - skipping test')
            return

        # The embedded server does not have a preference
        self.assertFalse(plugin_result.preferred_cipher)
        accepted_cipher_name_list = [
            cipher.name for cipher in plugin_result.accepted_cipher_list
        ]
        self.assertEqual(
            {
                'TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA',
                'TLS_RSA_WITH_3DES_EDE_CBC_SHA',
                'TLS_DH_anon_WITH_AES_128_CBC_SHA',
                'TLS_ECDH_anon_WITH_AES_128_CBC_SHA',
                'TLS_DH_anon_WITH_SEED_CBC_SHA',
                'TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5',
                'TLS_ECDHE_RSA_WITH_NULL_SHA',
                'TLS_ECDHE_RSA_WITH_RC4_128_SHA',
                'TLS_DH_anon_WITH_AES_256_CBC_SHA',
                'TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA',
                'TLS_ECDH_anon_WITH_RC4_128_SHA',
                'TLS_DH_anon_WITH_3DES_EDE_CBC_SHA',
                'TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA',
                'TLS_DH_anon_EXPORT_WITH_RC4_40_MD5',
                'TLS_RSA_EXPORT_WITH_DES40_CBC_SHA',
                'TLS_ECDH_anon_WITH_NULL_SHA',
                'TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA',
                'TLS_RSA_WITH_RC4_128_SHA', 'TLS_RSA_EXPORT_WITH_RC4_40_MD5',
                'TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA', 'TLS_RSA_WITH_NULL_MD5',
                'TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA',
                'TLS_DH_anon_WITH_DES_CBC_SHA', 'TLS_RSA_WITH_SEED_CBC_SHA',
                'TLS_RSA_WITH_DES_CBC_SHA',
                'TLS_ECDH_anon_WITH_AES_256_CBC_SHA',
                'TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA',
                'TLS_RSA_WITH_CAMELLIA_256_CBC_SHA',
                'TLS_RSA_WITH_AES_256_CBC_SHA', 'TLS_RSA_WITH_RC4_128_MD5',
                'TLS_RSA_WITH_CAMELLIA_128_CBC_SHA',
                'TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA', 'TLS_RSA_WITH_NULL_SHA',
                'TLS_RSA_WITH_IDEA_CBC_SHA', 'TLS_RSA_WITH_AES_128_CBC_SHA',
                'TLS_DH_anon_WITH_RC4_128_MD5'
            }, set(accepted_cipher_name_list))

        self.assertTrue(plugin_result.accepted_cipher_list)
        self.assertTrue(plugin_result.rejected_cipher_list)
        self.assertFalse(plugin_result.errored_cipher_list)

        self.assertTrue(plugin_result.as_text())
        self.assertTrue(plugin_result.as_xml())

        # Ensure the results are pickable so the ConcurrentScanner can receive them via a Queue
        self.assertTrue(pickle.dumps(plugin_result))
Пример #43
0
def scan(targets: List[object_models.TargetWithExtra],
         command_names: Optional[str] = None) -> List[ScanResult]:
    logger.info(
        f"SC0002 New scan initiated with sslyze version {sslyze_version} for target {targets}"
    )

    if command_names is None:
        commands = scan_commands.from_names_to_scan_commands(
            SslyzeConfig.limit_scan_to_scan_commands_names)
    else:
        commands = scan_commands.from_names_to_scan_commands(command_names)

    domain_results = []

    for target in targets:
        domain_result = ScanResult(target)

        try:
            server_tester = ServerConnectivityTester(
                hostname=target.target_definition.hostname,
                port=target.target_definition.port,
                ip_address=target.target_definition.ip_address,
                tls_wrapped_protocol=target.target_definition.protocol)

            server_info = server_tester.perform(
                network_timeout=connectivity_timeout)
        except ServerConnectivityError as e:
            error_msg = f"NT0001 Cannot establish connectivity to target {target} with error {e}"
            logger.warning(error_msg)
            domain_result.msg += error_msg + '\n'
            domain_results.append(domain_result)
            continue
        except Exception as e:
            error_msg = f"NT0002 Unknown exception in establishing connection to target {target} with error {e}"
            logger.warning(error_msg)
            domain_result.msg += error_msg + '\n'
            domain_results.append(domain_result)
            continue

        scan_results = set()

        if SslyzeConfig.asynchronous_scanning:
            logger.debug("Using SSLyze asynchronous scanner")
            scanner = ConcurrentScanner(
                network_timeout=scanner_plugin_network_timeout)
            for scan_command in commands:
                scanner.queue_scan_command(server_info, scan_command())

            for scan_result in scanner.get_results():
                # todo: put some error msg to db
                # todo: handle errors, maybe already solved by PluginRaisedExceptionScanResult
                scan_results.add(scan_result)

        else:
            logger.debug("Using SSLyze synchronous scanner")
            scanner = SynchronousScanner(
                network_timeout=scanner_plugin_network_timeout)
            for scan_command in commands:
                try:
                    scan_result = scanner.run_scan_command(
                        server_info, scan_command())
                    scan_results.add(scan_result)
                except Exception as e:
                    # todo: put some error msg to db
                    # todo: handle errors, maybe already solved by PluginRaisedExceptionScanResult
                    logger.exception(e)

        for scan_result in scan_results:
            scan_command_title = scan_result.scan_command.get_title()

            if isinstance(scan_result, PluginRaisedExceptionScanResult):
                error_msg = f"SC0003 Scan command failed: {target}, {scan_result.as_text()}"
                domain_result.msg += error_msg + '\n'
                logger.warning(error_msg)
                continue

            scan_result_dicts = scan_result_to_dicts(scan_result)
            domain_result.plugin_results[
                scan_command_title] = scan_result_dicts[1]
            domain_result.server_info = scan_result_dicts[0]

        domain_results.append(domain_result)

    return domain_results
Пример #44
0
 def test_tls_1_only(self):
     server_test = ServerConnectivityTester(hostname='tls-v1-0.badssl.com', port=1010)
     server_info = server_test.perform()
     assert server_info.highest_ssl_version_supported == OpenSslVersionEnum.TLSV1
Пример #45
0
def https_check(endpoint):
    """
    Uses sslyze to figure out the reason the endpoint wouldn't verify.
    """
    utils.debug("sslyzing %s..." % endpoint.url)

    # remove the https:// from prefix for sslyze
    try:
        hostname = endpoint.url[8:]
        server_tester = ServerConnectivityTester(hostname=hostname, port=443)
        server_info = server_tester.perform()
    except ServerConnectivityError as err:
        logging.warn(
            "Error in sslyze server connectivity check when connecting to {}".
            format(err.server_info.hostname))
        utils.debug("{0}".format(err))
        return
    except Exception as err:
        endpoint.unknown_error = True
        logging.warn("Unknown exception in sslyze server connectivity check.")
        utils.debug("{0}".format(err))
        return

    try:
        command = sslyze.plugins.certificate_info_plugin.CertificateInfoScanCommand(
            ca_file=CA_FILE)
        scanner = sslyze.synchronous_scanner.SynchronousScanner()
        cert_plugin_result = scanner.run_scan_command(server_info, command)
    except Exception as err:
        endpoint.unknown_error = True
        logging.warn("Unknown exception in sslyze scanner.")
        utils.debug("{0}".format(err))
        return

    try:
        cert_response = cert_plugin_result.as_text()
    except AttributeError as err:
        logging.warn(
            "Known error in sslyze 1.X with EC public keys. See https://github.com/nabla-c0d3/sslyze/issues/215"
        )
        return None
    except Exception as err:
        endpoint.unknown_error = True
        logging.warn("Unknown exception in cert plugin.")
        utils.debug("{0}".format(err))
        return

    # Debugging
    # for msg in cert_response:
    #     print(msg)

    # Default endpoint assessments to False until proven True.
    endpoint.https_expired_cert = False
    endpoint.https_self_signed_cert = False
    endpoint.https_bad_chain = False
    endpoint.https_bad_hostname = False

    # STORE will be either "Mozilla" or "Custom"
    # depending on what the user chose.

    # A certificate can have multiple issues.
    for msg in cert_response:

        # Check for missing SAN.
        if ((("DNS Subject Alternative Names") in msg) and (("[]") in msg)):
            endpoint.https_bad_hostname = True

        # Check for certificate expiration.
        if ((STORE in msg) and (("FAILED") in msg)
                and (("certificate has expired") in msg)):
            endpoint.https_expired_cert = True

        # Check to see if the cert is self-signed
        if ((STORE in msg) and (("FAILED") in msg)
                and (("self signed certificate") in msg)):
            endpoint.https_self_signed_cert = True

        # Check to see if there is a bad chain

        # NOTE: If this is the only flag that's set, it's probably
        # an incomplete chain
        # If this isnt the only flag that is set, it's might be
        # because there is another error. More debugging would
        # need to be done at this point, but not through sslyze
        # because sslyze doesn't have enough granularity

        if ((STORE in msg) and (("FAILED") in msg)
                and ((("unable to get local issuer certificate") in msg) or
                     (("self signed certificate") in msg))):
            endpoint.https_bad_chain = True

        # Check for whether the hostname validates.
        if ((("Hostname Validation") in msg) and (("FAILED") in msg)
                and (("Certificate does NOT match") in msg)):
            endpoint.https_bad_hostname = True
Пример #46
0
def handler(event, context):
    """Handler for all Lambda events

    The event parameter is a dictionary containing the following keys
    and value types:
    * hostname - A string containing the hostname to be scanned.  For
      example, "dhs.gov".
    * port - An integer specifying the port to be scanned.  If omitted
      then the default value of 443 is used.
    * timeout - An integer denoting the number of seconds to wait when
      creating a connection.  If omitted then the default value of 5
      is used.
    * starttls_smtp - A boolean value denoting whether to try to use
      STARTTLS after connecting to an SMTP server.  This option should
      be True is connecting to an SMTP host and otherwise False.  If
      omitted then the default value of False is used.
    * scan_tlsv10 - A boolean value denoting whether to scan for TLS
      version 1.0 ciphers. If omitted then the default value of False
      is used.
    * scan_tlsv11 - A boolean value denoting whether to scan for TLS
      version 1.1 ciphers. If omitted then the default value of False
      is used.
    * scan_tlsv12 - A boolean value denoting whether to scan for TLS
      version 1.2 ciphers. If omitted then the default value of False
      is used.
    * scan_tlsv13 - A boolean value denoting whether to scan for TLS
      version 1.3 ciphers. If omitted then the default value of False
      is used.
    * scan_sslv20 - A boolean value denoting whether to scan for SSL
      version 2.0 ciphers. If omitted then the default value of False
      is used.
    * scan_sslv30 - A boolean value denoting whether to scan for SSL
      version 3.0 ciphers. If omitted then the default value of False
      is used.
    * scan_cert_info - A boolean value denoting whether to return
      certificate information. If omitted then the default value of
      False is used.

    Parameters
    ----------
    event : dict
        A dictionary containing the scan parameters, as described
        above.

    context : LambdaContext
        The context for the Lambda function.  See the corresponding
        AWS documentation for more details:
        https://docs.aws.amazon.com/lambda/latest/dg/python-context-object.html

    Returns
    -------
    OrderedDict
        An OrderedDict specifying the fields of the
        trustymail.domain.Domain object resulting from the scan
        activity.
    """
    logging.info('AWS Event was: {}'.format(event))

    # Extract some variables from the event dictionary
    hostname = event['hostname']
    port = event.get('port', 443)
    timeout = event.get('timeout', 5)
    starttls_smtp = event.get('starttls_smtp', False)
    scan_tlsv10 = event.get('scan_tlsv10', False)
    scan_tlsv11 = event.get('scan_tlsv11', False)
    scan_tlsv12 = event.get('scan_tlsv12', False)
    scan_tlsv13 = event.get('scan_tlsv13', False)
    scan_sslv20 = event.get('scan_sslv20', False)
    scan_sslv30 = event.get('scan_sslv30', False)
    scan_cert_info = event.get('scan_cert_info', False)

    # Initialize sslyze
    protocol = TlsWrappedProtocolEnum.PLAIN_TLS
    if starttls_smtp:
        protocol = TlsWrappedProtocolEnum.STARTTLS_SMTP

    try:
        server_tester = ServerConnectivityTester(hostname=hostname,
                                                 port=port,
                                                 tls_wrapped_protocol=protocol)
        server_info = server_tester.perform(network_timeout=timeout)
    except ServerConnectivityError:
        logging.error('Unable to connect to {}:{}'.format(hostname, port),
                      exc_info=True, stack_info=True)
        return None
    except Exception:
        logging.error('Unable to connect to {}:{}'.format(hostname, port),
                      exc_info=True, stack_info=True)
        return None

    scanner = SynchronousScanner(network_timeout=timeout)

    # Perform the scans
    if scan_tlsv10:
        logging.debug('Performing TLSv1.0 scan')
        tlsv10 = scanner.run_scan_command(server_info, Tlsv10ScanCommand())
        logging.debug('tlsv10 = {}'.format(tlsv10))
    if scan_tlsv11:
        logging.debug('Performing TLSv1.1 scan')
        tlsv11 = scanner.run_scan_command(server_info, Tlsv11ScanCommand())
        logging.debug('tlsv11 = {}'.format(tlsv11))
    if scan_tlsv12:
        logging.debug('Performing TLSv1.2 scan')
        tlsv12 = scanner.run_scan_command(server_info, Tlsv12ScanCommand())
        logging.debug('tlsv12 = {}'.format(tlsv12))
    if scan_tlsv13:
        logging.debug('Performing TLSv1.3 scan')
        tlsv13 = scanner.run_scan_command(server_info, Tlsv13ScanCommand())
        logging.debug('tlsv13 = {}'.format(tlsv13))
    if scan_sslv20:
        logging.debug('Performing SSLv2 scan')
        sslv20 = scanner.run_scan_command(server_info, Sslv20ScanCommand())
        logging.debug('sslv20 = {}'.format(sslv20))
    if scan_sslv30:
        logging.debug('Performing SSLv3 scan')
        sslv30 = scanner.run_scan_command(server_info, Sslv30ScanCommand())
        logging.debug('sslv30 = {}'.format(sslv30))
    if scan_cert_info:
        logging.debug('Performing certificate scan')
        cert_info = scanner.run_scan_command(server_info,
                                             CertificateInfoScanCommand())
        logging.debug('cert_info = {}'.format(cert_info))

    return None
Пример #47
0
from sslyze.concurrent_scanner import ConcurrentScanner, PluginRaisedExceptionScanResult
from sslyze.plugins.utils.certificate_utils import CertificateUtils
from sslyze.plugins.certificate_info_plugin import CertificateInfoScanCommand
from sslyze.plugins.session_renegotiation_plugin import SessionRenegotiationScanCommand

from sslyze.server_connectivity_tester import ServerConnectivityTester, ServerConnectivityError
from sslyze.ssl_settings import TlsWrappedProtocolEnum
from sslyze.synchronous_scanner import SynchronousScanner
from sslyze.plugins.openssl_cipher_suites_plugin import Tlsv10ScanCommand, Tlsv12ScanCommand

if __name__ == '__main__':
    # Setup the server to scan and ensure it is online/reachable
    try:
        server_tester = ServerConnectivityTester(
            hostname='smtp.gmail.com',
            port=587,
            tls_wrapped_protocol=TlsWrappedProtocolEnum.STARTTLS_SMTP
        )
        server_info = server_tester.perform()
    except ServerConnectivityError as e:
        # Could not establish an SSL connection to the server
        raise RuntimeError('Error when connecting to {}: {}'.format(e.server_info.hostname, e.error_message))


    # Example 1: Run one scan command synchronously to list the server's TLS 1.0 cipher suites
    print('\nRunning one scan command synchronously...')
    synchronous_scanner = SynchronousScanner()
    command = Tlsv10ScanCommand()
    scan_result = synchronous_scanner.run_scan_command(server_info, command)
    for cipher in scan_result.accepted_cipher_list:
        print('    {}'.format(cipher.name))
Пример #48
0
def ssltlsscan(web):
    global name
    name = targetname(web)
    global lvl2
    lvl2 = inspect.stack()[0][3]
    global module
    module = "ScanANDEnum"
    global lvl1
    lvl1 = "Scanning & Enumeration"
    global lvl3
    lvl3 = ""
    target = web.split('//')[1]
    #print(R+'\n    ===============================')
    #print(R+'     S S L   E N U M E R A T I O N')
    #print(R+'    ===============================\n')
    from core.methods.print import pscan
    pscan("ssl enumeration")
    print(GR + ' [*] Testing server SSL status...')
    try:
        req = requests.get('https://' + target)
        print(G + ' [+] SSL Working Properly...' + color.TR2 + C)
        time.sleep(0.6)
        print(C + " [!] Running SSL Enumeration...\n")
        try:
            server_tester = ServerConnectivityTester(hostname=target)
            server_info = server_tester.perform()
            scanner = SynchronousScanner()

            command = Tlsv10ScanCommand()
            scan_result = scanner.run_scan_command(server_info, command)
            print(G + " [+] Available TLS v1.0 Ciphers:" + color.TR2 + C)
            for cipher in scan_result.accepted_cipher_list:
                print(C + '    {}'.format(cipher.name))
            print('')
            data = "TLS 1.0 :> " + str(scan_result.accepted_cipher_list)
            save_data(database, module, lvl1, lvl2, lvl3, name, data)

            command = Tlsv11ScanCommand()
            scan_result = scanner.run_scan_command(server_info, command)
            print(G + " [+] Available TLS v1.1 Ciphers:" + color.TR2 + C)
            for cipher in scan_result.accepted_cipher_list:
                print(C + '    {}'.format(cipher.name))
            print('')
            data = "TLS 1.1 :> " + str(scan_result.accepted_cipher_list)
            save_data(database, module, lvl1, lvl2, lvl3, name, data)

            command = Tlsv12ScanCommand()
            scan_result = scanner.run_scan_command(server_info, command)
            print(G + " [+] Available TLS v1.2 Ciphers:" + color.TR2 + C)
            for cipher in scan_result.accepted_cipher_list:
                print(C + '    {}'.format(cipher.name))
            print('')
            data = "TLS 1.2 :> " + str(scan_result.accepted_cipher_list)
            save_data(database, module, lvl1, lvl2, lvl3, name, data)

            command = CertificateInfoScanCommand()
            scan_result = scanner.run_scan_command(server_info, command)
            print(G + ' [+] Certificate Information:' + color.TR2 + C)
            for entry in scan_result.as_text():
                if entry != '':
                    if 'certificate information' in entry.lower():
                        pass
                    elif ':' in entry:
                        print(GR + '    [+] ' +
                              entry.strip().split(':', 1)[0].strip() + ' : ' +
                              C + entry.strip().split(':', 1)[1].strip())
                    else:
                        print(C + '\n  [+] ' + entry.strip())
            print('')
            data = "Cert Info :> " + str(scan_result.as_text())
            save_data(database, module, lvl1, lvl2, lvl3, name, data)

            command = HttpHeadersScanCommand()
            scan_result = scanner.run_scan_command(server_info, command)
            print(G + ' [+] HTTP Results:' + C + color.TR2 + C)
            for entry in scan_result.as_text():
                if 'http security' not in entry.strip().lower(
                ) and entry != '':
                    if '-' in entry:
                        print(GR + '    [+] ' +
                              entry.split('-', 1)[0].strip() + ' - ' + C +
                              entry.split('-', 1)[1].strip())
                    elif ':' in entry:
                        print(GR + '    [+] ' +
                              entry.strip().split(':', 1)[0].strip() + ' : ' +
                              C + entry.strip().split(':', 1)[1].strip())
                    else:
                        print(C + '\n  [+] ' + entry.strip())
            print('')
            data = "HTTP :> " + str(scan_result.as_text())
            save_data(database, module, lvl1, lvl2, lvl3, name, data)

        except Exception as e:
            print(R + ' [-] Unhandled SSL Runtime Exception : ' + str(e))
            pass

    except requests.exceptions.SSLError as e:
        print(R + ' [-] Distant Server SSL not working : ' + str(e))

    print(G + ' [+] SSlScan Module Completed!' + C + color.TR2 + C)
Пример #49
0
def check( hostname_user_input):
    try:
        print(u'hostname_user_input: '+hostname_user_input)

        # Strip http(s)
        m = re.search('^(https?://)?(.*?)(/.*)?$', hostname_user_input)
        if m.group(2):
            hostname_user_input = m.group(2)
        else:
            raise RuntimeError(u'Please provide non-empty host name!')

        server_tester = ServerConnectivityTester(hostname_user_input)
        server_info = server_tester.perform(network_timeout=10)
    # Could not establish an SSL connection to the server
    except ServerConnectivityError as e:
        raise RuntimeError(u'Error when connecting to {}: {}!'.format(hostname_user_input, e.error_message))
    # No SSL used
    except IOError as e:
        raise RuntimeError(u'Protocol does not use SSL/TLS!')
    
    # If the call to test_connectivity_to_server() returns successfully, the server_info is then ready to be used for scanning the server.
    
    # The ConcurrentScanner uses a pool of processes to run ScanCommands concurrently. 
    # It is very fast when scanning a large number of servers, and it has a dispatching mechanism to avoid DOS-ing a single server against which multiple ScanCommand are run at the same time.
    # The commands can be queued using the queue_scan_command() method, and the results can later be retrieved using the get_results() method:
    # Ref: https://nabla-c0d3.github.io/sslyze/documentation/running-scan-commands.html
    concurrent_scanner = ConcurrentScanner()
    
    # Put scans in queue - Put desired scans here
    # ROBOT
    concurrent_scanner.queue_scan_command(server_info, RobotScanCommand())
    
    # Heartbleed
    concurrent_scanner.queue_scan_command(server_info, HeartbleedScanCommand())
    
    # Detecting deprecated/weak ciphers
    concurrent_scanner.queue_scan_command(server_info, Sslv20ScanCommand())
    concurrent_scanner.queue_scan_command(server_info, Sslv30ScanCommand())
    concurrent_scanner.queue_scan_command(server_info, Tlsv10ScanCommand())
    concurrent_scanner.queue_scan_command(server_info, Tlsv11ScanCommand())
    concurrent_scanner.queue_scan_command(server_info, Tlsv12ScanCommand())
    concurrent_scanner.queue_scan_command(server_info, Tlsv13ScanCommand())
    concurrent_scanner.queue_scan_command(server_info, CompressionScanCommand())

    # Process the results
    robot_txt = 'Scan could not be executed'
    heartbleed_txt = 'Scan could not be executed'
    drown_txt = 'Scan could not be executed'
    poodle_txt = 'Scan could not be executed'
    beast_txt = 'Scan could not be executed'
    compression_text = 'Scan could not be executed'
    lucky_text = 'Scan could not be executed'
    potential_weak_ciphers = set()

    print(u'\nProcessing results...')
    for scan_result in concurrent_scanner.get_results():
        # Sometimes a scan command can unexpectedly fail (as a bug); it is returned as a PluginRaisedExceptionResult
        if isinstance(scan_result, PluginRaisedExceptionScanResult):
            raise RuntimeError(u'Scan command failed: Scan could not be executed!')
            continue

        # Each scan result has attributes with the information you're looking for, specific to each scan command
        # All these attributes are documented within each scan command's module
        if isinstance(scan_result.scan_command, RobotScanCommand):
            result_enum = scan_result.robot_result_enum
            if result_enum == RobotScanResultEnum.VULNERABLE_STRONG_ORACLE:
                robot_txt = 'Vulnerable - Strong oracle, a real attack is possible'

            elif result_enum == RobotScanResultEnum.VULNERABLE_WEAK_ORACLE:
                robot_txt = 'Vulnerable - Weak oracle, the attack would take too long'

            elif result_enum == RobotScanResultEnum.NOT_VULNERABLE_NO_ORACLE:
                robot_txt = 'Not vulnerable'

            elif result_enum == RobotScanResultEnum.NOT_VULNERABLE_RSA_NOT_SUPPORTED:
                robot_txt = 'Not vulnerable, RSA cipher suites not supported'

            elif result_enum == RobotScanResultEnum.UNKNOWN_INCONSISTENT_RESULTS:
                robot_txt = 'Unknown - Received inconsistent results'

        # Process CRIME
        elif isinstance(scan_result.scan_command, CompressionScanCommand):
            compression_text = "Vulnerable"
            result_compression = scan_result.compression_name
            if "None" == str(result_compression):
                compression_text = "Not vulnerable"

        # Process Heartbleed    
        elif isinstance(scan_result.scan_command, HeartbleedScanCommand):
            result_heartbleed = scan_result.is_vulnerable_to_heartbleed
            heartbleed_txt = 'Not vulnerable'
            if result_heartbleed == True:
                heartbleed_txt = 'Vulnerable'
                
        # Process POODLE
        elif isinstance(scan_result.scan_command, Sslv30ScanCommand):
            poodle_txt = 'Not vulnerable'
            for cipher in scan_result.accepted_cipher_list:
                potential_weak_ciphers.add(cipher.name)
                if 'CBC' in cipher.name:
                    poodle_txt = 'Vulnerable'
                    beast_txt = "Not mitigated on server-side"
                               
        
        # Process DROWN (a server is vulnerable to DROWN if it allows SSLv2 connections) Ref = https://drownattack.com/
        elif isinstance(scan_result.scan_command, Sslv20ScanCommand):
            drown_txt = 'Not vulnerable'
            for cipher in scan_result.accepted_cipher_list:
                potential_weak_ciphers.add(cipher.name)
                drown_txt = 'Vulnerable'
                if 'CBC' in cipher.name:
                    beast_txt = "Not mitigated on server-side"

                
        # Collect deprecated/weak ciphers
        elif isinstance(scan_result.scan_command, Tlsv10ScanCommand):
            beast_txt = "Not vulnerable"
            for cipher in scan_result.accepted_cipher_list:
                potential_weak_ciphers.add(cipher.name)
                if 'CBC' in cipher.name:
                    beast_txt = "Not mitigated on server-side"

        ## Check for tls version and ciphers not sufficient to detect lucky13 vulnerability
        elif isinstance(scan_result.scan_command, Tlsv11ScanCommand):
            #if lucky_text != 'Vulnerable':
            #    lucky_text = 'Not vulnerable'
            for cipher in scan_result.accepted_cipher_list:
                potential_weak_ciphers.add(cipher.name)
            #     if 'CBC' in cipher.name:
            #         lucky_text = 'Vulnerable'

        elif isinstance(scan_result.scan_command, Tlsv12ScanCommand):
            #if lucky_text != 'Vulnerable':
            #    lucky_text = 'Not vulnerable'
            for cipher in scan_result.accepted_cipher_list:
                potential_weak_ciphers.add(cipher.name)
            #    if 'CBC' in cipher.name:
            #        lucky_text = 'Vulnerable'

        elif isinstance(scan_result.scan_command, Tlsv13ScanCommand):
            for cipher in scan_result.accepted_cipher_list:
                potential_weak_ciphers.add(cipher.name)
        
    
    # Process weak ciphers
    weak_ciphers = getWeakCiphers(potential_weak_ciphers)
    print("potential_weak_ciphers:")
    print(potential_weak_ciphers)
    print("\nweak_ciphers:")
    print(weak_ciphers)

    
    res = collections.OrderedDict()
    res["BEAST"] = str(beast_txt)
    res["CRIME"] = str(compression_text)
    res["DROWN"] = str(drown_txt)
    res["HEARTBLEED"] = str(heartbleed_txt)
    res["POODLE"] = str(poodle_txt)
    res["ROBOT"] = str(robot_txt)
    res["WEAKCIPHERS"] = 'Not vulnerable' if len(weak_ciphers) == 0 else '\n'.join(str(s) for s in weak_ciphers)
    #res["LUCKY13"] = str(lucky_text)


    details = getCertiDetails(hostname_user_input, potential_weak_ciphers)
    return (res, details)
def sslyzeScan(threadname, connection, url):

    logfile_connection = 'log/' + scriptname + '-error-connections.log'
    logfile_other = 'log/' + scriptname + '-error-other.log'
    logfile_scan = 'log/' + scriptname + '-error-other.log'

    has_ip = 0
    is_reachable = 0

    has_ip = getIP(url)

    if has_ip:
        try:
            server_tester = ServerConnectivityTester(hostname=url)
            server_info = server_tester.perform()
            is_reachable = 1
        except ServerConnectivityError:
            with open(logfile_connection, 'a') as log:
                log.write('Error, ' + time.strftime("%Y-%m-%d %H:%M:%S") +
                          ', ' + threadname + ': Could not connect to host: ' +
                          url + '\n')
        except Exception:
            with open(logfile_other, 'a') as log:
                log.write('Error, ' + time.strftime("%Y-%m-%d %H:%M:%S") +
                          ', ' + threadname + ': Thrown error for host: ' +
                          url + '\n')
    else:
        with open(logfile_connection, 'a') as log:
            log.write('Error, ' + time.strftime("%Y-%m-%d %H:%M:%S") + ', ' +
                      threadname + ': Could not resolve host: ' + url + '\n')

    if (is_reachable):
        concurrent_scanner = ConcurrentScanner()
        concurrent_scanner.queue_scan_command(server_info, Sslv20ScanCommand())
        concurrent_scanner.queue_scan_command(server_info, Sslv30ScanCommand())
        concurrent_scanner.queue_scan_command(server_info, Tlsv10ScanCommand())
        concurrent_scanner.queue_scan_command(server_info, Tlsv11ScanCommand())
        concurrent_scanner.queue_scan_command(server_info, Tlsv12ScanCommand())
        concurrent_scanner.queue_scan_command(server_info, Tlsv13ScanCommand())
        concurrent_scanner.queue_scan_command(server_info,
                                              HeartbleedScanCommand())
        concurrent_scanner.queue_scan_command(server_info,
                                              HttpHeadersScanCommand())
        concurrent_scanner.queue_scan_command(server_info,
                                              CertificateInfoScanCommand())

        # Process the results
        for scan_result in concurrent_scanner.get_results():

            # Sometimes a scan command can unexpectedly fail (as a bug); it is returned as a PluginRaisedExceptionResult
            if isinstance(scan_result, PluginRaisedExceptionScanResult):
                with open(logfile_scan, 'a') as log:
                    log.write('Error, ' + time.strftime("%Y-%m-%d %H:%M:%S") +
                              ', Scan command failed: {}'.format(
                                  scan_result.as_text()) + '\n')

            if isinstance(scan_result.scan_command, Sslv20ScanCommand):
                ssl_version = "sslv2"
                try:
                    if len(scan_result.accepted_cipher_list) == 0:
                        supports_sslv2 = 0
                    else:
                        supports_sslv2 = 1
                        for cipher in scan_result.accepted_cipher_list:
                            cipher = (u'{}'.format(cipher.name))
                            sql_command = (
                                'insert into ' + tbl_supported_ciphers +
                                '(url,cipher,version) values (%s,%s,%s)')
                            sql_data = (url, cipher, ssl_version)
                            cur0 = connection.cursor()
                            cur0.execute(sql_command, sql_data)
                            connection.commit()
                            cur0.close()
                except AttributeError:
                    with open(logfile_scan, 'a') as log:
                        log.write(
                            'Error, ' + time.strftime("%Y-%m-%d %H:%M:%S") +
                            ', ' + threadname +
                            ': Could not get sslv2 attributes for host: ' +
                            url + '\n')
                    supports_sslv2 = 0

            if isinstance(scan_result.scan_command, Sslv30ScanCommand):
                ssl_version = "sslv3"
                try:
                    if len(scan_result.accepted_cipher_list) == 0:
                        supports_sslv3 = 0
                    else:
                        supports_sslv3 = 1
                        for cipher in scan_result.accepted_cipher_list:
                            cipher = (u'{}'.format(cipher.name))
                            sql_command = (
                                'insert into ' + tbl_supported_ciphers +
                                '(url,cipher,version) values (%s,%s,%s)')
                            sql_data = (url, cipher, ssl_version)
                            cur0 = connection.cursor()
                            cur0.execute(sql_command, sql_data)
                            connection.commit()
                            cur0.close()
                except AttributeError:
                    with open(logfile_scan, 'a') as log:
                        log.write(
                            'Error, ' + time.strftime("%Y-%m-%d %H:%M:%S") +
                            ', ' + threadname +
                            ': Could not get sslv3 attributes for host: ' +
                            url + '\n')
                    supports_sslv3 = 0

            if isinstance(scan_result.scan_command, Tlsv10ScanCommand):
                ssl_version = "tlsv10"
                try:
                    if len(scan_result.accepted_cipher_list) == 0:
                        supports_tlsv10 = 0
                    else:
                        supports_tlsv10 = 1
                        for cipher in scan_result.accepted_cipher_list:
                            cipher = (u'{}'.format(cipher.name))
                            sql_command = (
                                'insert into ' + tbl_supported_ciphers +
                                '(url,cipher,version) values (%s,%s,%s)')
                            sql_data = (url, cipher, ssl_version)
                            cur0 = connection.cursor()
                            cur0.execute(sql_command, sql_data)
                            connection.commit()
                            cur0.close()
                except AttributeError:
                    with open(logfile_scan, 'a') as log:
                        log.write(
                            'Error, ' + time.strftime("%Y-%m-%d %H:%M:%S") +
                            ', ' + threadname +
                            ': Could not get tlsv10 attributes for host: ' +
                            url + '\n')
                    supports_tlsv10 = 0

            if isinstance(scan_result.scan_command, Tlsv11ScanCommand):
                ssl_version = "tlsv11"
                try:
                    if len(scan_result.accepted_cipher_list) == 0:
                        supports_tlsv11 = 0
                    else:
                        supports_tlsv11 = 1
                        for cipher in scan_result.accepted_cipher_list:
                            cipher = (u'{}'.format(cipher.name))
                            sql_command = (
                                'insert into ' + tbl_supported_ciphers +
                                '(url,cipher,version) values (%s,%s,%s)')
                            sql_data = (url, cipher, ssl_version)
                            cur0 = connection.cursor()
                            cur0.execute(sql_command, sql_data)
                            connection.commit()
                            cur0.close()
                except AttributeError:
                    with open(logfile_scan, 'a') as log:
                        log.write(
                            'Error, ' + time.strftime("%Y-%m-%d %H:%M:%S") +
                            ', ' + threadname +
                            ': Could not get tlsv11 attributes for host: ' +
                            url + '\n')
                    supports_tlsv11 = 0

            if isinstance(scan_result.scan_command, Tlsv12ScanCommand):
                ssl_version = "tlsv12"
                try:
                    if len(scan_result.accepted_cipher_list) == 0:
                        supports_tlsv12 = 0
                    else:
                        supports_tlsv12 = 1
                        for cipher in scan_result.accepted_cipher_list:
                            cipher = (u'{}'.format(cipher.name))
                            sql_command = (
                                'insert into ' + tbl_supported_ciphers +
                                '(url,cipher,version) values (%s,%s,%s)')
                            sql_data = (url, cipher, ssl_version)
                            cur0 = connection.cursor()
                            cur0.execute(sql_command, sql_data)
                            connection.commit()
                            cur0.close()
                except AttributeError:
                    with open(logfile_scan, 'a') as log:
                        log.write(
                            'Error, ' + time.strftime("%Y-%m-%d %H:%M:%S") +
                            ', ' + threadname +
                            ': Could not get tlsv12 attributes for host: ' +
                            url + '\n')
                    supports_tlsv12 = 0

            if isinstance(scan_result.scan_command, Tlsv13ScanCommand):
                ssl_version = "tlsv13"
                try:
                    if len(scan_result.accepted_cipher_list) == 0:
                        supports_tlsv13 = 0
                    else:
                        supports_tlsv13 = 1
                        for cipher in scan_result.accepted_cipher_list:
                            cipher = (u'{}'.format(cipher.name))
                            sql_command = (
                                'insert into ' + tbl_supported_ciphers +
                                '(url,cipher,version) values (%s,%s,%s)')
                            sql_data = (url, cipher, ssl_version)
                            cur0 = connection.cursor()
                            cur0.execute(sql_command, sql_data)
                            connection.commit()
                            cur0.close()
                except AttributeError:
                    with open(logfile_scan, 'a') as log:
                        log.write(
                            'Error, ' + time.strftime("%Y-%m-%d %H:%M:%S") +
                            ', ' + threadname +
                            ': Could not get tlsv13 attributes for host: ' +
                            url + '\n')
                    supports_tlsv13 = 0

            if isinstance(scan_result.scan_command, HeartbleedScanCommand):
                vulnerable_heartbleed = 0
                try:
                    if (scan_result.is_vulnerable_to_heartbleed):
                        vulnerable_heartbleed = 1
                except AttributeError:
                    with open(logfile_scan, 'a') as log:
                        log.write(
                            'Error, ' + time.strftime("%Y-%m-%d %H:%M:%S") +
                            ', ' + threadname +
                            ': Could not get heartbleed attribute for host: ' +
                            url + '\n')
                    vulnerable_heartbleed = 0

            if isinstance(scan_result.scan_command, HttpHeadersScanCommand):
                hsts_preload_set = 0
                hsts_include_subdomains_set = 0
                hsts_max_age_set = 0
                hsts_supported = 0
                hpkp_supported = 0

                try:
                    if (scan_result.hsts_header):
                        hsts_supported = 1
                        if (scan_result.hsts_header.preload):
                            hsts_preload_set = 1
                        if (scan_result.hsts_header.include_subdomains
                            ) == True:
                            hsts_include_subdomains_set = 1
                        hsts_max_age_set = scan_result.hsts_header.max_age
                except AttributeError:
                    with open(logfile_scan, 'a') as log:
                        log.write(
                            'Error, ' + time.strftime("%Y-%m-%d %H:%M:%S") +
                            ', ' + threadname +
                            ': Could not get hsts attributes for host: ' +
                            url + '\n')
                    hsts_preload_set = 0
                    hsts_include_subdomains_set = 0
                    hsts_max_age_set = 0
                    hsts_supported = 0

                try:
                    if (scan_result.hpkp_header):
                        hpkp_supported = 1
                except AttributeError:
                    hpkp_supported = 0

            if isinstance(scan_result.scan_command,
                          CertificateInfoScanCommand):
                chain_is_trusted = 0
                try:
                    if (scan_result.verified_certificate_chain):
                        chain_is_trusted = 1
                except AttributeError:
                    with open(logfile_scan, 'a') as log:
                        log.write(
                            'Error, ' + time.strftime("%Y-%m-%d %H:%M:%S") +
                            ', ' + threadname +
                            ': Could not get hpkp attributes for host: ' +
                            url + '\n')
                    chain_is_trusted = 0

                cert_matches_hostname = 0
                cert_is_ev = False
                try:
                    CertificateUtils.matches_hostname(
                        scan_result.certificate_chain[0],
                        server_info.tls_server_name_indication)
                    cert_matches_hostname = 1
                except CertificateError:
                    cert_matches_hostname = 0
                except AttributeError:
                    with open(logfile_scan, 'a') as log:
                        log.write(
                            'Error, ' + time.strftime("%Y-%m-%d %H:%M:%S") +
                            ', ' + threadname +
                            ': Could not get certificate_chain attribute for host: '
                            + url + '\n')
                try:
                    cert_is_ev = TrustStoresRepository.get_default(
                    ).get_main_store().is_extended_validation(
                        scan_result.certificate_chain[0])
                except AttributeError:
                    with open(logfile_scan, 'a') as log:
                        log.write(
                            'Error, ' + time.strftime("%Y-%m-%d %H:%M:%S") +
                            ', ' + threadname +
                            ': Could not get extended_validation attribute for host: '
                            + url + '\n')

        sql_cmd = (
            'insert into ' + tbl_ssl_options +
            '(url,heartbleed_vulnerable,hsts_supported,hsts_preload_set,hsts_include_subdomains_set,hsts_max_age_set,hpkp_supported,chain_is_trusted,match_hostname,is_ev,sslv2,sslv3,tlsv10,tlsv11,tlsv12,tlsv13) values (%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)'
        )
        sql_dat = (url, vulnerable_heartbleed, hsts_supported,
                   hsts_preload_set, hsts_include_subdomains_set,
                   hsts_max_age_set, hpkp_supported, chain_is_trusted,
                   cert_matches_hostname, cert_is_ev, supports_sslv2,
                   supports_sslv3, supports_tlsv10, supports_tlsv11,
                   supports_tlsv12, supports_tlsv13)
        cur = connection.cursor()
        cur.execute(sql_cmd, sql_dat)
        connection.commit()
        cur.close()
Пример #51
0
def attack_host(results, host_name):
    print("Running forward_secrecy_attack.py host name: {}".format(host_name))
    expected_tls1_2_suites = ['TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384', 'TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256']

    try:
        server_tester = ServerConnectivityTester(
            hostname=host_name,
            port=443,
            tls_wrapped_protocol=TlsWrappedProtocolEnum.HTTPS)

        server_info = server_tester.perform()
    except ServerConnectivityError as e:
        results.append(AttackResult('10.13', host_name, False, e))
        return

    synchronous_scanner = SynchronousScanner()

    tls1_3_scan_result = synchronous_scanner.run_scan_command(server_info, Tlsv13ScanCommand())
    tls1_3_accepted_ciphers = tls1_3_scan_result.accepted_cipher_list

    tls1_2_scan_result = synchronous_scanner.run_scan_command(server_info, Tlsv12ScanCommand())
    tls1_2_accepted_ciphers = tls1_2_scan_result.accepted_cipher_list
    tls1_2_accepted_cipher_names = cipher_list_to_string_list(tls1_2_accepted_ciphers)

    tls1_1_scan_result = synchronous_scanner.run_scan_command(server_info, Tlsv11ScanCommand())
    tls1_1_accepted_ciphers = tls1_1_scan_result.accepted_cipher_list

    tls1_0_scan_result = synchronous_scanner.run_scan_command(server_info, Tlsv10ScanCommand())
    tls1_0_accepted_ciphers = tls1_0_scan_result.accepted_cipher_list

    ssl3_0_scan_result = synchronous_scanner.run_scan_command(server_info, Sslv30ScanCommand())
    ssl3_0_accepted_ciphers = ssl3_0_scan_result.accepted_cipher_list

    ssl2_0_scan_result = synchronous_scanner.run_scan_command(server_info, Sslv20ScanCommand())
    ssl2_0_accepted_ciphers = ssl2_0_scan_result.accepted_cipher_list

    # Determine result
    result = list_equal(tls1_2_accepted_cipher_names, expected_tls1_2_suites) and \
        len(tls1_3_accepted_ciphers) == 0 and \
        len(tls1_1_accepted_ciphers) == 0 and \
        len(tls1_0_accepted_ciphers) == 0 and \
        len(ssl3_0_accepted_ciphers) == 0 and \
        len(ssl3_0_accepted_ciphers) == 0

    # Build details
    details = ''
    if len(tls1_3_accepted_ciphers) != 0:
        details += 'TLS 1.3 should not be supported '

    if not list_equal(tls1_2_accepted_cipher_names, expected_tls1_2_suites):
        details += ' TLS 1.2 supporting ' + str(tls1_2_accepted_cipher_names) \
                   + ', should only be ' + str(expected_tls1_2_suites) + ' '

    if len(tls1_1_accepted_ciphers) != 0:
        details += 'TLS 1.1 should not be supported '

    if len(tls1_0_accepted_ciphers) != 0:
        details += 'TLS 1.0 should not be supported '

    if len(ssl3_0_accepted_ciphers) != 0:
        details += 'SSL 3.0 should not be supported '

    if len(ssl2_0_accepted_ciphers) != 0:
        details += 'SSL 2.0 should not be supported '

    if details == '':
        details = 'Cipher suites are correct'

    results.append(AttackResult('forward_secrecy', host_name, result, details))


# attack_host([], 'google.co.uk')
Пример #52
0
def init_sslyze(hostname, port, starttls_smtp, options, sync=False):
    global network_timeout, CA_FILE

    network_timeout = int(options.get("network_timeout", network_timeout))
    if options.get('ca_file'):
        CA_FILE = options['ca_file']

    tls_wrapped_protocol = TlsWrappedProtocolEnum.PLAIN_TLS
    if starttls_smtp:
        tls_wrapped_protocol = TlsWrappedProtocolEnum.STARTTLS_SMTP

    try:
        # logging.debug("\tTesting connectivity with timeout of %is." % network_timeout)
        server_tester = ServerConnectivityTester(
            hostname=hostname,
            port=port,
            tls_wrapped_protocol=tls_wrapped_protocol)
        server_info = server_tester.perform(network_timeout=network_timeout)
    except ServerConnectivityError:
        # Usually pshtt has already established that we can connect to the site, so let's try again a couple of times
        try:
            logging.debug(
                "\t{}:{} Server connectivity check failed. Trying again...".
                format(hostname, port))
            time.sleep(10)
            server_tester = ServerConnectivityTester(
                hostname=hostname,
                port=port,
                tls_wrapped_protocol=tls_wrapped_protocol)
            server_info = server_tester.perform(
                network_timeout=(network_timeout * 2))
        except Exception as err:
            try:
                logging.debug(
                    "\t{}:{} Server connectivity check failed. Trying again..."
                    .format(hostname, port))
                time.sleep(30)
                server_tester = ServerConnectivityTester(
                    hostname=hostname,
                    port=port,
                    tls_wrapped_protocol=tls_wrapped_protocol)
                server_info = server_tester.perform(
                    network_timeout=(network_timeout * 2))
            except Exception as err:
                logging.warning(
                    "\t{}:{} Server connectivity not established during test.".
                    format(hostname, port))
                return None, None
    except dns.exception.DNSException as err:
        logging.warning(
            "\t{}:{} DNS exception when performing sslyze server connectivity info check."
            .format(hostname, port))
        logging.debug("\t:{}:{} DNS exception: {}".format(hostname, port, err))
        return None, None
    except Exception as err:
        utils.notify(err)
        logging.warning(
            "\t{}:{} Unknown exception when performing server connectivity info."
            .format(hostname, port))
        return None, None

    if sync:
        scanner = SynchronousScanner(network_timeout=network_timeout)
    else:
        scanner = ConcurrentScanner(network_timeout=network_timeout)

    return server_info, scanner