예제 #1
0
def basic_example() -> None:
    # Define the server that you want to scan
    server_location = ServerNetworkLocationViaDirectConnection.with_ip_address_lookup("www.google.com", 443)

    # Do connectivity testing to ensure SSLyze is able to connect
    try:
        server_info = ServerConnectivityTester().perform(server_location)
    except ConnectionToServerFailed as e:
        # Could not connect to the server; abort
        print(f"Error connecting to {server_location}: {e.error_message}")
        return

    # Then queue some scan commands for the server
    scanner = Scanner()
    server_scan_req = ServerScanRequest(
        server_info=server_info, scan_commands={ScanCommand.CERTIFICATE_INFO, ScanCommand.SSL_2_0_CIPHER_SUITES},
    )
    scanner.start_scans([server_scan_req])

    # Then retrieve the results
    for server_scan_result in scanner.get_results():
        print(f"\nResults for {server_scan_result.server_info.server_location.hostname}:")

        # SSL 2.0 results
        ssl2_result = server_scan_result.scan_commands_results[ScanCommand.SSL_2_0_CIPHER_SUITES]
        print("\nAccepted cipher suites for SSL 2.0:")
        for accepted_cipher_suite in ssl2_result.accepted_cipher_suites:
            print(f"* {accepted_cipher_suite.cipher_suite.name}")

        # Certificate info results
        certinfo_result = server_scan_result.scan_commands_results[ScanCommand.CERTIFICATE_INFO]
        print("\nCertificate info:")
        for cert_deployment in certinfo_result.certificate_deployments:
            print(f"Leaf certificate: \n{cert_deployment.received_certificate_chain_as_pem[0]}")
    def test_invalid_certificate_bad_name(self, certificate_name_field):
        # Given a server to scan
        server_location = ServerNetworkLocationViaDirectConnection.with_ip_address_lookup(
            "www.cloudflare.com", 443)
        server_info = ServerConnectivityTester().perform(server_location)

        # And the server has a certificate with an invalid Subject field
        with mock.patch.object(
                hazmat.backends.openssl.x509._Certificate,
                certificate_name_field,
                new_callable=PropertyMock) as mock_certificate_name:
            # https://github.com/nabla-c0d3/sslyze/issues/495
            mock_certificate_name.side_effect = ValueError(
                "Country name must be a 2 character country code")

            # When running the scan, it succeeds
            scan_result = CertificateInfoImplementation.scan_server(
                server_info)

            # And the result can be converted to console output
            result_as_txt = CertificateInfoImplementation.cli_connector_cls.result_to_console_output(
                scan_result)
            assert result_as_txt

            # And the result can be converted to JSON
            result_as_json = json.dumps(asdict(scan_result), cls=JsonEncoder)
            assert result_as_json
예제 #3
0
    def test_ed25519_certificate(self):
        # Given a server that is configured with an ED25519 certificate
        with ModernOpenSslServer(
                server_certificate_path=Path(__file__).parent.absolute() /
                "server-ed25519-cert.pem",
                server_key_path=Path(__file__).parent.absolute() /
                "server-ed25519-key.pem",
        ) as server:
            server_location = ServerNetworkLocationViaDirectConnection(
                hostname=server.hostname,
                port=server.port,
                ip_address=server.ip_address)
            server_info = ServerConnectivityTester().perform(server_location)

            # When running the scan, it succeeds
            scan_result = CertificateInfoImplementation.scan_server(
                server_info)
            assert scan_result.certificate_deployments[
                0].received_certificate_chain

            # And the result can be converted to JSON
            result_as_json = json.dumps(asdict(scan_result), cls=JsonEncoder)
            assert result_as_json

            # And the result can be converted to console output
            result_as_txt = CertificateInfoImplementation.cli_connector_cls.result_to_console_output(
                scan_result)
            assert result_as_txt
예제 #4
0
def main() -> None:
    # First validate that we can connect to the servers we want to scan
    servers_to_scan = []
    for hostname in ["cloudflare.com", "google.com"]:
        server_location = ServerNetworkLocationViaDirectConnection.with_ip_address_lookup(
            hostname, 443)
        try:
            server_info = ServerConnectivityTester().perform(server_location)
            servers_to_scan.append(server_info)
        except ConnectionToServerFailed as e:
            print(
                f"Error connecting to {server_location.hostname}:{server_location.port}: {e.error_message}"
            )
            return

    scanner = Scanner()

    # Then queue some scan commands for each server
    for server_info in servers_to_scan:
        server_scan_req = ServerScanRequest(
            server_info=server_info,
            scan_commands={
                ScanCommand.CERTIFICATE_INFO, ScanCommand.SSL_2_0_CIPHER_SUITES
            },
        )
        scanner.queue_scan(server_scan_req)

    # Then retrieve the result of the scan commands for each server
    for server_scan_result in scanner.get_results():
        print(
            f"\nResults for {server_scan_result.server_info.server_location.hostname}:"
        )

        # Scan commands that were run with no errors
        try:
            ssl2_result = server_scan_result.scan_commands_results[
                ScanCommand.SSL_2_0_CIPHER_SUITES]
            print(f"\nAccepted cipher suites for SSL 2.0:")
            for accepted_cipher_suite in ssl2_result.accepted_cipher_suites:
                print(f"* {accepted_cipher_suite.cipher_suite.name}")
        except KeyError:
            pass

        try:
            certinfo_result = server_scan_result.scan_commands_results[
                ScanCommand.CERTIFICATE_INFO]
            print("\nCertificate info:")
            for cert_deployment in certinfo_result.certificate_deployments:
                print(
                    f"Leaf certificate: \n{cert_deployment.received_certificate_chain_as_pem[0]}"
                )
        except KeyError:
            pass

        # Scan commands that were run with errors
        for scan_command, error in server_scan_result.scan_commands_errors.items(
        ):
            print(
                f"\nError when running {scan_command}:\n{error.exception_trace}"
            )
