Exemple #1
0
def server_scanner(p):
    try:
        logger = logging.getLogger(__name__)
        logger.info("Opening file")
        server_tester = ServerConnectivityTester(hostname='localhost', port=p)
        server_info = server_tester.perform()
        scanner = SynchronousScanner()

        results = dict()
        suite_names = [
            'SSLV2 Cipher Suites', 'SSLV3 Cipher Suites',
            'TLSV1_0 Cipher Suites', 'TLSV1_1 Cipher Suites',
            'TLSV1_2 Cipher Suites', 'TLSV1_3 Cipher Suites'
        ]
        suites = [
            Sslv20ScanCommand, Sslv30ScanCommand, Tlsv10ScanCommand,
            Tlsv11ScanCommand, Tlsv12ScanCommand, Tlsv13ScanCommand
        ]

        logger.info("Scanning SSL/TLS suites, writing to ciphers.json")
        for suite_name, suite in zip(suite_names, suites):
            scan = scanner.run_scan_command(server_info, suite())
            results[suite_name] = [
                cipher.name for cipher in scan.accepted_cipher_list
            ]

        with open(filename, 'w') as outfile:
            json.dump(results, outfile)

    except ServerConnectivityError as e:
        raise RuntimeError(
            f'Could not connect to {e.server_info.hostname}: {e.error_message}'
        )
Exemple #2
0
def test_ssl_service_for_ssl_vulnerability(
        self,
        org_uuid=None,
        network_service_uuid=None,
        network_service_scan_uuid=None,
        vulnerability_name=None,
):
    """
    Test the given network service for the specified SSL vulnerability.
    :param org_uuid: The UUID of the organization to enumerate SSL vulnerabilities on behalf of.
    :param network_service_uuid: The UUID of the network service that is being scanned.
    :param network_service_scan_uuid: The UUID of the network service scan that this enumeration is
    a part of.
    :param vulnerability_name: A string representing the vulnerability to test for.
    :return: None
    """
    logger.info(
        "Now testing network service %s for SSL vulnerability %s."
        % (network_service_uuid, vulnerability_name)
    )
    command_map = get_ssl_vulnerabilities_command_map()
    ValidationHelper.validate_in(to_check=vulnerability_name, contained_by=command_map.keys())
    command = command_map[vulnerability_name]["command"]
    ip_address, port, protocol = self.get_endpoint_information(network_service_uuid)
    scanner = SynchronousScanner()
    server_info = ServerConnectivityInfo(hostname=ip_address, ip_address=ip_address, port=port)
    try:
        server_info.test_connectivity_to_server()
    except ServerConnectivityError as e:
        logger.warning(
            "ServerConnectivityError thrown when attempting to test SSL at %s:%s for %s vulnerability: %s"
            % (ip_address, port, vulnerability_name, e.message)
        )
        return
    try:
        result = scanner.run_scan_command(server_info, command())
        vuln_model = SslVulnerabilityModel.from_database_model_uuid(
            uuid=network_service_scan_uuid,
            db_session=self.db_session,
            test_errored=False,
            vuln_test_name=vulnerability_name,
        )
        vuln_model.test_results = []
        for field in command_map[vulnerability_name]["fields"]:
            vuln_model.test_results.append({
                "key": field,
                "value": getattr(result, field),
            })
        vuln_model.save(org_uuid)
    except (socket.error, OpenSSLError):
        vuln_model = SslVulnerabilityModel.from_database_model_uuid(
            uuid=network_service_scan_uuid,
            db_session=self.db_session,
            test_errored=True,
        )
        vuln_model.save(org_uuid)
    logger.info(
        "Network service %s successfully tested for SSL vulnerability %s."
        % (network_service_uuid, vulnerability_name)
    )
Exemple #3
0
def enumerate_cipher_suites_for_ssl_service(
    self,
    org_uuid=None,
    network_service_uuid=None,
    network_service_scan_uuid=None,
    order_uuid=None,
):
    """
    Enumerate all of the cipher suites that the given SSL/TLS service supports.
    :param org_uuid: The UUID of the organization to enumerate cipher suites on behalf of.
    :param network_service_uuid: The UUID of the network service that is being scanned.
    :param network_service_scan_uuid: The UUID of the network service scan that this enumeration is
    a part of.
    :return: None
    """
    logger.info(
        "Now enumerating supported cipher suites for network service %s." %
        (network_service_uuid, ))
    ip_address = self.network_service.ip_address.address
    port = self.network_service.port
    server_info = ServerConnectivityInfo(hostname=ip_address,
                                         ip_address=ip_address,
                                         port=port)
    try:
        server_info.test_connectivity_to_server()
    except ServerConnectivityError as e:
        logger.warning(
            "ServerConnectivityError thrown when attempting to inspect SSL at %s:%s: %s"
            % (ip_address, port, e.message))
        return
    scanner = SynchronousScanner()
    bulk_query = BulkElasticsearchQuery()
    network_service_scan = self.network_service_scan
    for ssl_protocol, command in get_ssl_cipher_suite_commands():
        result = scanner.run_scan_command(server_info, command())
        ssl_support_record = SslSupportModel.from_database_model(
            network_service_scan,
            ssl_version=ssl_protocol,
            supported=len(result.accepted_cipher_list) > 0,
        )
        ssl_support_record.accepted_ciphers = [
            cipher.name for cipher in result.accepted_cipher_list
        ]
        ssl_support_record.rejected_ciphers = [
            cipher.name for cipher in result.rejected_cipher_list
        ]
        ssl_support_record.errored_ciphers = [
            cipher.name for cipher in result.errored_cipher_list
        ]
        ssl_support_record.preferred_cipher = result.preferred_cipher.name if result.preferred_cipher else None
        bulk_query.add_model_for_indexing(model=ssl_support_record,
                                          index=org_uuid)
    logger.info(
        "All cipher suite information converted to Elasticsearch data. Now updating via bulk query."
    )
    bulk_query.save()
    logger.info(
        "Bulk query completed. SSL cipher suites enumerated for network service %s."
        % (network_service_uuid, ))
