Esempio n. 1
0
def _get_simulations(ep, protos):
    if ep["details"]["sims"]["results"] is not None:
        output.norm("\tHandshake Simulation:")

        for sim in ep["details"]["sims"]["results"]:
            name = f'{sim["client"]["name"]} {sim["client"]["version"]}'

            if "platform" in sim["client"]:
                name += f' / {sim["client"]["platform"]}'

            name = name.ljust(28)

            if sim["errorCode"] == 0:
                protocol = protos[sim["protocolId"]]
                ke = _get_key_exchange(sim, True)

                if ke is not None:
                    suite_name = f'{sim["suiteName"]} - {ke}'
                else:
                    suite_name = f'{sim["suiteName"]}'

                output.norm(f"\t\t{name} - {protocol} - {suite_name}")
            else:
                output.info(f"\t\t{name} - Simulation Failed")

        output.empty()
Esempio n. 2
0
def _get_suite_info(proto: str,
                    result: openssl_cipher_suites_plugin.CipherSuiteScanResult,
                    url: str):
    output.norm(f"\t\t{proto}:")

    if len(result.accepted_cipher_list) > 0:
        for suite in result.accepted_cipher_list:
            name = openssl_cipher_suites_plugin.OPENSSL_TO_RFC_NAMES_MAPPING[
                suite.ssl_version].get(suite.openssl_name, suite.openssl_name)

            if _is_cipher_suite_secure(suite, name):
                if "CBC" in name:
                    output.info(
                        f"\t\t  {name.ljust(50)} - {suite.key_size}-bits")

                    reporter.register(
                        issue.Issue(Vulnerabilities.TLS_CBC_CIPHER_SUITE, url,
                                    {"cipher": name}))
                else:
                    output.norm(
                        f"\t\t  {name.ljust(50)} - {suite.key_size}-bits")
            else:
                output.vuln(f"\t\t  {name.ljust(50)} - {suite.key_size}-bits")

                reporter.register(
                    issue.Issue(Vulnerabilities.TLS_INSECURE_CIPHER_SUITE, url,
                                {"cipher": name}))

        output.norm(
            f"\t\t  ({len(result.rejected_cipher_list)} suites rejected)")
    else:
        output.norm(
            f"\t\t  (all suites ({len(result.rejected_cipher_list)}) rejected)"
        )
Esempio n. 3
0
def display(msg: str, issue: Issue) -> None:
    if issue.vulnerability.display_all or not is_registered(
            issue.vulnerability):
        if issue.severity == Severity.CRITICAL or issue.severity == Severity.HIGH:
            output.vuln(msg)
        elif issue.severity == Severity.MEDIUM:
            output.warn(msg)
        else:
            output.info(msg)

    # if there's no evidence, default to the msg - better than nothing
    if issue.evidence is None:
        issue.evidence = msg.strip()

    register(issue)