예제 #5
0
def basic_example_connectivity_testing() -> None:
    # Define the server that you want to scan
    server_location = ServerNetworkLocationViaDirectConnection.with_ip_address_lookup("www.google.com", 443)

    # Do connectivity testing to ensure SSLyze is able to connect
    try:
        server_info = ServerConnectivityTester().perform(server_location)
    except ConnectionToServerFailed as e:
        # Could not connect to the server; abort
        print(f"Error connecting to {server_location}: {e.error_message}")
        return
    print(f"Connectivity testing completed: {server_info}")
예제 #6
0
def scan_runner(seq,host):
    hostname=host.decode("utf-8")
    servers_to_scan = []
    server_location = None
    try:
        if r.hget(seq,"ipaddr"):
            server_location = ServerNetworkLocationViaDirectConnection(hostname, 443, r.hget(seq,"ipaddr").decode("utf-8"))
        else:
            server_location = ServerNetworkLocationViaDirectConnection.with_ip_address_lookup(hostname, 443)
            r.hset(seq,"ipaddr",server_location.ip_address)
        #Initialize with hostname, port int and ip address str 
        #print(server_location)
    except Exception as e:
        return
    try:
        server_info = ServerConnectivityTester().perform(server_location)
        servers_to_scan.append(server_info)
    except ConnectionToServerFailed as e:
        return

    scanner = Scanner()

    # Then queue some scan commands for each server
    for server_info in servers_to_scan:
        server_scan_req = ServerScanRequest(
            server_info=server_info, scan_commands={ScanCommand.TLS_1_3_EARLY_DATA},
        )
        scanner.queue_scan(server_scan_req)

    # Then retrieve the result of the scan commands for each server
    for server_scan_result in scanner.get_results():
        try:
            if server_scan_result.scan_commands_results[ScanCommand.TLS_1_3_EARLY_DATA].supports_early_data:
                r.hset(seq,"early","TRUE")

        except KeyError:
            return
예제 #7
0
def createServerConnections(ip_address, hostname, servers_to_scan, port_to_scan):
    """
    Create connections to each server in ip_list, store connection results in servers_to_scan list
    :param ip_address: IP address to connect to
    :param hostname: name of host to connect to
    :param servers_to_scan: list of open server connections
    :param port_to_scan: desired port to attempt connection with
    :return: None
    """
    server_location = ServerNetworkLocationViaDirectConnection(str(hostname), port_to_scan, ip_address)
    try:
        server_info = ServerConnectivityTester().perform(server_location)
        servers_to_scan.append(server_info)
        return "success"
    except ConnectionToServerFailed as e:
        return f"Error connecting to {server_location.hostname}:{server_location.port}: {e.error_message}"
예제 #8
0
    def test_ecdsa_certificate(self):
        # Given a server to scan that has an ECDSA certificate
        server_location = ServerNetworkLocationViaDirectConnection.with_ip_address_lookup(
            "www.cloudflare.com", 443)
        server_info = ServerConnectivityTester().perform(server_location)

        # When running the scan, it succeeds
        scan_result = CertificateInfoImplementation.scan_server(server_info)

        # And the result can be converted to JSON
        result_as_json = json.dumps(asdict(scan_result), cls=JsonEncoder)
        assert result_as_json

        # And the result can be converted to console output
        result_as_txt = CertificateInfoImplementation.cli_connector_cls.result_to_console_output(
            scan_result)
        assert result_as_txt
    def test_supported_curves(self):
        # Given a server to scan that supports ECDH cipher suites
        server_location = ServerNetworkLocationViaDirectConnection.with_ip_address_lookup(
            "www.cloudflare.com", 443)
        server_info = ServerConnectivityTester().perform(server_location)

        # When scanning for supported elliptic curves, it succeeds
        result: SupportedEllipticCurvesScanResult = SupportedEllipticCurvesImplementation.scan_server(
            server_info)

        # And the result confirms that some curves are supported and some are not
        assert result.supports_ecdh_key_exchange
        assert result.supported_curves
        assert result.rejected_curves

        # And a CLI output can be generated
        assert SupportedEllipticCurvesImplementation.cli_connector_cls.result_to_console_output(
            result)
    def test_supported_curves(self):
        # Given a server to scan that supports ECDH cipher suites with specific curves
        server_curves = [
            "X25519", "X448", "prime256v1", "secp384r1", "secp521r1"
        ]
        with ModernOpenSslServer(groups=":".join(server_curves)) as server:
            server_location = ServerNetworkLocationViaDirectConnection(
                hostname=server.hostname,
                ip_address=server.ip_address,
                port=server.port)
            server_info = ServerConnectivityTester().perform(server_location)

            # When scanning the server for supported curves, it succeeds
            result: SupportedEllipticCurvesScanResult = SupportedEllipticCurvesImplementation.scan_server(
                server_info)

        # And the supported curves were detected
        assert set(server_curves) == {
            curve.name
            for curve in result.supported_curves
        }