Exemple #4
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())
        assert plugin_result.as_text()
        assert plugin_result.as_xml()
Exemple #5
0
    def test_synchronous_scanner(self):
        server_info = ServerConnectivityInfo(hostname='www.google.com')
        server_info.test_connectivity_to_server()

        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())
Exemple #6
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())
Exemple #7
0
def scan_ssl(self, ssl_domain, scan_id, cipher_list):

    # Comparing ciphers --
    #used_ciphers = {cipher for cipher in sslyze.get("Accepted Ciphers").split(', ')}
    #bad_ciphers = list(used_ciphers - accepted_ciphers)
    #signature_algorithm = sslyze.get("Signature Algorithm", "sha1")
    #acceptable_ciphers = not bad_ciphers

    ssl_dict = {}
    ssl_dict["domain"] = ssl_domain["domain"]
    domain = ssl_domain["domain"]
    self.update_state(state="SCANNING")
    print(f'Scanning {domain} for ssl info...')
    #_install_req = subprocess.check_output("")

    try:
        server_tester = ServerConnectivityTester(
            hostname=ssl_domain["domain"],
            port=443,
            tls_wrapped_protocol=TlsWrappedProtocolEnum.PLAIN_TLS)
        print(
            f'\nTesting connectivity with {server_tester.hostname}:{server_tester.port}...'
        )
        server_info = server_tester.perform()
    except ServerConnectivityError as e:
        # Could not establish an SSL connection to the server
        raise RuntimeError(
            f'Could not connect to {e.server_info.hostname}: {e.error_message}'
        )

    _cmd = Tlsv10ScanCommand()

    synchronous_scanner = SynchronousScanner()

    scan_result = synchronous_scanner.run_scan_command(server_info, _cmd)

    i = 0
    used_ciphers = []
    for cipher in scan_result.accepted_cipher_list:
        print(f'    {cipher.name}')
        used_ciphers.append(cipher.name)
        i = i + 1

    print(f'Finished scanning {domain} for ssl info')

    bad_ciphers = []
    for cipher in used_ciphers:
        if cipher not in cipher_list:
            bad_ciphers.append(cipher)

    ssl_dict['accepted_ciphers'] = used_ciphers
    ssl_dict['bad_ciphers'] = bad_ciphers

    return ssl_dict, "ssl", scan_id
Exemple #8
0
def ciphers_scanner(server_info: ServerConnectivityInfo) -> dict:
    scanner = SynchronousScanner()
    commands = COMMANDS
    ciphers_info: dict = {}
    for command in commands:
        scan_result = scanner.run_scan_command(server_info, command)
        ciphers: list = []
        for cipher in scan_result.accepted_cipher_list:
            ciphers.append(cipher.name)
        ciphers_info[command.get_cli_argument()] = ciphers
    return ciphers_info
Exemple #9
0
    def __init__(self, priority_queue_in, queue_in, queue_out, network_retries,
                 network_timeout):
        # type: (JoinableQueue, JoinableQueue, JoinableQueue, int, int) -> None
        Process.__init__(self)
        self.priority_queue_in = priority_queue_in
        self.queue_in = queue_in
        self.queue_out = queue_out

        # The object that will actually run the scan commands
        self._synchronous_scanner = SynchronousScanner(network_retries,
                                                       network_timeout)
def get_cert(site_json):

    hostname = get_hostname(site_json['hostname'])

    try:
        server_info = ServerConnectivityInfo(hostname=hostname)
        server_info.test_connectivity_to_server()
        command = CertificateInfoScanCommand()
        synchronous_scanner = SynchronousScanner()
        scan_result = synchronous_scanner.run_scan_command(server_info, command)
    except ServerConnectivityError:
        return None

    return scan_result