Esempio n. 4
0
def _get_vulnerability_info(ep, url):
    output.norm("\tProtocol & Vulnerability Information:")

    if "sniRequired" in ep["details"]:
        if ep["details"]["sniRequired"]:
            output.info("\t\tSNI Required: Yes")
        else:
            output.norm("\t\tSNI Required: No")

    if "drownVulnerable" in ep["details"]:
        if ep["details"]["drownVulnerable"]:
            output.vuln("\t\tDROWN: Vulnerable")

            servers = ""
            for dh in ep["details"]["drownHosts"]:
                servers += f'({dh["ip"]}:{dh["port"]} - {dh["status"]}) '
                output.norm(f'\t\t\t{dh["ip"]}:{dh["port"]} - {dh["status"]}')
                output.norm(
                    f'\t\t\t  https://test.drownattack.com/?site={dh["ip"]}')

            reporter.register(
                issue.Issue(
                    Vulnerabilities.TLS_DROWN,
                    url,
                    {
                        "servers": servers,
                        "ip": ep["ipAddress"]
                    },
                ))
        else:
            output.norm("\t\tDROWN: No")
    else:
        output.error("\t\tDROWN: Information Not Received")

    if "zeroRTTEnabled" in ep["details"]:
        if ep["details"]["zeroRTTEnabled"] == -2:
            output.error("\t\tTLS 1.3 0-RTT Support: Test Failed")
        elif ep["details"]["zeroRTTEnabled"] == -1:
            output.norm("\t\tTLS 1.3 0-RTT Support: Test Not Performed")
        elif ep["details"]["zeroRTTEnabled"] == 0:
            output.norm("\t\tTLS 1.3 0-RTT Support: No")
        elif ep["details"]["zeroRTTEnabled"] == 1:
            reporter.display(
                "\t\tTLS 1.3 0-RTT Support: Yes",
                issue.Issue(
                    Vulnerabilities.TLS_VERSION_1_3_EARLY_DATA_ENABLED,
                    url,
                    {"ip": ep["ipAddress"]},
                ),
            )
        else:
            output.error(
                f'\t\tTLS 1.3 0-RTT Support: Unknown ({ep["details"]["zeroRTTEnabled"]})'
            )
    else:
        output.error("\t\tTLS 1.3 0-RTT Support: Information Not Received")

    if "renegSupport" in ep["details"]:
        if ep["details"]["renegSupport"] & 1 != 0:
            reporter.display(
                "\t\tSecure Renegotiation: insecure client-initiated renegotiation supported",
                issue.Issue(Vulnerabilities.TLS_INSECURE_RENEG, url,
                            {"ip": ep["ipAddress"]}),
            )

        if ep["details"]["renegSupport"] & (1 << 1) != 0:
            output.norm(
                "\t\tSecure Renegotiation: secure renegotiation supported")

        if ep["details"]["renegSupport"] & (1 << 2) != 0:
            output.norm(
                "\t\tSecure Renegotiation: secure client-initiated renegotiation supported"
            )

        if ep["details"]["renegSupport"] & (1 << 3) != 0:
            output.norm(
                '\t\tSecure Renegotiation: server requires secure renegotiation support"'
            )
    else:
        output.error("\t\tSecure Renegotiation: Information Not Received")

    if "poodle" in ep["details"]:
        if ep["details"]["poodle"]:
            reporter.display(
                "\t\tPOODLE (SSL): Vulnerable",
                issue.Issue(Vulnerabilities.TLS_LEGACY_SSL_POODLE, url,
                            {"ip": ep["ipAddress"]}),
            )
        else:
            output.norm("\t\tPOODLE (SSL): No")
    else:
        output.error("\t\tPOODLE (SSL): Information Not Received")

    if "zombiePoodle" in ep["details"]:
        if ep["details"]["zombiePoodle"] == -1:
            output.error("\t\tZombie POODLE: Test Failed")
        elif ep["details"]["zombiePoodle"] == 0:
            output.error("\t\tZombie POODLE: Test Failed (Unknown)")
        elif ep["details"]["zombiePoodle"] == 1:
            output.norm("\t\tZombie POODLE: No")
        elif ep["details"]["zombiePoodle"] == 2:
            reporter.display(
                "\t\tZombie POODLE: Vulnerable - Not Exploitable",
                issue.Issue(Vulnerabilities.TLS_ZOMBIE_POODLE_NE, url,
                            {"ip": ep["ipAddress"]}),
            )
        elif ep["details"]["zombiePoodle"] == 3:
            output.vuln("\t\tZombie POODLE: Vulnerable - Exploitable")
            reporter.display(
                "\t\tZombie POODLE: Vulnerable - Exploitable",
                issue.Issue(Vulnerabilities.TLS_ZOMBIE_POODLE, url,
                            {"ip": ep["ipAddress"]}),
            )
        else:
            output.error(
                f'\t\tZombie POODLE: Unknown Response ({ep["details"]["zombiePoodle"]})'
            )
    else:
        output.error("\t\tZombie POODLE: Information Not Received")

    if "goldenDoodle" in ep["details"]:
        if ep["details"]["goldenDoodle"] == -1:
            output.error("\t\tGOLDENDOODLE: Test Failed")
        elif ep["details"]["goldenDoodle"] == 0:
            output.error("\t\tGOLDENDOODLE: Test Failed (Unknown)")
        elif ep["details"]["goldenDoodle"] == 1:
            output.norm("\t\tGOLDENDOODLE: No")
        elif ep["details"]["goldenDoodle"] == 4:
            reporter.display(
                "\t\tGOLDENDOODLE: Vulnerable - Not Exploitable",
                issue.Issue(Vulnerabilities.TLS_GOLDENDOODLE_NE, url,
                            {"ip": ep["ipAddress"]}),
            )
        elif ep["details"]["goldenDoodle"] == 5:
            reporter.display(
                "\t\tGOLDENDOODLE: Vulnerable - Exploitable",
                issue.Issue(Vulnerabilities.TLS_GOLDENDOODLE, url,
                            {"ip": ep["ipAddress"]}),
            )
        else:
            output.error(
                f't\tGOLDENDOODLE: Unknown Response ({ep["details"]["goldenDoodle"]})'
            )
    else:
        output.error("\t\tGOLDENDOODLE: Information Not Received")

    if "zeroLengthPaddingOracle" in ep["details"]:
        if ep["details"]["zeroLengthPaddingOracle"] == -1:
            output.error(
                "\t\tOpenSSL 0-Length Padding Oracle (CVE-2019-1559): Test Failed"
            )
        elif ep["details"]["zeroLengthPaddingOracle"] == 0:
            output.error(
                "\t\tOpenSSL 0-Length Padding Oracle (CVE-2019-1559): Test Failed (Unknown)"
            )
        elif ep["details"]["zeroLengthPaddingOracle"] == 1:
            output.norm(
                "\t\tOpenSSL 0-Length Padding Oracle (CVE-2019-1559): No")
        elif ep["details"]["zeroLengthPaddingOracle"] == 6:
            reporter.display(
                "\t\tOpenSSL 0-Length Padding Oracle (CVE-2019-1559): Vulnerable - Not Exploitable",
                issue.Issue(
                    Vulnerabilities.TLS_OPENSSL_CVE_2019_1559_NE,
                    url,
                    {"ip": ep["ipAddress"]},
                ),
            )
        elif ep["details"]["zeroLengthPaddingOracle"] == 7:
            reporter.display(
                "\t\tOpenSSL 0-Length Padding Oracle (CVE-2019-1559): Vulnerable - Exploitable",
                issue.Issue(
                    Vulnerabilities.TLS_OPENSSL_CVE_2019_1559,
                    url,
                    {"ip": ep["ipAddress"]},
                ),
            )
        else:
            output.error(
                f"\t\tOpenSSL 0-Length Padding Oracle (CVE-2019-1559): Unknown Response"
                f' ({ep["details"]["zeroLengthPaddingOracle"]})')
    else:
        output.error(
            "OpenSSL 0-Length Padding Oracle (CVE-2019-1559): Information Not Received"
        )

    if "sleepingPoodle" in ep["details"]:
        if ep["details"]["sleepingPoodle"] == -1:
            output.error("\t\tSleeping POODLE: Test Failed")
        elif ep["details"]["sleepingPoodle"] == 0:
            output.error("\t\tSleeping POODLE: Test Failed (Unknown)")
        elif ep["details"]["sleepingPoodle"] == 1:
            output.norm("\t\tSleeping POODLE: No")
        elif ep["details"]["sleepingPoodle"] == 10:
            reporter.display(
                "\t\tSleeping POODLE: Vulnerable - Not Exploitable",
                issue.Issue(Vulnerabilities.TLS_SLEEPING_POODLE_NE, url,
                            {"ip": ep["ipAddress"]}),
            )
        elif ep["details"]["sleepingPoodle"] == 11:
            output.vuln("\t\tSleeping POODLE: Vulnerable - Exploitable")
            reporter.display(
                "\t\tSleeping POODLE: Vulnerable - Exploitable",
                issue.Issue(Vulnerabilities.TLS_SLEEPING_POODLE, url,
                            {"ip": ep["ipAddress"]}),
            )
        else:
            output.error(
                f'\t\tSleeping POODLE: Unknown Response ({ep["details"]["sleepingPoodle"]})'
            )
    else:
        output.error("\t\tSleeping POODLE: Information Not Received")

    if "poodleTls" in ep["details"]:
        if ep["details"]["poodleTls"] == -3:
            output.info("\t\tPOODLE (TLS): Inconclusive (Timeout)")
        elif ep["details"]["poodleTls"] == -2:
            output.info("\t\tPOODLE (TLS): TLS Not Supported")
        elif ep["details"]["poodleTls"] == -1:
            output.error("\t\tPOODLE (TLS): Test Failed")
        elif ep["details"]["poodleTls"] == 0:
            output.error("\t\tPOODLE (TLS): Test Failed (Unknown)")
        elif ep["details"]["poodleTls"] == 1:
            output.norm("\t\tPOODLE (TLS): No")
        elif ep["details"]["poodleTls"] == 2:
            reporter.display(
                "\t\tPOODLE (TLS): Vulnerable",
                issue.Issue(Vulnerabilities.TLS_POODLE, url,
                            {"ip": ep["ipAddress"]}),
            )
        else:
            output.error(
                f'\t\tPOODLE (TLS): Unknown Response ({ep["details"]["poodleTls"]})'
            )
    else:
        output.error("\t\tPOODLE (TLS): Information Not Received")

    if "fallbackScsv" in ep["details"]:
        if ep["details"]["fallbackScsv"]:
            output.norm("\t\tDowngrade Prevention: Yes")
        else:
            reporter.display(
                "\t\tDowngrade Prevention: No",
                issue.Issue(
                    Vulnerabilities.TLS_FALLBACK_SCSV_MISSING,
                    url,
                    {"ip": ep["ipAddress"]},
                ),
            )
    else:
        output.error("\t\tDowngrade Prevention: Information Not Received")

    if "compressionMethods" in ep["details"]:
        if ep["details"]["compressionMethods"] & 1 != 0:
            reporter.display(
                "\t\tCompression: DEFLATE",
                issue.Issue(
                    Vulnerabilities.TLS_COMPRESSION_ENABLED,
                    url,
                    {"ip": ep["ipAddress"]},
                ),
            )
        else:
            output.norm("\t\tCompression: No")
    else:
        output.error("\t\tCompression: Information Not Received")

    if "heartbeat" in ep["details"]:
        if ep["details"]["heartbeat"]:
            reporter.display(
                "\t\tHeartbeat: Enabled",
                issue.Issue(Vulnerabilities.TLS_HEARTBEAT_ENABLED, url,
                            {"ip": ep["ipAddress"]}),
            )
        else:
            output.norm("\t\tHeartbeat: Disabled")
    else:
        output.error("\t\tHeartbeat: Information Not Received")

    if "heartbleed" in ep["details"]:
        if ep["details"]["heartbleed"]:
            reporter.display(
                "\t\tHeartbleed: Vulnerable",
                issue.Issue(Vulnerabilities.TLS_HEARTBLEEDL, url,
                            {"ip": ep["ipAddress"]}),
            )
        else:
            output.norm("\t\tHeartbleed: No")
    else:
        output.error("\t\tHeartbleed: Information Not Received")

    if "ticketbleed" in ep["details"]:
        if ep["details"]["ticketbleed"] == -1:
            output.error("\t\tTicketbleed (CVE-2016-9244): Test Failed")
        elif ep["details"]["ticketbleed"] == 0:
            output.error(
                "\t\tTicketbleed (CVE-2016-9244): Test Failed (Unknown)")
        elif ep["details"]["ticketbleed"] == 1:
            output.norm("\t\tTicketbleed (CVE-2016-9244): No")
        elif ep["details"]["ticketbleed"] == 2:
            reporter.display(
                "\t\tTicketbleed (CVE-2016-9244): Vulnerable",
                issue.Issue(Vulnerabilities.TLS_TICKETBLEED, url,
                            {"ip": ep["ipAddress"]}),
            )
        else:
            output.error(
                f'\t\tTicketbleed (CVE-2016-9244): Unknown Response ({ep["details"]["ticketbleed"]})'
            )
    else:
        output.error(
            "\t\tTicketbleed (CVE-2016-9244): Information Not Received")

    if "openSslCcs" in ep["details"]:
        if ep["details"]["openSslCcs"] == -1:
            output.error("\t\tOpenSSL CCS (CVE-2014-0224): Test Failed")
        elif ep["details"]["openSslCcs"] == 0:
            output.error(
                "\t\tOpenSSL CCS (CVE-2014-0224): Test Failed (Unknown)")
        elif ep["details"]["openSslCcs"] == 1:
            output.norm("\t\tOpenSSL CCS (CVE-2014-0224): No")
        elif ep["details"]["openSslCcs"] == 2:
            reporter.display(
                "\t\tOpenSSL CCS (CVE-2014-0224): Vulnerable - Not Exploitable",
                issue.Issue(
                    Vulnerabilities.TLS_OPENSSL_CVE_2014_0224_NE,
                    url,
                    {"ip": ep["ipAddress"]},
                ),
            )
        elif ep["details"]["openSslCcs"] == 3:
            output.vuln("\t\tOpenSSL CCS (CVE-2014-0224): Vulnerable")
            reporter.display(
                "\t\tOpenSSL CCS (CVE-2014-0224): Vulnerable",
                issue.Issue(
                    Vulnerabilities.TLS_OPENSSL_CVE_2014_0224,
                    url,
                    {"ip": ep["ipAddress"]},
                ),
            )
        else:
            output.error(
                f'\t\tOpenSSL CCS (CVE-2014-0224): Unknown Response ({ep["details"]["openSslCcs"]})'
            )
    else:
        output.error(
            "\t\tOpenSSL CCS (CVE-2014-0224): Information Not Received")

    if "openSSLLuckyMinus20" in ep["details"]:
        if ep["details"]["openSSLLuckyMinus20"] == -1:
            output.error(
                "\t\tOpenSSL Padding Oracle (CVE-2016-2107): Test Failed")
        elif ep["details"]["openSSLLuckyMinus20"] == 0:
            output.error(
                "\t\tOpenSSL Padding Oracle (CVE-2016-2107): Test Failed (Unknown)"
            )
        elif ep["details"]["openSSLLuckyMinus20"] == 1:
            output.norm("\t\tOpenSSL Padding Oracle (CVE-2016-2107): No")
        elif ep["details"]["openSSLLuckyMinus20"] == 2:
            reporter.display(
                "\t\tOpenSSL Padding Oracle (CVE-2016-2107): Vulnerable",
                issue.Issue(
                    Vulnerabilities.TLS_OPENSSL_CVE_2016_2107,
                    url,
                    {"ip": ep["ipAddress"]},
                ),
            )
        else:
            output.error(
                f"\t\tOpenSSL Padding Oracle (CVE-2016-2107): Unknown Response "
                f'({ep["details"]["openSSLLuckyMinus20"]})')
    else:
        output.error(
            "\t\tOpenSSL Padding Oracle (CVE-2016-2107): Information Not Received"
        )

    if "bleichenbacher" in ep["details"]:
        if ep["details"]["bleichenbacher"] == -1:
            output.error("\t\tROBOT: Test Failed")
        elif ep["details"]["bleichenbacher"] == 0:
            output.error("\t\tROBOT: Test Failed (Unknown)")
        elif ep["details"]["bleichenbacher"] == 1:
            output.norm("\t\tROBOT: No")
        elif ep["details"]["bleichenbacher"] == 2:
            reporter.display(
                "\t\tROBOT: Vulnerable - Not Exploitable",
                issue.Issue(Vulnerabilities.TLS_ROBOT_ORACLE_WEAK, url,
                            {"ip": ep["ipAddress"]}),
            )
        elif ep["details"]["bleichenbacher"] == 3:
            reporter.display(
                "\t\tROBOT: Vulnerable - Exploitable",
                issue.Issue(
                    Vulnerabilities.TLS_ROBOT_ORACLE_STRONG,
                    url,
                    {"ip": ep["ipAddress"]},
                ),
            )
        elif ep["details"]["bleichenbacher"] == 4:
            output.norm("\t\tROBOT: Unknown - Inconsistent Results")
        else:
            output.error(
                f'\t\tROBOT: Unknown Response ({ep["details"]["bleichenbacher"]})'
            )
    else:
        output.error("\t\tROBOT: Information Not Received")

    if "forwardSecrecy" in ep["details"]:
        if ep["details"]["forwardSecrecy"] & (1 << 2) != 0:
            output.norm("\t\tForward Secrecy: Yes (all simulated clients)")
        elif ep["details"]["forwardSecrecy"] & (1 << 1) != 0:
            output.info("\t\tForward Secrecy: Yes (modern clients)")
        elif ep["details"]["forwardSecrecy"] & 1 != 0:
            reporter.display(
                "\t\tForward Secrecy: Yes (limited support)",
                issue.Issue(
                    Vulnerabilities.TLS_LIMITED_FORWARD_SECRECY,
                    url,
                    {"ip": ep["ipAddress"]},
                ),
            )
        else:
            output.vuln("\t\tForward Secrecy: No")
    else:
        output.error("\t\tForward Secrecy: Information Not Received")

    if "supportsAead" in ep["details"]:
        if ep["details"]["supportsAead"]:
            output.norm("\t\tAEAD Cipher Suites Supported: Yes")
        else:
            reporter.display(
                "\t\tAEAD Cipher Suites Supported: No",
                issue.Issue(Vulnerabilities.TLS_NO_AEAD_SUPPORT, url,
                            {"ip": ep["ipAddress"]}),
            )
    else:
        output.error(
            "\t\tAEAD Cipher Suites Supported: Information Not Received")

    if "supportsCBC" in ep["details"]:
        if ep["details"]["supportsCBC"]:
            output.info("\t\tCBC Cipher Suites Supported: Yes")
        else:
            output.norm("\t\tCBC Cipher Suites Supported: No")
    else:
        output.error(
            "\t\tCBC Cipher Suites Supported: Information Not Received")

    if "alpnProtocols" in ep["details"]:
        output.norm(f'\t\tALPN: {ep["details"]["alpnProtocols"]}')

    if "npnProtocols" in ep["details"]:
        output.norm(f'\t\tNPN: {ep["details"]["npnProtocols"]}')

    if "sessionResumption" in ep["details"]:
        if ep["details"]["sessionResumption"] == 0:
            output.norm("\t\tSession Resumption: Not Enabled / Empty Tickets")
        elif ep["details"]["sessionResumption"] == 1:
            output.norm("\t\tSession Resumption: Enabled / No Resumption")
        elif ep["details"]["sessionResumption"] == 2:
            reporter.display(
                "\t\tSession Resumption: Enabled",
                issue.Issue(
                    Vulnerabilities.TLS_SESSION_RESP_ENABLED,
                    url,
                    {"ip": ep["ipAddress"]},
                ),
            )
        else:
            output.error(
                f'\t\tSession Resumption: Unknown Response ({ep["details"]["sessionResumption"]})'
            )
    else:
        output.error("\t\tSession Resumption: Information Not Received")

    if "ocspStapling" in ep["details"]:
        if ep["details"]["ocspStapling"]:
            output.norm("\t\tOCSP Stapling: Yes")
        else:
            reporter.display(
                "\t\tOCSP Stapling: No",
                issue.Issue(
                    Vulnerabilities.TLS_OCSP_STAPLE_MISSING,
                    url,
                    {"ip": ep["ipAddress"]},
                ),
            )
    else:
        output.error("\t\tOCSP Stapling: Information Not Received")

    if "miscIntolerance" in ep["details"]:
        if ep["details"]["miscIntolerance"] & 1 != 0:
            output.info("\t\tTLS Extension Intolerance: Yes")

        if ep["details"]["miscIntolerance"] & (1 << 1) != 0:
            output.warn("\t\tLong Handshake Intolerance: Yes")

        if ep["details"]["miscIntolerance"] & (1 << 2) != 0:
            output.warn("\t\tLong Handshake Intolerance: Workaround Success")

    if "protocolIntolerance" in ep["details"]:
        if ep["details"]["protocolIntolerance"] & 1 != 0:
            output.warn("\t\tProtocol Intolerance: TLS 1.0")

        if ep["details"]["protocolIntolerance"] & (1 << 1) != 0:
            output.warn("\t\tProtocol Intolerance: TLS 1.1")

        if ep["details"]["protocolIntolerance"] & (1 << 2) != 0:
            output.warn("\t\tProtocol Intolerance: TLS 1.2")

        if ep["details"]["protocolIntolerance"] & (1 << 3) != 0:
            output.warn("\t\tProtocol Intolerance: TLS 1.3")

        if ep["details"]["protocolIntolerance"] & (1 << 4) != 0:
            output.warn("\t\tProtocol Intolerance: TLS 1.152")

        if ep["details"]["protocolIntolerance"] & (1 << 5) != 0:
            output.warn("\t\tProtocol Intolerance: TLS 2.152")

    if "freak" in ep["details"]:
        if ep["details"]["freak"]:
            reporter.display(
                "\t\tFREAK: Vulnerable (512-bit key exchange supported)",
                issue.Issue(Vulnerabilities.TLS_FREAK, url,
                            {"ip": ep["ipAddress"]}),
            )
        else:
            output.norm("\t\tFREAK: No")
    else:
        output.error("\t\tFREAK: Information Not Received")

    if "logjam" in ep["details"]:
        if ep["details"]["logjam"]:
            reporter.display(
                "\t\tLogjam: Vulnerable",
                issue.Issue(Vulnerabilities.TLS_LOGJAM, url,
                            {"ip": ep["ipAddress"]}),
            )
        else:
            output.norm("\t\tLogjam: No")
    else:
        output.error("\t\tLogjam: Information Not Received")

    if "dhUsesKnownPrimes" in ep["details"]:
        if ep["details"]["dhUsesKnownPrimes"] == 0:
            output.norm("\t\tUses common DH primes: No")
        elif ep["details"]["dhUsesKnownPrimes"] == 1:
            output.warn("\t\tUses common DH primes: Yes (not weak)")
            reporter.display(
                "\t\tUses common DH primes: Yes (weak)",
                issue.Issue(
                    Vulnerabilities.TLS_DH_KNOWN_PRIMES_STRONG,
                    url,
                    {"ip": ep["ipAddress"]},
                ),
            )
        elif ep["details"]["dhUsesKnownPrimes"] == 2:
            reporter.display(
                "\t\tUses common DH primes: Yes (weak)",
                issue.Issue(
                    Vulnerabilities.TLS_DH_KNOWN_PRIMES_WEAK,
                    url,
                    {"ip": ep["ipAddress"]},
                ),
            )
        else:
            output.error(
                f'\t\tUses common DH primes: Unknown Response ({ep["details"]["dhUsesKnownPrimes"]})'
            )

    if "dhYsReuse" in ep["details"]:
        if ep["details"]["dhYsReuse"]:
            reporter.display(
                "\t\tDH public server param (Ys) reuse: Yes",
                issue.Issue(Vulnerabilities.TLS_DH_PARAM_REUSE, url,
                            {"ip": ep["ipAddress"]}),
            )
        else:
            output.norm("\t\tDH public server param (Ys) reuse: No")

    if "ecdhParameterReuse" in ep["details"]:
        if ep["details"]["ecdhParameterReuse"]:
            reporter.display(
                "\t\tECDH Public Server Param Reuse: Yes",
                issue.Issue(Vulnerabilities.TLS_ECDH_PARAM_REUSE, url,
                            {"ip": ep["ipAddress"]}),
            )
        else:
            output.norm("\t\tECDH Public Server Param Reuse: No")

    output.empty()