예제 #11
0
파일: ssl.py 프로젝트: sdfmmbi/Anubis
def search_subject_alt_name(self, target):
  print("Searching for Subject Alt Names")
  try:
    server_location = ServerNetworkLocationViaDirectConnection.with_ip_address_lookup(
      target, 443)

    # Do connectivity testing to ensure SSLyze is able to connect
    try:
      server_info = ServerConnectivityTester().perform(server_location)
    except ConnectionToServerFailed as e:
      # Could not connect to the server; abort
      print(f"Error connecting to {server_location}: {e.error_message}")
      return

    # Then queue some scan commands for the server
    scanner = Scanner()
    server_scan_req = ServerScanRequest(server_info=server_info, scan_commands={
      ScanCommand.CERTIFICATE_INFO}, )
    scanner.queue_scan(server_scan_req)
    # Then retrieve the results
    for server_scan_result in scanner.get_results():
      # Certificate info results
      certinfo_result = server_scan_result.scan_commands_results[
        ScanCommand.CERTIFICATE_INFO]

      # Direct object reference is pretty bad, but then again so is the crypto.x509 object implementation, so...
      cert_deployment = certinfo_result.certificate_deployments[0]
      chain = cert_deployment.received_certificate_chain[0]
      ext = chain.extensions.get_extension_for_oid(
        ExtensionOID.SUBJECT_ALTERNATIVE_NAME)
      for entry in ext.value.get_values_for_type(x509.DNSName):
        if entry.strip() not in self.domains:
          self.domains.append(entry.strip())

  except Exception as e:
    self.handle_exception(e)
예제 #12
0
    def parseArgsAndCheckConnectivity(self):
        if len(sys.argv) == 3 or len(sys.argv) == 4:
            if len(sys.argv) == 4:
                if sys.argv[1] == '--verbose':
                    self.verbose = True
                    self.host = sys.argv[2]
                    self.port = sys.argv[3]
                else:
                    self.printHelp()
            else:
                self.verbose = False
                self.host = sys.argv[1]
                self.port = sys.argv[2]
            try:
                print('Testing connectivity ...', end='', flush=True)
                # Define the server that you want to scan
                serverLocation = ServerNetworkLocationViaDirectConnection.with_ip_address_lookup(
                    self.host, self.port)

                # Do connectivity testing to ensure SSLyze is able to connect
                self.serverInfo = ServerConnectivityTester().perform(
                    serverLocation)
            except ConnectionToServerFailed as e:
                # Could not connect to the server; abort
                print(
                    f"Error connecting to {serverLocation}: {e.error_message}")
                sys.exit()
            except ServerHostnameCouldNotBeResolved:
                print(
                    f"Cannot resolve {self.host}, check that it is correct (IP is correct and domain does not include protocol)"
                )
                sys.exit()
            print(" COMPLETED.")
            self.highestProtocol = self.serverInfo.tls_probing_result.highest_tls_version_supported.name
        else:
            self.printHelp()