Exemple #11
0
def check_tcp_service_for_ssl_protocol_cipher_support(
        self,
        org_uuid=None,
        service_uuid=None,
        ssl_protocol=None,
        scan_uuid=None
):
    """
    Check to see what ciphers this TCP service supports for the given SSL protocol.
    :param org_uuid: The UUID of the organization to collect information on behalf of.
    :param service_uuid: The UUID of the network service to check for SSL support.
    :param ssl_protocol: The SSL protocol to check
    :param scan_uuid: The UUID of the network service scan that this SSL version check is associated
    with.
    :return: None
    """
    ip_address, port, protocol = self.get_endpoint_information(service_uuid)
    server_info = ServerConnectivityInfo(hostname=ip_address, ip_address=ip_address, port=port)
    synchronous_scanner = SynchronousScanner()
    command = None
    if ssl_protocol == 'PROTOCOL_TLSv1' or ssl_protocol == 'PROTOCOL_TLS':
        command = Tlsv10ScanCommand()
    elif ssl_protocol == 'PROTOCOL_TLSv1_1':
        command = Tlsv11ScanCommand()
    elif ssl_protocol == 'PROTOCOL_TLSv1_2':
        command = Tlsv12ScanCommand()
    elif ssl_protocol == 'PROTOCOL_SSLv23':
        command = Sslv20ScanCommand()
    elif ssl_protocol == 'PROTOCOL_SSLv3':
        command = Sslv30ScanCommand()
    else:
        raise ValueError(
            "Not sure how to run scan command for SSL protocol of %s."
            % (ssl_protocol,)
        )
    cipher_scan_result = synchronous_scanner.run_scan_command(server_info, command)
    ssl_support_record = SslSupportModel.from_database_model_uuid(
        uuid=scan_uuid,
        db_session=self.db_session,
        ssl_version=ssl_protocol,
        supported=True,
    )
    ssl_support_record.accepted_ciphers = [ cipher.name for cipher in cipher_scan_result.accepted_cipher_list ]
    ssl_support_record.rejected_ciphers = [ cipher.name for cipher in cipher_scan_result.rejected_cipher_list ]
    ssl_support_record.errored_ciphers = [ cipher.name for cipher in cipher_scan_result.errored_cipher_list ]
    if cipher_scan_result.preferred_cipher is not None:
        ssl_support_record.preferred_cipher = cipher_scan_result.preferred_cipher.name
    else:
        ssl_support_record.preferred_cipher = None
    ssl_support_record.save(org_uuid)