Esempio n. 5
0
def _get_protocol_info(ep, url):
    output.norm("Configuration Information:")
    output.norm("\tProtocol Support:")

    # check protocols
    protos = {}
    tls13_enabled = False

    for proto in ep["details"]["protocols"]:
        if proto["name"] == "SSL":
            # show a vuln for SSLvX

            reporter.display(
                f'\t\t{proto["name"]} {proto["version"]}',
                issue.Issue(Vulnerabilities.TLS_LEGACY_SSL_ENABLED, url,
                            {"ip": ep["ipAddress"]}),
            )
        elif proto["name"] == "TLS" and proto["version"] == "1.0":
            # show a warn for TLSv1.0

            reporter.display(
                f'\t\t{proto["name"]} {proto["version"]}',
                issue.Issue(
                    Vulnerabilities.TLS_VERSION_1_0_ENABLED,
                    url,
                    {"ip": ep["ipAddress"]},
                ),
            )
        elif proto["name"] == "TLS" and proto["version"] == "1.3":
            # capture TLS 1.3 status
            tls13_enabled = True

            output.norm(f'\t\t{proto["name"]} {proto["version"]}')
        else:
            output.norm(f'\t\t{proto["name"]} {proto["version"]}')

        protos[proto["id"]] = f'{proto["name"]} {proto["version"]}'

    if not tls13_enabled:
        reporter.display(
            "\t\tTLS 1.3 Is Not Enabled",
            issue.Issue(
                Vulnerabilities.TLS_VERSION_1_3_NOT_ENABLED,
                url,
                {"ip": ep["ipAddress"]},
            ),
        )

    output.empty()

    if "namedGroups" in ep["details"]:
        output.norm("\tNamed Group Support:")

        for group in ep["details"]["namedGroups"]["list"]:
            output.norm(f'\t\t{group["name"]} {group["bits"]}')

        output.empty()

    if "suites" in ep["details"]:
        output.norm("\tCipher Suite Support:")

        for proto_suites in ep["details"]["suites"]:
            output.norm(f'\t\t{protos[proto_suites["protocol"]]}')

            for suite in proto_suites["list"]:
                ke = _get_key_exchange(suite)

                strength = suite["cipherStrength"]

                if "3DES" in suite["name"]:
                    # in this case, the effective strength is only 112 bits,
                    #  which is what we want to report. So override SSL Labs
                    strength = 112

                if ke is not None:
                    suite_info = f'{suite["name"].ljust(50)} - {strength}-bits - {ke}'
                else:
                    suite_info = f'{suite["name"].ljust(50)} - {strength}-bits'

                if _is_cipher_suite_secure(suite):
                    if "CBC" in suite["name"]:
                        output.info(f"\t\t  {suite_info}")

                        reporter.register(
                            issue.Issue(
                                Vulnerabilities.TLS_CBC_CIPHER_SUITE,
                                url,
                                {"cipher": suite_info},
                            ))
                    else:
                        output.norm(f"\t\t  {suite_info}")
                else:
                    output.vuln(f"\t\t  {suite_info}")

                    reporter.register(
                        issue.Issue(
                            Vulnerabilities.TLS_INSECURE_CIPHER_SUITE,
                            url,
                            {"cipher": suite_info},
                        ))

    output.empty()

    _get_simulations(ep, protos)