예제 #13
0
def main(server_software_running_on_localhost: WebServerSoftwareEnum) -> None:
    # Ensure the server is accessible on localhost
    server_location = ServerNetworkLocationViaDirectConnection.with_ip_address_lookup(
        "localhost", 443)
    server_info = ServerConnectivityTester().perform(server_location)

    if server_software_running_on_localhost == WebServerSoftwareEnum.APACHE2:
        # Apache2 is configured to require a client cert, and returns an error at the TLS layer if it is missing
        if server_info.tls_probing_result.client_auth_requirement != ClientAuthRequirementEnum.REQUIRED:
            raise RuntimeError(
                f"SSLyze did not detect that client authentication was required by Apache2:"
                f" {server_info.tls_probing_result.client_auth_requirement}.")
    elif server_software_running_on_localhost == WebServerSoftwareEnum.NGINX:
        # Nginx is configured to require a client cert but implements this by returning an error at the HTTP layer,
        # if the client cert is missing. This gets translated in SSLyze as "optionally" requiring a client cert
        if server_info.tls_probing_result.client_auth_requirement != ClientAuthRequirementEnum.OPTIONAL:
            raise RuntimeError(
                f"SSLyze did not detect that client authentication was required by Nginx:"
                f" {server_info.tls_probing_result.client_auth_requirement}.")
    elif server_software_running_on_localhost == WebServerSoftwareEnum.IIS:
        # IIS is not configured to require a client cert for now because I don't know how to enable this
        if server_info.tls_probing_result.client_auth_requirement != ClientAuthRequirementEnum.DISABLED:
            raise RuntimeError(
                f"SSLyze detected that client authentication was enabled by IIS:"
                f" {server_info.tls_probing_result.client_auth_requirement}.")
    else:
        raise ValueError(
            f"Unexpected value: {server_software_running_on_localhost}")

    # Queue all scan commands
    print("Starting scan.")
    scanner = Scanner()
    server_scan_req = ServerScanRequest(
        server_info=server_info,
        scan_commands=ScanCommandsRepository.get_all_scan_commands(),
    )
    scanner.queue_scan(server_scan_req)

    # Retrieve the result
    for server_scan_result in scanner.get_results():
        successful_cmds_count = len(server_scan_result.scan_commands_results)
        errored_cmds_count = len(server_scan_result.scan_commands_errors)
        print(
            f"Finished scan with {successful_cmds_count} results and {errored_cmds_count} errors."
        )

        # Crash if any scan commands triggered an error that's not due to client authentication being required
        triggered_unexpected_error = False
        for scan_command, error in server_scan_result.scan_commands_errors.items(
        ):
            if error.reason != ScanCommandErrorReasonEnum.CLIENT_CERTIFICATE_NEEDED:
                triggered_unexpected_error = True
                print(
                    f"\nError when running {scan_command}: {error.reason.name}."
                )
                if error.exception_trace:
                    exc_trace = ""
                    for line in error.exception_trace.format(chain=False):
                        exc_trace += f"       {line}"
                    print(exc_trace)

                print("\n")

        if triggered_unexpected_error:
            raise RuntimeError("The scan triggered unexpected errors")
        else:
            # The CLIENT_CERTIFICATE_NEEDED errors are expected, because of how Apache2 is configured
            print("OK: Triggered CLIENT_CERTIFICATE_NEEDED errors only.")

        # Crash if SSLyze didn't complete the scan commands that are supposed to work even when we don't provide a
        # client certificate
        if server_software_running_on_localhost == WebServerSoftwareEnum.APACHE2:
            expected_scan_command_results = {
                ScanCommand.TLS_1_3_CIPHER_SUITES,
                ScanCommand.TLS_1_2_CIPHER_SUITES,
                ScanCommand.TLS_1_1_CIPHER_SUITES,
                ScanCommand.TLS_1_0_CIPHER_SUITES,
                ScanCommand.SSL_3_0_CIPHER_SUITES,
                ScanCommand.SSL_2_0_CIPHER_SUITES,
                ScanCommand.OPENSSL_CCS_INJECTION,
                ScanCommand.HEARTBLEED,
                ScanCommand.ELLIPTIC_CURVES,
                ScanCommand.TLS_FALLBACK_SCSV,
                ScanCommand.CERTIFICATE_INFO,
                ScanCommand.TLS_COMPRESSION,
            }
        elif server_software_running_on_localhost == WebServerSoftwareEnum.NGINX:
            # With nginx, when configured to require client authentication, more scan commands work because unlike
            # Apache2, it does complete a full TLS handshake even when a client cert was not provided. It then returns
            # an error page at the HTTP layer.
            expected_scan_command_results = {
                ScanCommand.TLS_1_3_CIPHER_SUITES,
                ScanCommand.TLS_1_2_CIPHER_SUITES,
                ScanCommand.TLS_1_1_CIPHER_SUITES,
                ScanCommand.TLS_1_0_CIPHER_SUITES,
                ScanCommand.SSL_3_0_CIPHER_SUITES,
                ScanCommand.SSL_2_0_CIPHER_SUITES,
                ScanCommand.OPENSSL_CCS_INJECTION,
                ScanCommand.HEARTBLEED,
                ScanCommand.ELLIPTIC_CURVES,
                ScanCommand.TLS_FALLBACK_SCSV,
                ScanCommand.CERTIFICATE_INFO,
                ScanCommand.TLS_COMPRESSION,
                ScanCommand.SESSION_RESUMPTION,
                ScanCommand.TLS_1_3_EARLY_DATA,
                ScanCommand.HTTP_HEADERS,
                ScanCommand.SESSION_RESUMPTION_RATE,
                ScanCommand.SESSION_RENEGOTIATION,
            }
        elif server_software_running_on_localhost == WebServerSoftwareEnum.IIS:
            # With IIS, client authentication is not enabled so all scan commands should succeed
            expected_scan_command_results = ScanCommandsRepository.get_all_scan_commands(
            )  # type: ignore
        else:
            raise ValueError(
                f"Unexpected value: {server_software_running_on_localhost}")

        completed_scan_command_results = server_scan_result.scan_commands_results.keys(
        )
        if completed_scan_command_results != expected_scan_command_results:
            raise RuntimeError(
                f"SSLyze did not complete all the expected scan commands: {completed_scan_command_results}"
            )
        else:
            print("OK: Completed all the expected scan commands.")

        # Ensure the right TLS versions were detected by SSLyze as enabled
        # https://github.com/nabla-c0d3/sslyze/issues/472
        if server_software_running_on_localhost in [
                WebServerSoftwareEnum.APACHE2, WebServerSoftwareEnum.NGINX
        ]:
            # Apache and nginx are configured to only enable TLS 1.2 and TLS 1.3
            expected_enabled_tls_scan_commands = {
                ScanCommand.TLS_1_3_CIPHER_SUITES,
                ScanCommand.TLS_1_2_CIPHER_SUITES,
            }
        elif server_software_running_on_localhost == WebServerSoftwareEnum.IIS:
            # TLS 1.3 is not supported by IIS
            expected_enabled_tls_scan_commands = {
                ScanCommand.TLS_1_2_CIPHER_SUITES,
                ScanCommand.TLS_1_1_CIPHER_SUITES,
                ScanCommand.TLS_1_0_CIPHER_SUITES,
            }
        else:
            raise ValueError(
                f"Unexpected value: {server_software_running_on_localhost}")

        for ciphers_scan_cmd in expected_enabled_tls_scan_commands:
            scan_cmd_result = server_scan_result.scan_commands_results[
                ciphers_scan_cmd]  # type: ignore
            if not scan_cmd_result.accepted_cipher_suites:
                raise RuntimeError(
                    f"SSLyze did not detect {scan_cmd_result.tls_version_used.name} to be enabled on the server."
                )
            else:
                print(
                    f"OK: Scan command {ciphers_scan_cmd} detected cipher suites."
                )

        # Ensure a JSON output can be generated from the results
        json_output = _SslyzeOutputAsJson(
            server_scan_results=[server_scan_result],
            server_connectivity_errors=[],
            total_scan_time=3,
        )
        json_output_as_dict = asdict(json_output)
        json.dumps(json_output_as_dict,
                   cls=JsonEncoder,
                   sort_keys=True,
                   indent=4,
                   ensure_ascii=True)
        print("OK: Was able to generate JSON output.")