Exemple #12
0
def init_sslyze(hostname, port, starttls_smtp, options, sync=False):
    global network_timeout

    network_timeout = int(options.get("network_timeout", network_timeout))

    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 as err:
        logging.warn("\tServer connectivity not established during test.")
        return None, None
    except Exception as err:
        utils.notify(err)
        logging.warn(
            "\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
Exemple #13
0
 def run_sslyze_commands(self, server_info):
     full_scan_results = {}
     synchronous_scanner = SynchronousScanner()
     full_scan_results["Cipher suites"] = self.run_cipher_suite_commands(
         server_info, synchronous_scanner)
     full_scan_results["Certificates"] = self.run_certificate_command(
         server_info, synchronous_scanner)
     full_scan_results["Compression"] = self.run_compression_command(
         server_info, synchronous_scanner)
     full_scan_results["Fallback SCSV"] = self.run_fallback_scsv_command(
         server_info, synchronous_scanner)
     full_scan_results["Heartbleed"] = self.run_heartbleed_command(
         server_info, synchronous_scanner)
     full_scan_results["Early Data"] = self.run_early_data_command(
         server_info, synchronous_scanner)
     full_scan_results[
         "CCS Injection"] = self.run_openssl_ccs_injection_command(
             server_info, synchronous_scanner)
     full_scan_results["Robot"] = self.run_robot_command(
         server_info, synchronous_scanner)
     full_scan_results[
         "Session Renegotiation"] = self.run_session_renegotiation_command(
             server_info, synchronous_scanner)
     full_scan_results[
         "Session Resumption"] = self.run_session_resumption_command(
             server_info, synchronous_scanner)
     return full_scan_results
Exemple #14
0
def get_cert_alt_names(host, port=443):
    try:
        server_tester = ServerConnectivityTester(hostname=host, port=port,
                            tls_wrapped_protocol=TlsWrappedProtocolEnum.HTTPS)
        server_info = server_tester.perform()
    except ServerConnectivityError:
        print("Impossible to connect")
        sys.exit(1)

    command = CertificateInfoScanCommand()
    synchronous_scanner = SynchronousScanner()
    scan_result = synchronous_scanner.run_scan_command(server_info, command)
    cert = scan_result.verified_certificate_chain[0]
    subj_alt_names = []
    san_ext = cert.extensions.get_extension_for_oid(ExtensionOID.SUBJECT_ALTERNATIVE_NAME)
    subj_alt_names = san_ext.value.get_values_for_type(DNSName)
    return subj_alt_names
Exemple #15
0
def scan(name, ip, view, suite):
    """ Two inputs: web site name and ip
    TODO: extend this to include port """

    try:
        server_tester = ServerConnectivityTester(
            hostname=name,
            ip_address=ip,
            port=443,
            tls_wrapped_protocol=TlsWrappedProtocolEnum.HTTPS)
        # This line checks to see if the host is online
        server_info = server_tester.perform()
        ip = server_info.ip_address
    # Could not establish an SSL connection to the server
    except ConnectionToServerTimedOut:
        error = results.set_error(f'{name}', "Connection to TCP 443 timed-out")
        return error
    except ServerConnectivityError:
        error = results.set_error(f'{name}', "Unknown Error")
        return error

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

    # I hash the combination of hostname and ip for tracking
    key = md5((f'{name}' + ip).encode("utf-8")).hexdigest()
    results.set_result(scan_output, "MD5", key)
    results.set_result(scan_output, "Hostname", f'{name}')
    results.set_result(scan_output, "IP", ip)
    results.set_result(scan_output, "View", view)

    for suite in ciphersuites.get(suite):
        synchronous_scanner = SynchronousScanner()
        scan_result = synchronous_scanner.run_scan_command(server_info, suite)

        for cipher in scan_result.accepted_cipher_list:
            results.set_ciphers(scan_output, {
                "Version": cipher.ssl_version.name,
                "Cipher": cipher.name
            })

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

    return scan_output
Exemple #16
0
    def __init__(
        self,
        domain: str,
        target_profile: str,
        ca_file: Optional[str] = None,
        cert_expire_warning: int = 15,
    ) -> None:
        """
        :param domain:
        :param target_profile: One of [old|intermediate|modern]
        :param ca_file: Path to a trusted custom root certificates in PEM format.
        :param cert_expire_warning: A warning is issued if the certificate expires in less days than specified.
        """
        self.ca_file = ca_file
        self.cert_expire_warning = cert_expire_warning

        if TLSProfiler.PROFILES is None:
            TLSProfiler.PROFILES = requests.get(self.PROFILES_URL).json()
            log.info(
                f"Loaded version {TLSProfiler.PROFILES['version']} of the Mozilla TLS configuration recommendations."
            )

        self.target_profile = TLSProfiler.PROFILES["configurations"][
            target_profile]
        self.target_profile["tls_curves"] = self._get_equivalent_curves(
            self.target_profile["tls_curves"])
        self.target_profile[
            "certificate_curves"] = self._get_equivalent_curves(
                self.target_profile["certificate_curves"])

        self.scanner = SynchronousScanner()
        try:
            server_tester = ServerConnectivityTester(hostname=domain, )
            log.info(
                f"Testing connectivity with {server_tester.hostname}:{server_tester.port}..."
            )
            self.server_info = server_tester.perform()
            self.server_error = None
        except ServerConnectivityError as e:
            # Could not establish an SSL connection to the server
            log.warning(
                f"Could not connect to {e.server_info.hostname}: {e.error_message}"
            )
            self.server_error = e.error_message
            self.server_info = None
Exemple #17
0
def scan(name, ip, port, view, suite):
    """ Five inputs: web site name, ip, port
    split-dns view, and cipher suite """

    try:
        server_tester = ServerConnectivityTester(
            hostname=name,
            ip_address=ip,
            port=port,
            tls_wrapped_protocol=TlsWrappedProtocolEnum.HTTPS)
        # This line checks to see if the host is online
        server_info = server_tester.perform()
        ip = server_info.ip_address
    # Could not establish an SSL connection to the server
    except ConnectionToServerTimedOut:
        raise ConnectionError('Connection Timeout',
                              ERROR_MSG_CONNECTION_TIMEOUT(name, port))
    except ServerConnectivityError:
        raise ConnectionError('Unknow Connection Error',
                              ERROR_MSG_UNKNOWN_CONNECTION(name, port))

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

    # I hash the combination of hostname and ip for tracking
    key = md5((f'{name}' + ip).encode("utf-8")).hexdigest()
    results.set_result(scan_output, "MD5", key)
    results.set_result(scan_output, "Hostname", f'{name}')
    results.set_result(scan_output, "IP", ip)
    results.set_result(scan_output, "View", view)

    for suite in ciphersuites.get(suite):
        synchronous_scanner = SynchronousScanner()
        scan_result = synchronous_scanner.run_scan_command(server_info, suite)

        for cipher in scan_result.accepted_cipher_list:
            results.set_ciphers(scan_output, {
                "Version": cipher.ssl_version.name,
                "Cipher": cipher.name
            })

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

    return scan_output
Exemple #18
0
def search_subject_alt_name(self, target):
  print("Searching for Subject Alt Names")
  try:
    server_info = ServerConnectivityInfo(hostname=target)
    server_info.test_connectivity_to_server()
    synchronous_scanner = SynchronousScanner()

    # Certificate information
    command = CertificateInfoScanCommand()
    scan_result = synchronous_scanner.run_scan_command(server_info, command)
    # Direct object reference is pretty bad, but then again so is the crypto.x509 object implementation, so...
    extensions = scan_result.certificate_chain[0].extensions[6]
    for entry in extensions.value:
      if entry.value.strip() not in self.domains:
        self.domains.append(entry.value.strip())

  except Exception as e:
    self.handle_exception(e)
Exemple #19
0
    def __init__(self, priority_queue_in, queue_in, queue_out, network_retries, network_timeout):
        # type: (JoinableQueue, JoinableQueue, JoinableQueue, int, int) -> None
        Process.__init__(self)
        self.priority_queue_in = priority_queue_in
        self.queue_in = queue_in
        self.queue_out = queue_out

        # The object that will actually run the scan commands
        self._synchronous_scanner = SynchronousScanner(network_retries, network_timeout)
Exemple #20
0
class WorkerProcess(Process):
    """The main process class responsible for instantiating and running the plugins.
    """

    def __init__(
        self,
        priority_queue_in: JoinableQueue,
        queue_in: JoinableQueue,
        queue_out: JoinableQueue,
        network_retries: int,
        network_timeout: int,
    ) -> None:
        Process.__init__(self)
        self.priority_queue_in = priority_queue_in
        self.queue_in = queue_in
        self.queue_out = queue_out

        # The object that will actually run the scan commands
        self._synchronous_scanner = SynchronousScanner(network_retries, network_timeout)

    def run(self) -> None:
        """The process will first complete tasks it gets from self.queue_in.
        Once it gets notified that all the tasks have been completed, it terminates.
        """
        from sslyze.concurrent_scanner import PluginRaisedExceptionScanResult

        # Start processing task in the priority queue first
        current_queue_in = self.priority_queue_in
        while True:

            task = current_queue_in.get()  # Grab a task from queue_in
            if task is None:  # All tasks have been completed
                current_queue_in.task_done()

                if current_queue_in == self.priority_queue_in:
                    # All high priority tasks have been completed; switch to low priority tasks
                    current_queue_in = self.queue_in
                    continue
                else:
                    # All the tasks have been completed; pass on the sentinel to result_queue and exit
                    self.queue_out.put(None)
                    break

            server_info, scan_command = task
            try:
                result = self._synchronous_scanner.run_scan_command(server_info, scan_command)
            except Exception as e:
                # raise
                result = PluginRaisedExceptionScanResult(server_info, scan_command, e)

            # Send the result to queue_out
            self.queue_out.put(result)
            current_queue_in.task_done()
Exemple #21
0
def demo_synchronous_scanner():
    # Run one scan command to list the server's TLS 1.0 cipher suites
    try:
        server_tester = ServerConnectivityTester(
            hostname='smtp.gmail.com',
            port=587,
            tls_wrapped_protocol=TlsWrappedProtocolEnum.STARTTLS_SMTP
        )
        print(f'\nTesting connectivity with {server_tester.hostname}:{server_tester.port}...')
        server_info = server_tester.perform()
    except ServerConnectivityError as e:
        # Could not establish an SSL connection to the server
        raise RuntimeError(f'Could not connect to {e.server_info.hostname}: {e.error_message}')

    command = Tlsv10ScanCommand()

    synchronous_scanner = SynchronousScanner()

    scan_result = synchronous_scanner.run_scan_command(server_info, command)
    for cipher in scan_result.accepted_cipher_list:
        print(f'    {cipher.name}')
Exemple #22
0
    def executePerDomainAction(self, domain):
        """
        This plugin's per-domain action is to run a barrage of sslyze certificate tests

        Params:
            domain (str)
        """
        from sslyze.plugins.certificate_info_plugin import CertificateInfoScanCommand
        from sslyze.plugins.compression_plugin import CompressionScanCommand
        from sslyze.plugins.session_renegotiation_plugin import SessionRenegotiationScanCommand
        from sslyze.server_connectivity_tester import ServerConnectivityTester
        from sslyze.server_connectivity_tester import ServerConnectivityError
        from sslyze.synchronous_scanner import SynchronousScanner
        try:
            sslyze_conn_test = ServerConnectivityTester(hostname=domain)
            sslyze_server_info = sslyze_conn_test.perform()
            sslyze_scanner = SynchronousScanner()
            sslyze_results = sslyze_scanner.run_scan_command(
                sslyze_server_info, CertificateInfoScanCommand())
            sslyze_result_lines = sslyze_results.as_text()
            for line in sslyze_result_lines:
                self.logger.info(line)
            sslyze_results = sslyze_scanner.run_scan_command(
                sslyze_server_info, SessionRenegotiationScanCommand())
            sslyze_result_lines = sslyze_results.as_text()
            for line in sslyze_result_lines:
                self.logger.info(line)
            sslyze_results = sslyze_scanner.run_scan_command(
                sslyze_server_info, CompressionScanCommand())
            sslyze_result_lines = sslyze_results.as_text()
            for line in sslyze_result_lines:
                self.logger.info(line)
        except ServerConnectivityError as e:
            # Could not establish a TLS/SSL connection to the server
            self.logger.error(
                f'sslyze ended early, could not connect to {e.server_info.hostname}: {e.error_message}'
            )
            print(
                f'sslyze ended early, could not connect to {e.server_info.hostname}: {e.error_message}'
            )
Exemple #23
0
    def test_ssl_server_headers(self, hostname, port=443):
        '''
                Uses the ServerConnectivityTester to identify host headers specific to TLS/SSL implementations to identify
                apparent security flaws with SSL/TLS implementations at the web server level.

                Currently, we can enumerate HSTS and Expect-CT Headers. HPKP is available, but is not being included because
                its being deprecated by Chrome.

                | test ssl server headers  | hostname  | port (optional |

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

            scanner = SynchronousScanner()
            result = scanner.run_scan_command(server_info,
                                              HttpHeadersScanCommand())
            logger.info("Test for HSTS Header")

            if result.hsts_header:
                preload = result.hsts_header.preload
                include_subdomains = result.hsts_header.include_subdomains
                max_age = result.hsts_header.max_age
                logger.info(
                    "\tHSTS Header with Preload: {}, Include Subdomains: {} and max_age: {}"
                    .format(preload, include_subdomains, max_age))
            else:
                logger.warn("\tNo HSTS Header found")

            logger.info("Test for Expect-CT Header")
            if result.expect_ct_header:
                logger.info("\tExpect-CT Header found: {}".format(
                    result.expect_ct_header))
            else:
                logger.warn("\tNo Expect-CT Header found.")

        except ServerConnectivityError as e:
            logger.error('Error when trying to connect to {}: {}'.format(
                e.server_info.hostname, e.error_message))
Exemple #24
0
class WorkerProcess(Process):
    """The main process class responsible for instantiating and running the plugins.
    """

    def __init__(
            self,
            priority_queue_in: JoinableQueue,
            queue_in: JoinableQueue, queue_out: JoinableQueue,
            network_retries: int,
            network_timeout: int
    ) -> None:
        Process.__init__(self)
        self.priority_queue_in = priority_queue_in
        self.queue_in = queue_in
        self.queue_out = queue_out

        # The object that will actually run the scan commands
        self._synchronous_scanner = SynchronousScanner(network_retries, network_timeout)

    def run(self) -> None:
        """The process will first complete tasks it gets from self.queue_in.
        Once it gets notified that all the tasks have been completed, it terminates.
        """
        from sslyze.concurrent_scanner import PluginRaisedExceptionScanResult

        # Start processing task in the priority queue first
        current_queue_in = self.priority_queue_in
        while True:

            task = current_queue_in.get()  # Grab a task from queue_in
            if task is None:  # All tasks have been completed
                current_queue_in.task_done()

                if current_queue_in == self.priority_queue_in:
                    # All high priority tasks have been completed; switch to low priority tasks
                    current_queue_in = self.queue_in
                    continue
                else:
                    # All the tasks have been completed; pass on the sentinel to result_queue and exit
                    self.queue_out.put(None)
                    break

            server_info, scan_command = task
            try:
                result = self._synchronous_scanner.run_scan_command(server_info, scan_command)
            except Exception as e:
                # raise
                result = PluginRaisedExceptionScanResult(server_info, scan_command, e)

            # Send the result to queue_out
            self.queue_out.put(result)
            current_queue_in.task_done()
Exemple #25
0
def concurrent_scan(site_info):
    # Setup the server to scan and ensure it is online/reachable
    server_info = server_connectivity_tester(site_info.name)

    if server_info:
        synchronous_scanner = SynchronousScanner()

        cert_info_plugin = CertificateInfoPlugin()
        plugin_result = cert_info_plugin.process_task(
            server_info, CertificateInfoScanCommand())
        #not plugin_result.verified_certificate_chain or
        #not plugin_result.leaf_certificate_subject_matches_hostname some sites' certs CN is with "www." so the result here is false
        if plugin_result.verified_certificate_chain and site_info.name not in str(
                plugin_result.verified_certificate_chain[0].subject):
            site_info.cert_trusted = "False"
            print("not trusted: " + site_info.name)
            print(plugin_result.__dict__)
        # elif not plugin_result.verified_certificate_chain:
        #     site_info.cert_trusted = "False"
        #     print("not trusted: " + site_info.name)
        #     print(plugin_result.__dict__)
        else:
            site_info.cert_trusted = "True"
            scan_result1 = synchronous_scanner.run_scan_command(
                server_info, Sslv20ScanCommand())
            if len(scan_result1.accepted_cipher_list) > 0:
                site_info.sslv2 = "True"
            scan_result2 = synchronous_scanner.run_scan_command(
                server_info, Sslv30ScanCommand())
            if len(scan_result2.accepted_cipher_list) > 0:
                site_info.sslv3 = "True"
            scan_result3 = synchronous_scanner.run_scan_command(
                server_info, Tlsv10ScanCommand())
            if len(scan_result3.accepted_cipher_list) > 0:
                site_info.tlsv1 = "True"
            scan_result4 = synchronous_scanner.run_scan_command(
                server_info, Tlsv11ScanCommand())
            if len(scan_result4.accepted_cipher_list) > 0:
                site_info.tlsv11 = "True"
            scan_result5 = synchronous_scanner.run_scan_command(
                server_info, Tlsv12ScanCommand())
            if len(scan_result5.accepted_cipher_list) > 0:
                site_info.tlsv12 = "True"
            scan_result6 = synchronous_scanner.run_scan_command(
                server_info, Tlsv13ScanCommand())
            if len(scan_result6.accepted_cipher_list) > 0:
                site_info.tlsv13 = "True"

            recheck_cert(site_info)
Exemple #26
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
Exemple #27
0
def retrieve_ssl_vulnerabilities_for_tcp_service(
        self,
        org_uuid=None,
        service_uuid=None,
        scan_uuid=None,
):
    """
    This performs various SSL vulnerability scans on the tcp service
    :param org_uuid: The UUID of the organization to collect information on behalf of.
    :param service_uuid: The UUID of the network service to retrieve the SSL certificate for.
    :param scan_uuid: The UUID of the network service scan that this SSL certificate retrieval is associated
    with.
    :return: None
    """
    ip_address, port, protocol = self.get_endpoint_information(service_uuid)
    ssl_vulnerabilities_record = SslVulnerabilitiesModel.from_database_model_uuid(
        uuid=scan_uuid,
        db_session=self.db_session
    )
    server_info = ServerConnectivityInfo(hostname=ip_address, ip_address=ip_address, port=port)
    try:
        server_info.test_connectivity_to_server()
    except ServerConnectivityError as e:
        # Could not establish an SSL connection to the server
        logger.error(
            "Error making an SSL connection to the server while looking for vulnerabilities, something went really wrong."
        )
    synchronous_scanner = SynchronousScanner()

    fallback_scsv_command = FallbackScsvScanCommand()
    fallback_scsv_result = synchronous_scanner.run_scan_command(server_info, fallback_scsv_command)
    ssl_vulnerabilities_record.supports_fallback_scsv = fallback_scsv_result.supports_fallback_scsv

    heartbleed_command = HeartbleedScanCommand()
    heartbleed_result = synchronous_scanner.run_scan_command(server_info, heartbleed_command)
    ssl_vulnerabilities_record.is_vulnerable_to_heartbleed = heartbleed_result.is_vulnerable_to_heartbleed

    openssl_css_injection_command = OpenSslCcsInjectionScanCommand()
    openssl_css_injection_result = synchronous_scanner.run_scan_command(server_info, openssl_css_injection_command)
    ssl_vulnerabilities_record.is_vulnerable_to_ccs_injection = openssl_css_injection_result.is_vulnerable_to_ccs_injection

    session_renegotion_command = SessionRenegotiationScanCommand()
    session_renegotion_result = synchronous_scanner.run_scan_command(server_info, session_renegotion_command)
    ssl_vulnerabilities_record.accepts_client_renegotiation = session_renegotion_result.accepts_client_renegotiation
    ssl_vulnerabilities_record.supports_secure_renegotiation = session_renegotion_result.supports_secure_renegotiation

    session_resumption_support_command = SessionResumptionSupportScanCommand()
    session_resumption_support_result = synchronous_scanner.run_scan_command(server_info, session_resumption_support_command)
    ssl_vulnerabilities_record.is_ticket_resumption_supported = session_resumption_support_result.is_ticket_resumption_supported

    ssl_vulnerabilities_record.save(org_uuid)
Exemple #28
0
    def ssl_scan(self):
        print("Running SSL Scan")
        try:
            server_info = ServerConnectivityInfo(
                hostname=self.options["TARGET"])
            server_info.test_connectivity_to_server()
            synchronous_scanner = SynchronousScanner()

            # TLS 1.0
            command = Tlsv10ScanCommand()
            scan_result = synchronous_scanner.run_scan_command(
                server_info, command)
            print("Available TLSv1.0 Ciphers:")
            for cipher in scan_result.accepted_cipher_list:
                print('    {}'.format(cipher.name))

            # TLSv1.2
            command = Tlsv12ScanCommand()
            scan_result = synchronous_scanner.run_scan_command(
                server_info, command)
            print("Available TLSv1.2 Ciphers:")
            for cipher in scan_result.accepted_cipher_list:
                print('    {}'.format(cipher.name))

            # Certificate information
            command = CertificateInfoScanCommand()
            scan_result = synchronous_scanner.run_scan_command(
                server_info, command)
            for entry in scan_result.as_text():
                print(entry)

            # Heartbleed vulnerability info
            command = HeartbleedScanCommand()
            scan_result = synchronous_scanner.run_scan_command(
                server_info, command)
            for entry in scan_result.as_text():
                print(entry)

            # HTTP Headers info
            command = HttpHeadersScanCommand()
            scan_result = synchronous_scanner.run_scan_command(
                server_info, command)
            for entry in scan_result.as_text():
                print(entry)

        except Exception as e:
            self.handle_exception(e, "Error running SSL scan")
            pass
Exemple #29
0
def init_sslyze(hostname, options, sync=False):
    global network_timeout

    network_timeout = int(options.get("network_timeout", network_timeout))

    try:
        server_info = sslyze.server_connectivity.ServerConnectivityInfo(
            hostname=hostname, port=443)
    except sslyze.server_connectivity.ServerConnectivityError as error:
        logging.warn(
            "\tServer connectivity not established during initialization.")
        return None, None
    except Exception as err:
        utils.notify(err)
        logging.warn(
            "\tUnknown exception when initializing server connectivity info.")
        return None, None

    try:
        # logging.debug("\tTesting connectivity with timeout of %is." % network_timeout)
        server_info.test_connectivity_to_server(
            network_timeout=network_timeout)
    except sslyze.server_connectivity.ServerConnectivityError as err:
        logging.warn("\tServer connectivity not established during test.")
        return None, None
    except Exception as err:
        utils.notify(err)
        logging.warn(
            "\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
Exemple #30
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')
    def run_tests(self, tests):
        """
        Run all enabled tests against the target url with the http or https port specified in the connect function.
        The Test objects within the tests array describes each test. The array should be changed according to the
        outcome, and if both ports have been specified and are supported the results must be merged before returned.

        :param tests: Array of Test objects
        :type tests: Array[Test...]
        :param targetURL: The target including address and port
        :type targetURL: str
        :return: Array of test objects
        :rtype: Array[Test...]
        """

        # Perform tests

        synchronous_scanner = SynchronousScanner()

        # Run all plugins and do individual checks to see if the tests passed
        for i, plugin in enumerate(PluginsRepository._PLUGIN_CLASSES):
            if tests[i].enabled is True:
                plugin_passed = True

                # Individual check for cipher suites
                if plugin is OpenSslCipherSuitesPlugin:
                    for command in plugin.get_available_commands():
                        scan_result = synchronous_scanner.run_scan_command(
                            self.server_info, command())
                        if not self.is_open_ssl_cihper_suites_secure(
                                command, scan_result):
                            # If one command fails the plugin fails as a whole
                            plugin_passed = False
                            break

                # Individual check for certificates
                elif plugin is CertificateInfoPlugin:
                    for command in plugin.get_available_commands():
                        scan_result = synchronous_scanner.run_scan_command(
                            self.server_info, command())
                        if not self.is_certificate_info_secure(scan_result):
                            plugin_passed = False
                            break

                # Individual check for compression
                elif plugin is CompressionPlugin:
                    for command in plugin.get_available_commands():
                        scan_result = synchronous_scanner.run_scan_command(
                            self.server_info, command())
                        if not self.is_compression_secure(scan_result):
                            plugin_passed = False
                            break

                # Individual check for fallback scsv
                elif plugin is FallbackScsvPlugin:
                    for command in plugin.get_available_commands():
                        scan_result = synchronous_scanner.run_scan_command(
                            self.server_info, command())
                        if not self.is_fallback_scsv_secure(scan_result):
                            plugin_passed = False
                            break

                # Individual check for heartbleed
                elif plugin is HeartbleedPlugin:
                    for command in plugin.get_available_commands():
                        scan_result = synchronous_scanner.run_scan_command(
                            self.server_info, command())
                        if not self.is_heartbleed_secure(scan_result):
                            plugin_passed = False
                            break

                # Individual check for secure http headers
                elif plugin is HttpHeadersPlugin:
                    for command in plugin.get_available_commands():
                        scan_result = synchronous_scanner.run_scan_command(
                            self.server_info, command())
                        if not self.is_http_headers_secure(scan_result):
                            plugin_passed = False
                            break

                # Individual check for openssl css injection
                elif plugin is OpenSslCcsInjectionPlugin:
                    for command in plugin.get_available_commands():
                        scan_result = synchronous_scanner.run_scan_command(
                            self.server_info, command())
                        if not self.is_openssl_css_injection_secure(
                                scan_result):
                            plugin_passed = False
                            break

                # Individual check for session renegotiation
                elif plugin is SessionRenegotiationPlugin:
                    for command in plugin.get_available_commands():
                        scan_result = synchronous_scanner.run_scan_command(
                            self.server_info, command())
                        if not self.is_session_renegotiation_secure(
                                scan_result):
                            plugin_passed = False
                            break

                # Individual check for session resumption
                elif plugin is SessionResumptionPlugin:
                    for command in plugin.get_available_commands():
                        scan_result = synchronous_scanner.run_scan_command(
                            self.server_info, command())
                        if not self.is_session_resumption_secure(scan_result):
                            plugin_passed = False
                            break

                # Individual check for the robot attack
                elif plugin is RobotPlugin:
                    for command in plugin.get_available_commands():
                        scan_result = synchronous_scanner.run_scan_command(
                            self.server_info, command())
                        if not self.is_robot_secure(scan_result):
                            plugin_passed = False
                            break

                # Individual check for early data support
                elif plugin is EarlyDataPlugin:
                    for command in plugin.get_available_commands():
                        scan_result = synchronous_scanner.run_scan_command(
                            self.server_info, command())
                        if not self.is_early_data_secure(scan_result):
                            plugin_passed = False
                            break

            else:
                plugin_passed = None
            tests[i].passed = plugin_passed

        return tests
Exemple #32
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!')
Exemple #33
0
    # Setup the server to scan and ensure it is online/reachable
    hostname = 'smtp.gmail.com'
    try:
        server_info = ServerConnectivityInfo(
            hostname=hostname,
            port=587,
            tls_wrapped_protocol=TlsWrappedProtocolEnum.STARTTLS_SMTP)
        server_info.test_connectivity_to_server()
    except ServerConnectivityError as e:
        # Could not establish an SSL connection to the server
        raise RuntimeError('Error when connecting to {}: {}'.format(
            hostname, e.error_msg))

    # 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))

    # Example 2: Run multiple scan commands concurrently. It is of course much faster than the SynchronousScanner
    concurrent_scanner = ConcurrentScanner()

    # Queue some scan commands
    print('\nQueuing some commands...')
    concurrent_scanner.queue_scan_command(server_info, Tlsv12ScanCommand())
    concurrent_scanner.queue_scan_command(server_info,
                                          SessionRenegotiationScanCommand())
    concurrent_scanner.queue_scan_command(server_info,
                                          CertificateInfoScanCommand())
Exemple #34
0
if __name__ == '__main__':
    # Setup the server to scan and ensure it is online/reachable
    hostname = 'smtp.gmail.com'
    try:
        server_info = ServerConnectivityInfo(hostname=hostname, port=587,
                                             tls_wrapped_protocol=TlsWrappedProtocolEnum.STARTTLS_SMTP)
        server_info.test_connectivity_to_server()
    except ServerConnectivityError as e:
        # Could not establish an SSL connection to the server
        raise RuntimeError('Error when connecting to {}: {}'.format(hostname, e.error_msg))


    # 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))


    # Example 2: Run multiple scan commands concurrently. It is of course much faster than the SynchronousScanner
    concurrent_scanner = ConcurrentScanner()

    # Queue some scan commands
    print('\nQueuing some commands...')
    concurrent_scanner.queue_scan_command(server_info, Tlsv12ScanCommand())
    concurrent_scanner.queue_scan_command(server_info, SessionRenegotiationScanCommand())
    concurrent_scanner.queue_scan_command(server_info, CertificateInfoScanCommand())