function tls_fallback_scsv($host, $ip, $port)
{
    global $timeout;
    if (filter_var(preg_replace('/[^A-Za-z0-9\\.\\:_-]/', '', $ip), FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
        // ipv6 openssl tools are broken. (https://rt.openssl.org/Ticket/Display.html?id=1365&user=guest&pass=guest)
        return false;
    }
    $result = [];
    $protocols = ssl_conn_protocols($host, $ip, $port);
    if (count(array_filter($protocols)) > 1) {
        $result['protocol_count'] = count(array_filter($protocols));
        $fallback_test = shell_exec("echo | timeout {$timeout} openssl s_client -servername \"" . escapeshellcmd($host) . "\" -connect " . escapeshellcmd($ip) . ":" . escapeshellcmd($port) . " -fallback_scsv -no_tls1_2 2>&1 >/dev/null");
        if (stripos($fallback_test, "alert inappropriate fallback") !== false) {
            $result['tls_fallback_scsv_support'] = 1;
        }
    } else {
        $result['protocol_count'] = 1;
    }
    return $result;
}
Esempio n. 2
0
function ssl_conn_metadata_json($host, $ip, $port, $read_stream, $chain_data = null)
{
    $result = array();
    global $random_blurp;
    global $current_folder;
    $context = stream_context_get_params($read_stream);
    $context_meta = stream_context_get_options($read_stream)['ssl']['session_meta'];
    $cert_data = openssl_x509_parse($context["options"]["ssl"]["peer_certificate"])[0];
    if (filter_var(preg_replace('/[^A-Za-z0-9\\.\\:-]/', '', $ip), FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
        $result["warning"][] = "You are testing an IPv6 host. Due to <a href=\"https://rt.openssl.org/Ticket/Display.html?id=1365&user=guest&pass=guest\">bugs</a> in OpenSSL's command line tools the results will be inaccurate. Known incorrect are OCSP Stapling, TLS_FALLBACK_SCSV and SSL Compression results, others may also be incorrect.";
    }
    $result["checked_hostname"] = $host;
    //chain
    if (isset($context_meta)) {
        if (isset($chain_data)) {
            $chain_length = count($chain_data);
            $certificate_chain = array();
            if ($chain_length <= 10) {
                for ($i = 0; $i < $chain_length; $i++) {
                    if (openssl_x509_parse($chain_data[$i])['issuer']['CN'] && openssl_x509_parse($chain_data[$i])['subject']['CN']) {
                        $result["chain"][$i]["name"] = openssl_x509_parse($chain_data[$i])['subject']['CN'];
                        $result["chain"][$i]["issuer"] = openssl_x509_parse($chain_data[$i])['issuer']['CN'];
                        $export_pem = "";
                        openssl_x509_export($chain_data[$i], $export_pem);
                        array_push($certificate_chain, $export_pem);
                        if (openssl_x509_parse($chain_data[$i])['issuer']['CN'] == openssl_x509_parse($chain_data[$i + 1])['subject']['CN']) {
                            continue;
                        } else {
                            if ($i != $chain_length - 1) {
                                $result["chain"][$i]["error"] = "Issuer does not match the next certificate CN. Chain order is probably wrong.";
                                $result["warning"][] = "Issuer does not match the next certificate CN. Chain order is probably wrong.";
                            }
                        }
                    }
                }
            }
            // chain validation
            file_put_contents('/tmp/verify_cert.' . $random_blurp . '.pem', implode("\n", array_reverse($certificate_chain)) . PHP_EOL, FILE_APPEND);
            $verify_output = 0;
            $verify_exit_code = 0;
            $verify_exec = exec(escapeshellcmd('openssl verify -verbose -purpose any -CAfile ' . getcwd() . '/cacert.pem /tmp/verify_cert.' . $random_blurp . '.pem') . "| grep -v OK", $verify_output, $verify_exit_code);
            if ($verify_exit_code != 1) {
                $result["validation"]["status"] = "failed";
                $result["validation"]["error"] = "Error: Validating certificate chain failed: " . str_replace('/tmp/verify_cert.' . $random_blurp . '.pem: ', '', implode("\n", $verify_output));
                $result["warning"][] = "Validating certificate chain failed. Probably non-trusted root/self signed certificate, or the chain order is wrong.";
            } else {
                $result["validation"]["status"] = "success";
            }
            unlink('/tmp/verify_cert.' . $random_blurp . '.pem');
        }
        // hostname ip port
        $result["ip"] = $ip;
        if (filter_var(preg_replace('/[^A-Za-z0-9\\.\\:-]/', '', $ip), FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
            $addr = inet_pton(preg_replace('/[^A-Za-z0-9\\.\\:-]/', '', $ip));
            $unpack = unpack('H*hex', $addr);
            $hex = $unpack['hex'];
            $arpa = implode('.', array_reverse(str_split($hex))) . '.ip6.arpa';
            if (!empty(dns_get_record($arpa, DNS_PTR)[0]["target"])) {
                $result["hostname"] = dns_get_record($arpa, DNS_PTR)[0]["target"];
            } else {
                $result["hostname"] = "{$host} (No PTR available).";
            }
        } elseif (filter_var(preg_replace('/[^A-Za-z0-9\\.\\:-]/', '', $ip), FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
            if (!empty(gethostbyaddr(preg_replace('/[^A-Za-z0-9\\.\\:-]/', '', $ip)))) {
                $result["hostname"] = gethostbyaddr(preg_replace('/[^A-Za-z0-9\\.\\:-]/', '', $ip));
            } else {
                $result["hostname"] = "{$host} (No PTR available).";
            }
        } else {
            $result["hostname"] = "{$host} (No PTR available).";
        }
        $result["port"] = $port;
        //heartbleed
        $result['heartbleed'] = test_heartbleed($ip, $port);
        if ($result['heartbleed'] == "vulnerable") {
            $result["warning"][] = 'Vulnerable to the Heartbleed bug. Please update your OpenSSL ASAP!';
        }
        // compression
        $compression = conn_compression($host, $ip, $port);
        if ($compression == false) {
            $result["compression"] = false;
        } else {
            if (filter_var(preg_replace('/[^A-Za-z0-9\\.\\:_-]/', '', $ip), FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
                // ipv6 openssl tools are broken. (https://rt.openssl.org/Ticket/Display.html?id=1365&user=guest&pass=guest)
                $result["warning"][] = 'SSL compression not tested because of <a href="https://rt.openssl.org/Ticket/Display.html?id=1365&user=guest&pass=guest">bugs</a> in the OpenSSL tools and IPv6.';
            } else {
                $result["compression"] = true;
                $result["warning"][] = 'SSL compression enabled. Please disable to prevent attacks like CRIME.';
            }
        }
        // protocols
        $result["protocols"] = array_reverse(ssl_conn_protocols($host, $ip, $port));
        foreach ($result["protocols"] as $key => $value) {
            if ($value == true) {
                if ($key == "sslv2") {
                    $result["warning"][] = 'SSLv2 supported. Please disable ASAP and upgrade to a newer protocol like TLSv1.2.';
                }
                if ($key == "sslv3") {
                    $result["warning"][] = 'SSLv3 supported. Please disable and upgrade to a newer protocol like TLSv1.2.';
                }
            } else {
                if ($key == "tlsv1.2") {
                    $result["warning"][] = 'TLSv1.2 unsupported. Please enable TLSv1.2.';
                }
            }
        }
        // ciphersuites
        if ($_GET['ciphersuites'] == 1) {
            $ciphersuites_to_test = array('ECDHE-RSA-AES256-GCM-SHA384', 'ECDHE-ECDSA-AES256-GCM-SHA384', 'ECDHE-RSA-AES256-SHA384', 'ECDHE-ECDSA-AES256-SHA384', 'ECDHE-RSA-AES256-SHA', 'ECDHE-ECDSA-AES256-SHA', 'SRP-DSS-AES-256-CBC-SHA', 'SRP-RSA-AES-256-CBC-SHA', 'SRP-AES-256-CBC-SHA', 'DH-DSS-AES256-GCM-SHA384', 'DHE-DSS-AES256-GCM-SHA384', 'DH-RSA-AES256-GCM-SHA384', 'DHE-RSA-AES256-GCM-SHA384', 'DHE-RSA-AES256-SHA256', 'DHE-DSS-AES256-SHA256', 'DH-RSA-AES256-SHA256', 'DH-DSS-AES256-SHA256', 'DHE-RSA-AES256-SHA', 'DHE-DSS-AES256-SHA', 'DH-RSA-AES256-SHA', 'DH-DSS-AES256-SHA', 'DHE-RSA-CAMELLIA256-SHA', 'DHE-DSS-CAMELLIA256-SHA', 'DH-RSA-CAMELLIA256-SHA', 'DH-DSS-CAMELLIA256-SHA', 'ECDH-RSA-AES256-GCM-SHA384', 'ECDH-ECDSA-AES256-GCM-SHA384', 'ECDH-RSA-AES256-SHA384', 'ECDH-ECDSA-AES256-SHA384', 'ECDH-RSA-AES256-SHA', 'ECDH-ECDSA-AES256-SHA', 'AES256-GCM-SHA384', 'AES256-SHA256', 'AES256-SHA', 'CAMELLIA256-SHA', 'PSK-AES256-CBC-SHA', 'ECDHE-RSA-AES128-GCM-SHA256', 'ECDHE-ECDSA-AES128-GCM-SHA256', 'ECDHE-RSA-AES128-SHA256', 'ECDHE-ECDSA-AES128-SHA256', 'ECDHE-RSA-AES128-SHA', 'ECDHE-ECDSA-AES128-SHA', 'SRP-DSS-AES-128-CBC-SHA', 'SRP-RSA-AES-128-CBC-SHA', 'SRP-AES-128-CBC-SHA', 'DH-DSS-AES128-GCM-SHA256', 'DHE-DSS-AES128-GCM-SHA256', 'DH-RSA-AES128-GCM-SHA256', 'DHE-RSA-AES128-GCM-SHA256', 'DHE-RSA-AES128-SHA256', 'DHE-DSS-AES128-SHA256', 'DH-RSA-AES128-SHA256', 'DH-DSS-AES128-SHA256', 'DHE-RSA-AES128-SHA', 'DHE-DSS-AES128-SHA', 'DH-RSA-AES128-SHA', 'DH-DSS-AES128-SHA', 'DHE-RSA-SEED-SHA', 'DHE-DSS-SEED-SHA', 'DH-RSA-SEED-SHA', 'DH-DSS-SEED-SHA', 'DHE-RSA-CAMELLIA128-SHA', 'DHE-DSS-CAMELLIA128-SHA', 'DH-RSA-CAMELLIA128-SHA', 'DH-DSS-CAMELLIA128-SHA', 'ECDH-RSA-AES128-GCM-SHA256', 'ECDH-ECDSA-AES128-GCM-SHA256', 'ECDH-RSA-AES128-SHA256', 'ECDH-ECDSA-AES128-SHA256', 'ECDH-RSA-AES128-SHA', 'ECDH-ECDSA-AES128-SHA', 'AES128-GCM-SHA256', 'AES128-SHA256', 'AES128-SHA', 'SEED-SHA', 'CAMELLIA128-SHA', 'IDEA-CBC-SHA', 'PSK-AES128-CBC-SHA', 'ECDHE-RSA-RC4-SHA', 'ECDHE-ECDSA-RC4-SHA', 'ECDH-RSA-RC4-SHA', 'ECDH-ECDSA-RC4-SHA', 'RC4-SHA', 'RC4-MD5', 'PSK-RC4-SHA', 'ECDHE-RSA-DES-CBC3-SHA', 'ECDHE-ECDSA-DES-CBC3-SHA', 'SRP-DSS-3DES-EDE-CBC-SHA', 'SRP-RSA-3DES-EDE-CBC-SHA', 'SRP-3DES-EDE-CBC-SHA', 'EDH-RSA-DES-CBC3-SHA', 'EDH-DSS-DES-CBC3-SHA', 'DH-RSA-DES-CBC3-SHA', 'DH-DSS-DES-CBC3-SHA', 'ECDH-RSA-DES-CBC3-SHA', 'ECDH-ECDSA-DES-CBC3-SHA', 'DES-CBC3-SHA', 'PSK-3DES-EDE-CBC-SHA', 'EDH-RSA-DES-CBC-SHA', 'EDH-DSS-DES-CBC-SHA', 'DH-RSA-DES-CBC-SHA', 'DH-DSS-DES-CBC-SHA', 'DES-CBC-SHA', 'EXP-EDH-RSA-DES-CBC-SHA', 'EXP-EDH-DSS-DES-CBC-SHA', 'EXP-DH-RSA-DES-CBC-SHA', 'EXP-DH-DSS-DES-CBC-SHA', 'EXP-DES-CBC-SHA', 'EXP-RC2-CBC-MD5', 'EXP-RC4-MD5', 'ECDHE-RSA-NULL-SHA', 'ECDHE-ECDSA-NULL-SHA', 'AECDH-NULL-SHA', 'ECDH-RSA-NULL-SHA', 'ECDH-ECDSA-NULL-SHA', 'NULL-SHA256', 'NULL-SHA', 'NULL-MD5');
            $tested_ciphersuites = ssl_conn_ciphersuites($host, $ip, $port, $ciphersuites_to_test);
            $result["supported_ciphersuites"] = array();
            foreach ($tested_ciphersuites as $key => $value) {
                if ($value == true) {
                    $result["supported_ciphersuites"][] = $key;
                }
            }
        } else {
            $result["used_ciphersuite"]["name"] = $context_meta['cipher_name'];
            $result["used_ciphersuite"]["bits"] = $context_meta['cipher_bits'];
        }
        // tls_fallback_scsv
        $fallback = tls_fallback_scsv($host, $ip, $port);
        if ($fallback['protocol_count'] == 1) {
            $result["tls_fallback_scsv"] = "Only 1 protocol enabled, fallback not possible, TLS_FALLBACK_SCSV not required.";
        } else {
            if ($fallback['tls_fallback_scsv_support'] == 1) {
                $result["tls_fallback_scsv"] = "supported";
            } else {
                if (filter_var(preg_replace('/[^A-Za-z0-9\\.\\:_-]/', '', $ip), FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
                    // ipv6 openssl tools are broken. (https://rt.openssl.org/Ticket/Display.html?id=1365&user=guest&pass=guest)
                    $result["warning"][] = 'TLS_FALLBACK_SCSV not tested because of <a href="https://rt.openssl.org/Ticket/Display.html?id=1365&user=guest&pass=guest">bugs</a> in the OpenSSL tools and IPv6.';
                } else {
                    $result["tls_fallback_scsv"] = "unsupported";
                    $result["warning"][] = "TLS_FALLBACK_SCSV unsupported. Please upgrade OpenSSL to enable. This offers downgrade attack protection.";
                }
            }
        }
        //hsts
        $headers = server_http_headers($host, $ip, $port);
        if ($headers["strict-transport-security"]) {
            if (is_array($headers["strict-transport-security"])) {
                $result["strict_sransport-security"] = substr($headers["strict-transport-security"][0], 0, 50);
            } else {
                $result["strict_transport_security"] = substr($headers["strict-transport-security"], 0, 50);
            }
        } else {
            $result["strict_transport_security"] = 'not set';
            $result["warning"][] = "HTTP Strict Transport Security not set.";
        }
        //hpkp
        if ($headers["public-key-pins"]) {
            if (is_array($headers["public-key-pins"])) {
                $result["public_key_pins"] = substr($headers["public-key-pins"][0], 0, 255);
            } else {
                $result["public_key_pins"] = substr($headers["public-key-pins"], 0, 255);
            }
        } else {
            $result["public_key_pins"] = 'not set';
        }
        if ($headers["public-key-pins-report-only"]) {
            if (is_array($headers["public-key-pins-report-only"])) {
                $result["public_key_pins_report_only"] = substr($headers["public-key-pins-report-only"][0], 0, 255);
            } else {
                $result["public_key_pins_report_only"] = substr($headers["public-key-pins-report-only"], 0, 255);
            }
        }
        // ocsp stapling
        $stapling = ocsp_stapling($host, $ip, $port);
        if ($stapling["working"] == 1) {
            $result["ocsp_stapling"] = $stapling;
        } else {
            if (filter_var(preg_replace('/[^A-Za-z0-9\\.\\:_-]/', '', $ip), FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
                // ipv6 openssl tools are broken. (https://rt.openssl.org/Ticket/Display.html?id=1365&user=guest&pass=guest)
                $result["warning"][] = 'OCSP Stapling not tested because of <a href="https://rt.openssl.org/Ticket/Display.html?id=1365&user=guest&pass=guest">bugs</a> in the OpenSSL tools and IPv6.';
            } else {
                $result["ocsp_stapling"] = "not set";
                $result["warning"][] = "OCSP Stapling not enabled.";
            }
        }
        $result["openssl_version"] = shell_exec("openssl version");
        $result["datetime_rfc2822"] = shell_exec("date --rfc-2822");
    }
    return $result;
}