예제 #14
0
def main() -> None:
    # Ensure the server is accessible on localhost
    server_location = ServerNetworkLocationViaDirectConnection.with_ip_address_lookup("localhost", 443)
    server_info = ServerConnectivityTester().perform(server_location)

    if server_info.tls_probing_result.client_auth_requirement != ClientAuthRequirementEnum.REQUIRED:
        raise RuntimeError(
            f"SSLyze did not detect that client authentication was required by the server:"
            f" {server_info.tls_probing_result.client_auth_requirement}."
        )

    # Queue all scan commands
    print("Starting scan.")
    scanner = Scanner()
    server_scan_req = ServerScanRequest(
        server_info=server_info, scan_commands=ScanCommandsRepository.get_all_scan_commands(),
    )
    scanner.queue_scan(server_scan_req)

    # Retrieve the result
    for server_scan_result in scanner.get_results():
        successful_cmds_count = len(server_scan_result.scan_commands_results)
        errored_cmds_count = len(server_scan_result.scan_commands_errors)
        print(f"Finished scan with {successful_cmds_count} results and {errored_cmds_count} errors.")

        # Crash if any scan commands triggered an error that's not due to client authentication being required
        triggered_unexpected_error = False
        for scan_command, error in server_scan_result.scan_commands_errors.items():
            if error.reason != ScanCommandErrorReasonEnum.CLIENT_CERTIFICATE_NEEDED:
                triggered_unexpected_error = True
                print(f"\nError when running {scan_command}: {error.reason.name}.")
                if error.exception_trace:
                    exc_trace = ""
                    for line in error.exception_trace.format(chain=False):
                        exc_trace += f"       {line}"
                    print(exc_trace)

                print("\n")

        if triggered_unexpected_error:
            raise RuntimeError("The scan triggered unexpected errors")
        else:
            # The CLIENT_CERTIFICATE_NEEDED errors are expected, because of how Apache2 is configured
            print("OK: Triggered CLIENT_CERTIFICATE_NEEDED errors only.")

        # Crash if SSLyze didn't complete the scan commands that are supposed to work even when we don't provide a
        # client certificate
        expected_scan_command_results = {
            ScanCommand.TLS_1_3_CIPHER_SUITES,
            ScanCommand.TLS_1_2_CIPHER_SUITES,
            ScanCommand.TLS_1_1_CIPHER_SUITES,
            ScanCommand.TLS_1_0_CIPHER_SUITES,
            ScanCommand.SSL_3_0_CIPHER_SUITES,
            ScanCommand.SSL_2_0_CIPHER_SUITES,
            ScanCommand.OPENSSL_CCS_INJECTION,
            ScanCommand.HEARTBLEED,
            ScanCommand.ELLIPTIC_CURVES,
            ScanCommand.TLS_FALLBACK_SCSV,
            ScanCommand.CERTIFICATE_INFO,
            ScanCommand.TLS_COMPRESSION,
        }
        if server_scan_result.scan_commands_results.keys() != expected_scan_command_results:
            raise RuntimeError("SSLyze did not complete all the expected scan commands.")
        else:
            print("OK: Completed all the expected scan commands.")

        # Ensure TLS 1.2 and 1.3 were detected by SSLyze to be enabled
        # https://github.com/nabla-c0d3/sslyze/issues/472
        for ciphers_scan_cmd in [ScanCommand.TLS_1_3_CIPHER_SUITES, ScanCommand.TLS_1_2_CIPHER_SUITES]:
            scan_cmd_result = server_scan_result.scan_commands_results[ciphers_scan_cmd]  # type: ignore
            if not scan_cmd_result.accepted_cipher_suites:
                raise RuntimeError(
                    f"SSLyze did not detect {scan_cmd_result.tls_version_used.name} to be enabled on the server."
                )
            else:
                print(f"OK: Scan command {ciphers_scan_cmd} detected cipher suites.")