Esempio n. 6
0
def scan(args: Namespace, url: str, domain: str):
    output.norm(
        f"Beginning SSL scan using sslyze {__version__} (this could take a minute or two)"
    )
    output.empty()

    ips = basic.get_ips(domain)

    for ip in ips:
        try:
            conn_tester = server_connectivity_tester.ServerConnectivityTester(
                hostname=domain, port=utils.get_port(url), ip_address=ip)

            output.norm(f"IP: {conn_tester.ip_address}:{conn_tester.port}")
            server_info = conn_tester.perform()

            scanner = synchronous_scanner.SynchronousScanner()

            cinfo = scanner.run_scan_command(
                server_info,
                certificate_info_plugin.CertificateInfoScanCommand())
            cinfo = typing.cast(
                certificate_info_plugin.CertificateInfoScanResult, cinfo)

            # print info on the server cert
            _get_leaf_cert_info(cinfo.verified_certificate_chain[0])

            # get all but the first element
            _get_cert_chain(cinfo.verified_certificate_chain[1:], url)

            # list the root stores this is trusted by
            trust = ""
            for t in _get_trusted_root_stores(cinfo):
                trust += f"{t} (trusted) "

            output.norm(f"\tRoot Stores: {trust}")

            output.empty()

            # get info for the various versions of SSL/TLS
            output.norm("\tCipher Suite Support:")

            sslv2 = scanner.run_scan_command(
                server_info, openssl_cipher_suites_plugin.Sslv20ScanCommand())
            sslv2 = typing.cast(
                openssl_cipher_suites_plugin.CipherSuiteScanResult, sslv2)

            _get_suite_info("SSLv2", sslv2, url)

            sslv3 = scanner.run_scan_command(
                server_info, openssl_cipher_suites_plugin.Sslv30ScanCommand())
            sslv3 = typing.cast(
                openssl_cipher_suites_plugin.CipherSuiteScanResult, sslv3)

            _get_suite_info("SSLv3", sslv3, url)

            tls10 = scanner.run_scan_command(
                server_info, openssl_cipher_suites_plugin.Tlsv10ScanCommand())
            tls10 = typing.cast(
                openssl_cipher_suites_plugin.CipherSuiteScanResult, tls10)

            _get_suite_info("TLSv1.0", tls10, url)

            tls11 = scanner.run_scan_command(
                server_info, openssl_cipher_suites_plugin.Tlsv11ScanCommand())
            tls11 = typing.cast(
                openssl_cipher_suites_plugin.CipherSuiteScanResult, tls11)

            _get_suite_info("TLSv1.1", tls11, url)

            tls12 = scanner.run_scan_command(
                server_info, openssl_cipher_suites_plugin.Tlsv12ScanCommand())
            tls12 = typing.cast(
                openssl_cipher_suites_plugin.CipherSuiteScanResult, tls12)

            _get_suite_info("TLSv1.2", tls12, url)

            tls13 = scanner.run_scan_command(
                server_info, openssl_cipher_suites_plugin.Tlsv13ScanCommand())
            tls13 = typing.cast(
                openssl_cipher_suites_plugin.CipherSuiteScanResult, tls13)

            _get_suite_info("TLSv1.3", tls13, url)

            output.empty()

            # check compression
            compression = scanner.run_scan_command(
                server_info, compression_plugin.CompressionScanCommand())
            compression = typing.cast(compression_plugin.CompressionScanResult,
                                      compression)

            if compression.compression_name is not None:
                reporter.display(
                    f"\tCompression: {compression.compression_name}",
                    issue.Issue(Vulnerabilities.TLS_COMPRESSION_ENABLED, url,
                                {}),
                )
            else:
                output.norm("\tCompression: None")

            # check TLS_FALLBACK_SCSV
            fallback = scanner.run_scan_command(
                server_info, fallback_scsv_plugin.FallbackScsvScanCommand())
            fallback = typing.cast(fallback_scsv_plugin.FallbackScsvScanResult,
                                   fallback)

            if fallback.supports_fallback_scsv:
                output.norm("\tDowngrade Prevention: Yes")
            else:
                reporter.display(
                    "\tDowngrade Prevention: No",
                    issue.Issue(Vulnerabilities.TLS_FALLBACK_SCSV_MISSING, url,
                                {}),
                )

            # check Heartbleed
            heartbleed = scanner.run_scan_command(
                server_info, heartbleed_plugin.HeartbleedScanCommand())
            heartbleed = typing.cast(heartbleed_plugin.HeartbleedScanResult,
                                     heartbleed)

            if heartbleed.is_vulnerable_to_heartbleed:
                reporter.display(
                    "\tHeartbleed: Vulnerable",
                    issue.Issue(Vulnerabilities.TLS_HEARTBLEED, url, {}),
                )
            else:
                output.norm("\tHeartbleed: No")

            # check OpenSSL CCS injection vulnerability (CVE-2014-0224)
            openssl_ccs = scanner.run_scan_command(
                server_info,
                openssl_ccs_injection_plugin.OpenSslCcsInjectionScanCommand(),
            )
            openssl_ccs = typing.cast(
                openssl_ccs_injection_plugin.OpenSslCcsInjectionScanResult,
                openssl_ccs)

            if openssl_ccs.is_vulnerable_to_ccs_injection:
                reporter.display(
                    "\tOpenSSL CCS (CVE-2014-0224): Vulnerable",
                    issue.Issue(Vulnerabilities.TLS_OPENSSL_CVE_2014_0224, url,
                                {}),
                )
            else:
                output.norm("\tOpenSSL CCS (CVE-2014-0224): No")

            # check SessionRenegotiation
            sr = scanner.run_scan_command(
                server_info,
                session_renegotiation_plugin.SessionRenegotiationScanCommand(),
            )
            sr = typing.cast(
                session_renegotiation_plugin.SessionRenegotiationScanResult,
                sr)

            if sr.accepts_client_renegotiation:
                output.norm(
                    "\tSecure Renegotiation: client-initiated renegotiation supported"
                )

            if sr.supports_secure_renegotiation:
                output.norm(
                    "\tSecure Renegotiation: secure renegotiation supported")

            # check SessionResumption
            resump = scanner.run_scan_command(
                server_info,
                session_resumption_plugin.SessionResumptionSupportScanCommand(
                ),
            )
            resump = typing.cast(
                session_resumption_plugin.SessionResumptionSupportScanResult,
                resump)

            output.norm(
                f"\tSession Resumption Tickets Supported: {resump.is_ticket_resumption_supported}"
            )

            output.norm(
                f"\tSession Resumption: {resump.successful_resumptions_nb} of "
                f"{resump.attempted_resumptions_nb} successful")

            # check ROBOT
            robot = scanner.run_scan_command(server_info,
                                             robot_plugin.RobotScanCommand())
            robot = typing.cast(robot_plugin.RobotScanResult, robot)

            if (robot.robot_result_enum ==
                    robot_plugin.RobotScanResultEnum.VULNERABLE_WEAK_ORACLE):
                reporter.display(
                    "\tROBOT: Vulnerable - Not Exploitable",
                    issue.Issue(Vulnerabilities.TLS_ROBOT_ORACLE_WEAK, url,
                                {}),
                )
            elif (robot.robot_result_enum ==
                  robot_plugin.RobotScanResultEnum.VULNERABLE_STRONG_ORACLE):
                reporter.display(
                    "\tROBOT: Vulnerable - Exploitable",
                    issue.Issue(Vulnerabilities.TLS_ROBOT_ORACLE_STRONG, url,
                                {}),
                )
            elif (robot.robot_result_enum == robot_plugin.RobotScanResultEnum.
                  UNKNOWN_INCONSISTENT_RESULTS):
                output.error("\tROBOT: Test Failed (Inconsistent Results)")
            else:
                output.norm("\tROBOT: No")

            # check TLS 1.3 Early Data
            ed = scanner.run_scan_command(
                server_info, early_data_plugin.EarlyDataScanCommand())
            ed = typing.cast(early_data_plugin.EarlyDataScanResult, ed)

            if ed.is_early_data_supported:
                output.info("\tTLS 1.3 0-RTT Support: Yes")
            else:
                output.norm("\tTLS 1.3 0-RTT Support: No")

            if cinfo.ocsp_response_status is not None:
                output.norm("\tOCSP Stapling: Yes")
            else:
                reporter.display(
                    "\tOCSP Stapling: No",
                    issue.Issue(Vulnerabilities.TLS_OCSP_STAPLE_MISSING, url,
                                {}),
                )

            output.empty()

        except server_connectivity_tester.ServerConnectivityError as error:
            output.debug_exception()

            if checkers.is_ipv6(ip):
                output.error(
                    "\tError connecting to IPv6 IP. Please ensure that your system is configured properly."
                )

            output.error(f"\tConnection failed ({str(error)})")
            output.empty()