예제 #15
0
def scan_runner(seq, host):
    hostname = host.decode("utf-8")
    servers_to_scan = []
    server_location = None
    try:
        if r.hget(seq, "ipaddr"):
            server_location = ServerNetworkLocationViaDirectConnection(
                hostname, 443,
                r.hget(seq, "ipaddr").decode("utf-8"))
        else:
            server_location = ServerNetworkLocationViaDirectConnection.with_ip_address_lookup(
                hostname, 443)
            r.hset(seq, "ipaddr", server_location.ip_address)
        #Initialize with hostname, port int and ip address str
        #print(server_location)
    except Exception as e:
        print(e)
        r.hset(seq, "STATUS", 2)
    try:
        server_info = ServerConnectivityTester().perform(server_location)
        servers_to_scan.append(server_info)
    except ConnectionToServerFailed as e:
        if 'Probing failed' in str(e):
            r.hset(seq, "STATUS", 31)
        else:
            r.hset(seq, "STATUS", 32)
        return

    scanner = Scanner()

    # Then queue some scan commands for each server
    for server_info in servers_to_scan:
        server_scan_req = ServerScanRequest(
            server_info=server_info,
            scan_commands={
                ScanCommand.TLS_1_3_CIPHER_SUITES,
                ScanCommand.TLS_1_2_CIPHER_SUITES,
                ScanCommand.TLS_1_1_CIPHER_SUITES,
                ScanCommand.TLS_1_0_CIPHER_SUITES
            },
        )
        scanner.queue_scan(server_scan_req)

    # Then retrieve the result of the scan commands for each server
    for server_scan_result in scanner.get_results():
        try:
            tls1_3_result = server_scan_result.scan_commands_results[
                ScanCommand.TLS_1_3_CIPHER_SUITES]
            cipherstr = ""
            if tls1_3_result.accepted_cipher_suites:
                for accepted_cipher_suite in tls1_3_result.accepted_cipher_suites:
                    cipherstr = cipherstr + str(
                        accepted_cipher_suite.cipher_suite.name) + " "
                r.hset(seq, "TLS1_3", cipherstr)

            tls1_2_result = server_scan_result.scan_commands_results[
                ScanCommand.TLS_1_2_CIPHER_SUITES]
            cipherstr = ""
            if tls1_2_result.accepted_cipher_suites:
                for accepted_cipher_suite in tls1_2_result.accepted_cipher_suites:
                    cipherstr = cipherstr + str(
                        accepted_cipher_suite.cipher_suite.name) + " "
                r.hset(seq, "TLS1_2", cipherstr)

            tls1_1_result = server_scan_result.scan_commands_results[
                ScanCommand.TLS_1_1_CIPHER_SUITES]
            cipherstr = ""
            if tls1_1_result.accepted_cipher_suites:
                for accepted_cipher_suite in tls1_1_result.accepted_cipher_suites:
                    cipherstr = cipherstr + str(
                        accepted_cipher_suite.cipher_suite.name) + " "
                r.hset(seq, "TLS1_1", cipherstr)

            tls1_0_result = server_scan_result.scan_commands_results[
                ScanCommand.TLS_1_0_CIPHER_SUITES]
            cipherstr = ""
            if tls1_0_result.accepted_cipher_suites:
                for accepted_cipher_suite in tls1_0_result.accepted_cipher_suites:
                    cipherstr = cipherstr + str(
                        accepted_cipher_suite.cipher_suite.name) + " "
                r.hset(seq, "TLS1_0", cipherstr)
            r.hset(seq, "STATUS", 1)

        except KeyError:
            r.hset(seq, "STATUS", 4)

        # Scan commands that were run with errors
        for scan_command, error in server_scan_result.scan_commands_errors.items(
        ):
            r.hset(seq, "STATUS", 5)
예제 #16
0
def scan(target, ip, port, view, suite):
    """ Five inputs: web site name, ip, port
    split-dns view, and cipher suite """

    server_location = ServerNetworkLocationViaDirectConnection(
        target, port, ip)

    # This line checks to see if the host is online
    try:
        server_info = ServerConnectivityTester().perform(server_location)
    except errors.ConnectionToServerTimedOut:
        raise ConnectionError("Connection Timeout",
                              ERROR_MSG_CONNECTION_TIMEOUT(target, port))
    except errors.ConnectionToServerFailed:
        raise ConnectionError("Unknown Connection Error",
                              ERROR_MSG_UNKNOWN_CONNECTION(target, port))

    # Create a new results dictionary
    scan_output = results.new_result_set()

    # I hash the combination of hostname and ip for tracking
    key = md5((target + ip).encode("utf-8")).hexdigest()
    results.set_result(scan_output, "MD5", key)
    results.set_result(scan_output, "Target", f"{target}:{port}")
    results.set_result(scan_output, "IP", f"{ip}:{port}")
    results.set_result(scan_output, "Scan", suite)
    results.set_result(scan_output, "View", view)

    scanner = Scanner()
    server_scan_req = ServerScanRequest(server_info=server_info,
                                        scan_commands=CIPHER_SUITES.get(suite))
    scanner.queue_scan(server_scan_req)

    for result in scanner.get_results():
        for cipher_suite in CIPHER_SUITES.get(suite):
            scan_result = result.scan_commands_results[cipher_suite]

            for accepted_cipher_suite in scan_result.accepted_cipher_suites:
                if suite == "policy" and scan_result.tls_version_used.name == "TLS_1_2":
                    if (accepted_cipher_suite.cipher_suite.name
                            not in ALLOWED_TLS12_CIPHERS):
                        results.set_ciphers(
                            scan_output,
                            {
                                "Version":
                                f"{scan_result.tls_version_used.name}",
                                "Cipher":
                                f"{accepted_cipher_suite.cipher_suite.name}",
                            },
                        )
                else:
                    results.set_ciphers(
                        scan_output,
                        {
                            "Version": f"{scan_result.tls_version_used.name}",
                            "Cipher":
                            f"{accepted_cipher_suite.cipher_suite.name}",
                        },
                    )

    if len(scan_output["Results"]) == 0:
        results.set_result(scan_output, "Results", "No Policy Violations")

    return scan_output
예제 #17
0
파일: ssl.py 프로젝트: sdfmmbi/Anubis
def ssl_scan(self, target):
  print("Running SSL Scan")
  # Define the server that you want to scan
  server_location = ServerNetworkLocationViaDirectConnection.with_ip_address_lookup(
    target, 443)

  try:
    # Do connectivity testing to ensure SSLyze is able to connect
    try:
      server_info = ServerConnectivityTester().perform(server_location)
    except ConnectionToServerFailed as e:
      # Could not connect to the server; abort
      print(f"Error connecting to {server_location}: {e.error_message}")
      return

    # Then queue some scan commands for the server
    scanner = Scanner()
    server_scan_req = ServerScanRequest(server_info=server_info, scan_commands={
      ScanCommand.CERTIFICATE_INFO, ScanCommand.SSL_2_0_CIPHER_SUITES,
      ScanCommand.TLS_1_0_CIPHER_SUITES, ScanCommand.TLS_1_1_CIPHER_SUITES,
      ScanCommand.TLS_1_2_CIPHER_SUITES, ScanCommand.TLS_1_3_CIPHER_SUITES,
      ScanCommand.HEARTBLEED, ScanCommand.HTTP_HEADERS}, )
    scanner.queue_scan(server_scan_req)

    # Then retrieve the results
    for server_scan_result in scanner.get_results():
      print(
        f"\nResults for {server_scan_result.server_info.server_location.hostname}:")

      heartbleed_vuln = server_scan_result.scan_commands_results[
        ScanCommand.HEARTBLEED].is_vulnerable_to_heartbleed
      print(f"\nIs vulnerable to heartbleed? {heartbleed_vuln}")

      print("\nAccepted cipher suites for TLS 1.0:")
      for accepted_cipher_suite in server_scan_result.scan_commands_results[
        ScanCommand.TLS_1_0_CIPHER_SUITES].accepted_cipher_suites:
        print(f"* {accepted_cipher_suite.cipher_suite.name}")

      print("\nAccepted cipher suites for TLS 1.1:")
      for accepted_cipher_suite in server_scan_result.scan_commands_results[
        ScanCommand.TLS_1_1_CIPHER_SUITES].accepted_cipher_suites:
        print(f"* {accepted_cipher_suite.cipher_suite.name}")

      print("\nAccepted cipher suites for TLS 1.2:")
      for accepted_cipher_suite in server_scan_result.scan_commands_results[
        ScanCommand.TLS_1_2_CIPHER_SUITES].accepted_cipher_suites:
        print(f"* {accepted_cipher_suite.cipher_suite.name}")

      print("\nAccepted cipher suites for TLS 1.3:")
      for accepted_cipher_suite in server_scan_result.scan_commands_results[
        ScanCommand.TLS_1_3_CIPHER_SUITES].accepted_cipher_suites:
        print(f"* {accepted_cipher_suite.cipher_suite.name}")

      # SSL 2.0 results
      ssl2_result = server_scan_result.scan_commands_results[
        ScanCommand.SSL_2_0_CIPHER_SUITES]
      print("\nAccepted cipher suites for SSL 2.0:")
      for accepted_cipher_suite in ssl2_result.accepted_cipher_suites:
        print(f"* {accepted_cipher_suite.cipher_suite.name}")

      # Certificate info results
      certinfo_result = server_scan_result.scan_commands_results[
        ScanCommand.CERTIFICATE_INFO]
      print("\nCertificate info:")
      for cert_deployment in certinfo_result.certificate_deployments:
        print(
          f"Leaf certificate: \n{cert_deployment.received_certificate_chain_as_pem[0]}")

  except Exception as e:
    self.handle_exception(e, "Error running SSL scan")
    pass
예제 #18
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": []
        },
        "effective": {
            "name": "Effective",
            "sequence": 1,
            "result": []
        },
        "subject": {
            "name": "Subject",
            "sequence": 2,
            "result": []
        },
        "issuer": {
            "name": "Issuer",
            "sequence": 3,
            "result": []
        },
        "public": {
            "name": "Public key algorithm",
            "sequence": 4,
            "result": [],
        },
        "signature": {
            "name": "Signature hash algorithm",
            "sequence": 5,
            "result": [],
        },
        "before": {
            "name": "Not valid before (UTC)",
            "sequence": 6,
            "result": [],
        },
        "after": {
            "name": "Not valid after (UTC)",
            "sequence": 7,
            "result": [],
        },
        "tls1_2": {
            "name": "Accepted TLS1.2 cipher suites",
            "sequence": 8,
            "result": []
        },
        "tls1_3": {
            "name": "Accepted TLS1.3 cipher suites",
            "sequence": 9,
            "result": []
        },
        "pfs": {
            "name": "Perfect Forward Secrecy (PFS)",
            "sequence": 10,
            "result": [],
        },
        "ats": {
            "name": "App Transport Security (ATS)",
            "sequence": 11,
            "result": [],
        },
        "tls1_3_early_data": {
            "name": "Support TLS1.3 early data",
            "sequence": 12,
            "result": []
        },
        "match": {
            "name": "Leaf certificate subject matches hostname",
            "sequence": 13,
            "result": [],
        },
        "ocsp": {
            "name": "OCSP Must-Staple",
            "sequence": 14,
            "result": [],
        },
        "fallback": {
            "name": "The TLS_FALLBACK_SCSV mechanism",
            "sequence": 15,
            "result": []
        },
        "ccs": {
            "name": "The OpenSSL CCS Injection vulnerability",
            "sequence": 16,
            "result": []
        },
        "heartbleed": {
            "name": "The Heartbleed vulnerability",
            "sequence": 17,
            "result": []
        },
        "crime": {
            "name": "The CRIME vulnerability",
            "sequence": 18,
            "result": []
        },
        "robot": {
            "name": "The ROBOT vulnerability",
            "sequence": 19,
            "result": []
        },
    }

    server_location = ServerNetworkLocationViaDirectConnection.with_ip_address_lookup(
        url.netloc, 443)
    try:
        server_info = ServerConnectivityTester().perform(server_location)
    except ConnectionToServerFailed as e:
        return error_result

    scanner = Scanner()
    server_scan_req = ServerScanRequest(
        server_info,
        {
            ScanCommand.CERTIFICATE_INFO,
            ScanCommand.TLS_1_2_CIPHER_SUITES,
            ScanCommand.TLS_1_3_CIPHER_SUITES,
            ScanCommand.TLS_1_3_EARLY_DATA,
            ScanCommand.TLS_FALLBACK_SCSV,
            ScanCommand.OPENSSL_CCS_INJECTION,
            ScanCommand.HEARTBLEED,
            ScanCommand.TLS_COMPRESSION,
            ScanCommand.ROBOT,
        },
    )
    scanner.queue_scan(server_scan_req)
    for server_scan_result in scanner.get_results():
        certificate_result = server_scan_result.scan_commands_results[
            ScanCommand.CERTIFICATE_INFO]
        tls_1_2_cipher_result = server_scan_result.scan_commands_results[
            ScanCommand.TLS_1_2_CIPHER_SUITES]
        tls_1_3_cipher_result = server_scan_result.scan_commands_results[
            ScanCommand.TLS_1_3_CIPHER_SUITES]
        tls_1_3_early_result = server_scan_result.scan_commands_results[
            ScanCommand.TLS_1_3_EARLY_DATA]
        tls_fallback_result = server_scan_result.scan_commands_results[
            ScanCommand.TLS_FALLBACK_SCSV]
        ccs_result = server_scan_result.scan_commands_results[
            ScanCommand.OPENSSL_CCS_INJECTION]
        heartbleed_result = server_scan_result.scan_commands_results[
            ScanCommand.HEARTBLEED]
        crime_result = server_scan_result.scan_commands_results[
            ScanCommand.TLS_COMPRESSION]
        robot_result = server_scan_result.scan_commands_results[
            ScanCommand.ROBOT]

    for certificate_deployment in certificate_result.certificate_deployments:
        for certificate_info in certificate_deployment.received_certificate_chain:
            result_map["subject"]["result"] = [{
                "name":
                certificate_info.subject.rfc4514_string()
            }]
            result_map["issuer"]["result"] = [{
                "name":
                certificate_info.issuer.rfc4514_string()
            }]
            public_key = certificate_info.public_key()
            public_key_name = type(public_key).__name__[1:][:-9]
            if "key_size" in dir(public_key):
                result_map["public"]["result"] = [{
                    "name":
                    f"{public_key_name}{certificate_info.public_key().key_size}"
                }]
            else:
                result_map["public"]["result"] = [{"name": public_key_name}]
            result_map["signature"]["result"] = [{
                "name":
                certificate_info.signature_hash_algorithm.name.upper()
            }]
            if datetime.now(
            ) > certificate_info.not_valid_before and datetime.now(
            ) < certificate_info.not_valid_after:
                result_map["effective"]["result"] = True
            result_map["before"]["result"] = [{
                "name":
                datetime.strftime(certificate_info.not_valid_before,
                                  "%Y-%m-%d %H:%M:%S")
            }]
            result_map["after"]["result"] = [{
                "name":
                datetime.strftime(certificate_info.not_valid_after,
                                  "%Y-%m-%d %H:%M:%S")
            }]
            break
        result_map["https"]["result"] = True
        result_map["match"][
            "result"] = certificate_deployment.leaf_certificate_subject_matches_hostname
        result_map["ocsp"][
            "result"] = certificate_deployment.leaf_certificate_has_must_staple_extension
        break

    tls_1_2_cipher_list = [
        accepted_cipher_suite.cipher_suite.name for accepted_cipher_suite in
        tls_1_2_cipher_result.accepted_cipher_suites
    ]
    tls_1_3_cipher_list = [
        accepted_cipher_suite.cipher_suite.name for accepted_cipher_suite in
        tls_1_3_cipher_result.accepted_cipher_suites
    ]
    result_map["tls1_2"]["result"] = [{
        "name": tls_1_2_cipher
    } for tls_1_2_cipher in tls_1_2_cipher_list
                                      ] if tls_1_2_cipher_list else False
    result_map["tls1_3"]["result"] = [{
        "name": tls_1_3_cipher
    } for tls_1_3_cipher in tls_1_3_cipher_list
                                      ] if tls_1_3_cipher_list else False
    cipher_list = tls_1_2_cipher_list + tls_1_3_cipher_list
    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
    result_map["tls1_3_early_data"][
        "result"] = tls_1_3_early_result.supports_early_data
    result_map["fallback"][
        "result"] = tls_fallback_result.supports_fallback_scsv
    result_map["ccs"]["result"] = not ccs_result.is_vulnerable_to_ccs_injection
    result_map["heartbleed"][
        "result"] = not heartbleed_result.is_vulnerable_to_heartbleed
    result_map["crime"]["result"] = not crime_result.supports_compression
    result_map["robot"]["result"] = [{"name": robot_result.robot_result.name}]

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

    return scan_result