summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRemy <relst@relst.nl>2015-05-24 09:35:28 +0200
committerRemy <relst@relst.nl>2015-05-24 09:35:28 +0200
commit988f08b9eb952404b94817a973d1a19ff7c6524b (patch)
treeb23c940603507f240f377ba9278b49ae97dc6190
parent5e7e74fe94062683cce82c189cd43dd18c3aff9b (diff)
downloadssl-decoder-988f08b9eb952404b94817a973d1a19ff7c6524b.zip
ssl-decoder-988f08b9eb952404b94817a973d1a19ff7c6524b.tar.gz
ssl-decoder-988f08b9eb952404b94817a973d1a19ff7c6524b.tar.bz2
Add support for specific endpoints
-rw-r--r--CHANGELOG.md5
-rw-r--r--README.md8
-rw-r--r--functions/connection.php82
-rw-r--r--functions/crl.php8
-rw-r--r--functions/json.php15
-rw-r--r--functions/ocsp.php11
-rw-r--r--functions/tls_fallback_scsv.php11
-rw-r--r--functions/variables.php127
-rw-r--r--inc/form.php1
-rw-r--r--index.php28
-rw-r--r--json.php16
11 files changed, 218 insertions, 94 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index f5856b2..d764b6c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,10 @@
# Changelog
+## 2.5
+
+- Show specific endpoint picker when multiple A/AAAA records exist.
+- Add support for testing specific IP's with specific hostnames (instead of what DNS says)
+
## 2.4
- Add SSL Compressio check
diff --git a/README.md b/README.md
index 48fbb3b..0c048c9 100644
--- a/README.md
+++ b/README.md
@@ -32,6 +32,7 @@ Simple PHP script which decodes an SSL connection and/or certificate and display
- JSON API
- Warnings for bad connection settings or certificate options
- Heartbleed test
+- SNI specific testing
## Requirements
@@ -50,6 +51,8 @@ Unpack and go!
Browse to https://your-server/ssl-decoder.
+The default timeout for checks is 2 seconds. If this is to fast for your internal services, this can be raised in the `variables.php` file.
+
### OpenSSL compilation
If you want to use the latest OpenSSL and your distro doesn't shit with it you can compile your own OpenSSL and replace the system one. Do note that this might break stuff.
@@ -83,11 +86,10 @@ The SSL Decoder includes Piwik Javascript tracking code. If you self host it, yo
Endpoint: `/json.php`.
-
Accepts:
- CSR
- Certificate
-- Host (+port, default 443)
+- Host:ip (+port, default 443)
Returns JSON UTF-8 encoded certificate (and connection) data.
@@ -276,7 +278,7 @@ Example Response:
Params:
- - `host` = Hostname or IP address
+ - `host:ip` = Hostname:IP address
- `port` = port to test (443, 993, 465, 8443 etc).
- ciphersuites = 1 to enumerate ciphersuites supported by the tested server. Takes longer. If not specified or not 1, ciphersuites will not be tested, used ciphersuite will be reported.
diff --git a/functions/connection.php b/functions/connection.php
index 60b111f..5cb98ab 100644
--- a/functions/connection.php
+++ b/functions/connection.php
@@ -27,11 +27,13 @@ function get(&$var, $default=null) {
return isset($var) ? $var : $default;
}
-function server_http_headers($host, $port){
+function server_http_headers($host, $ip, $port){
+ global $timeout;
// first check if server is http. otherwise long timeout.
- $ch = curl_init(("https://" . $host . ":" . $port));
- curl_setopt($ch, CURLOPT_TIMEOUT, 2);
+ $ch = curl_init(("https://" . $ip . ":" . $port));
+ curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
curl_setopt($ch, CURLOPT_NOBODY, true);
+ curl_setopt($ch, CURLOPT_HTTPHEADER, array("Host: $host"));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_FAILONERROR, true);
curl_setopt($ch, CURLOPT_FRESH_CONNECT, true);
@@ -49,23 +51,25 @@ function server_http_headers($host, $port){
array("verify_peer" => false,
"capture_session_meta" => true,
"verify_peer_name" => false,
+ "peer_name" => $host,
"allow_self_signed" => true,
"sni_enabled" => true),
'http' => array(
'method' => 'GET',
'max_redirects' => 1,
- 'timeout' => 2
+ 'timeout' => $timeout
)
)
);
- $headers = get_headers("https://$host:$port", 1);
+ $headers = get_headers("https://$ip:$port", 1);
if (!empty($headers)) {
$headers = array_change_key_case($headers, CASE_LOWER);
return $headers;
}
}
-function ssl_conn_ciphersuites($host, $port, $ciphersuites){
+function ssl_conn_ciphersuites($host, $ip, $port, $ciphersuites) {
+ global $timeout;
$old_error_reporting = error_reporting();
error_reporting($old_error_reporting ^ E_WARNING);
$results = array();
@@ -75,9 +79,10 @@ function ssl_conn_ciphersuites($host, $port, $ciphersuites){
array("verify_peer" => false,
"verify_peer_name" => false,
"allow_self_signed" => true,
+ "peer_name" => $host,
'ciphers' => $value,
"sni_enabled" => true)));
- $read_stream = stream_socket_client("ssl://$host:$port", $errno, $errstr, 2, STREAM_CLIENT_CONNECT, $stream);
+ $read_stream = stream_socket_client("ssl://$ip:$port", $errno, $errstr, $timeout, STREAM_CLIENT_CONNECT, $stream);
if ( $read_stream === false ) {
$results[$value] = false;
} else {
@@ -88,7 +93,7 @@ function ssl_conn_ciphersuites($host, $port, $ciphersuites){
return $results;
}
-function test_heartbleed($host, $port) {
+function test_heartbleed($ip, $port) {
global $current_folder;
$exitstatus = 0;
$output = 0;
@@ -100,7 +105,7 @@ function test_heartbleed($host, $port) {
# check if python2 is available
exec("command -v python2 >/dev/null 2>&1", $cmdoutput, $cmdexitstatus);
if ($cmdexitstatus != 1) {
- exec("timeout 15 python2 " . getcwd() . "/inc/heartbleed.py " . escapeshellcmd($host) . " --json \"" . $tmpfile . "\" --threads 1 --port " . escapeshellcmd($port) . " --silent", $output, $exitstatus);
+ exec("timeout 15 python2 " . getcwd() . "/inc/heartbleed.py " . escapeshellcmd($ip) . " --json \"" . $tmpfile . "\" --threads 1 --port " . escapeshellcmd($port) . " --silent", $output, $exitstatus);
if (file_exists($tmpfile)) {
$json_data = json_decode(file_get_contents($tmpfile),true);
foreach ($json_data as $key => $value) {
@@ -118,10 +123,11 @@ function test_heartbleed($host, $port) {
return $result;
}
-function test_sslv2($host, $port) {
+function test_sslv2($ip, $port) {
+ global $timeout;
$exitstatus = 0;
$output = 0;
- exec('echo | timeout 2 openssl s_client -connect "' . escapeshellcmd($host) . ':' . escapeshellcmd($port) . '" -ssl2 2>&1 >/dev/null', $output, $exitstatus);
+ exec('echo | timeout ' . $timeout . ' openssl s_client -connect "' . escapeshellcmd($ip) . ':' . escapeshellcmd($port) . '" -ssl2 2>&1 >/dev/null', $output, $exitstatus);
if ($exitstatus == 0) {
$result = true;
} else {
@@ -130,12 +136,12 @@ function test_sslv2($host, $port) {
return $result;
}
-## python2 inc/heartbleed.py 85.222.224.236 --json tmp --max 1 --threads 1 --port 443
-
-function conn_compression($host, $port) {
+function conn_compression($host, $ip, $port) {
+ global $timeout;
$exitstatus = 0;
$output = 0;
- exec('echo | timeout 2 openssl s_client -connect "' . escapeshellcmd($host) . ':' . escapeshellcmd($port) . '" -status -tlsextdebug 2>&1 | grep -qe "^Compression: NONE"', $output, $exitstatus);
+ //pre_dump('echo | timeout ' . $timeout . ' openssl s_client -servername "' . escapeshellcmd($host) . '" -connect "' . escapeshellcmd($ip) . ':' . escapeshellcmd($port) . '" -status -tlsextdebug 2>&1 | grep -qe "^Compression: NONE"');
+ exec('echo | timeout ' . $timeout . ' openssl s_client -servername "' . escapeshellcmd($host) . '" -connect "' . escapeshellcmd($ip) . ':' . escapeshellcmd($port) . '" -status -tlsextdebug 2>&1 | grep -qe "^Compression: NONE"', $output, $exitstatus);
if ($exitstatus == 0) {
$result = false;
} else {
@@ -144,7 +150,8 @@ function conn_compression($host, $port) {
return $result;
}
-function ssl_conn_protocols($host, $port){
+function ssl_conn_protocols($host, $ip, $port) {
+ global $timeout;
$old_error_reporting = error_reporting();
error_reporting($old_error_reporting ^ E_WARNING);
$results = array('sslv2' => false,
@@ -159,10 +166,11 @@ function ssl_conn_protocols($host, $port){
array("verify_peer" => false,
"capture_session_meta" => true,
"verify_peer_name" => false,
+ "peer_name" => $host,
"allow_self_signed" => true,
'crypto_method' => STREAM_CRYPTO_METHOD_SSLv3_CLIENT,
"sni_enabled" => true)));
- $read_stream_sslv3 = stream_socket_client("sslv3://$host:$port", $errno, $errstr, 2, STREAM_CLIENT_CONNECT, $stream_sslv3);
+ $read_stream_sslv3 = stream_socket_client("sslv3://$ip:$port", $errno, $errstr, $timeout, STREAM_CLIENT_CONNECT, $stream_sslv3);
if ( $read_stream_sslv3 === false ) {
$results['sslv3'] = false;
} else {
@@ -173,10 +181,11 @@ function ssl_conn_protocols($host, $port){
array("verify_peer" => false,
"capture_session_meta" => true,
"verify_peer_name" => false,
+ "peer_name" => $host,
"allow_self_signed" => true,
'crypto_method' => STREAM_CRYPTO_METHOD_TLSv_1_0_CLIENT,
"sni_enabled" => true)));
- $read_stream_tlsv10 = stream_socket_client("tlsv1.0://$host:$port", $errno, $errstr, 2, STREAM_CLIENT_CONNECT, $stream_tlsv10);
+ $read_stream_tlsv10 = stream_socket_client("tlsv1.0://$ip:$port", $errno, $errstr, $timeout, STREAM_CLIENT_CONNECT, $stream_tlsv10);
if ( $read_stream_tlsv10 === false ) {
$results['tlsv1.0'] = false;
} else {
@@ -188,9 +197,10 @@ function ssl_conn_protocols($host, $port){
"capture_session_meta" => true,
"verify_peer_name" => false,
"allow_self_signed" => true,
+ "peer_name" => $host,
'crypto_method' => STREAM_CRYPTO_METHOD_TLSv_1_1_CLIENT,
"sni_enabled" => true)));
- $read_stream_tlsv11 = stream_socket_client("tlsv1.1://$host:$port", $errno, $errstr, 2, STREAM_CLIENT_CONNECT, $stream_tlsv11);
+ $read_stream_tlsv11 = stream_socket_client("tlsv1.1://$ip:$port", $errno, $errstr, $timeout, STREAM_CLIENT_CONNECT, $stream_tlsv11);
if ( $read_stream_tlsv11 === false ) {
$results['tlsv1.1'] = false;
} else {
@@ -202,9 +212,10 @@ function ssl_conn_protocols($host, $port){
"capture_session_meta" => true,
"verify_peer_name" => false,
"allow_self_signed" => true,
+ "peer_name" => $host,
'crypto_method' => STREAM_CRYPTO_METHOD_TLSv_1_2_CLIENT,
"sni_enabled" => true)));
- $read_stream_tlsv12 = stream_socket_client("tlsv1.2://$host:$port", $errno, $errstr, 2, STREAM_CLIENT_CONNECT, $stream_tlsv12);
+ $read_stream_tlsv12 = stream_socket_client("tlsv1.2://$ip:$port", $errno, $errstr, $timeout, STREAM_CLIENT_CONNECT, $stream_tlsv12);
if ( $read_stream_tlsv12 === false ) {
$results['tlsv1.2'] = false;
} else {
@@ -228,7 +239,7 @@ function ssl_conn_metadata($data) {
}
foreach ($data["warning"] as $key => $value) {
echo "<div class='alert alert-danger' role='alert'>";
- echo htmlspecialchars($value);
+ echo $value;
echo "</div>";
}
}
@@ -525,13 +536,18 @@ function ssl_conn_metadata($data) {
-function ssl_conn_metadata_json($host, $port, $read_stream, $chain_data=null) {
+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)) {
@@ -573,20 +589,18 @@ function ssl_conn_metadata_json($host, $port, $read_stream, $chain_data=null) {
unlink('/tmp/verify_cert.' . $random_blurp . '.pem');
}
// hostname ip port
- if (fixed_gethostbyname($host)) {
- $result["ip"] = fixed_gethostbyname($host);
- $result["hostname"] = gethostbyaddr(fixed_gethostbyname($host));
- $result["port"] = $port;
- }
+ $result["ip"] = $ip;
+ $result["hostname"] = gethostbyaddr($ip);
+ $result["port"] = $port;
//heartbleed
- $result['heartbleed'] = test_heartbleed($host, $port);
+ $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, $port);
+ $compression = conn_compression($host, $ip, $port);
if ($compression == false) {
$result["compression"] = false;
} else {
@@ -595,7 +609,7 @@ function ssl_conn_metadata_json($host, $port, $read_stream, $chain_data=null) {
}
// protocols
- $result["protocols"] = array_reverse(ssl_conn_protocols($host, $port));
+ $result["protocols"] = array_reverse(ssl_conn_protocols($host, $ip, $port));
foreach ($result["protocols"] as $key => $value) {
if ( $value == true ) {
if ( $key == "sslv2") {
@@ -731,7 +745,7 @@ function ssl_conn_metadata_json($host, $port, $read_stream, $chain_data=null) {
'NULL-SHA256',
'NULL-SHA',
'NULL-MD5');
- $tested_ciphersuites = ssl_conn_ciphersuites($host, $port, $ciphersuites_to_test);
+ $tested_ciphersuites = ssl_conn_ciphersuites($host, $ip, $port, $ciphersuites_to_test);
$result["supported_ciphersuites"] = array();
foreach ($tested_ciphersuites as $key => $value) {
if ($value == true) {
@@ -744,7 +758,7 @@ function ssl_conn_metadata_json($host, $port, $read_stream, $chain_data=null) {
$result["used_ciphersuite"]["bits"] = $context_meta['cipher_bits'];
}
// tls_fallback_scsv
- $fallback = tls_fallback_scsv($host, $port);
+ $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 {
@@ -756,7 +770,7 @@ function ssl_conn_metadata_json($host, $port, $read_stream, $chain_data=null) {
}
}
//hsts
- $headers = server_http_headers($host, $port);
+ $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);
@@ -785,7 +799,7 @@ function ssl_conn_metadata_json($host, $port, $read_stream, $chain_data=null) {
}
}
// ocsp stapling
- $stapling = ocsp_stapling($host,$port);
+ $stapling = ocsp_stapling($host, $ip, $port);
if($stapling["working"] == 1) {
$result["ocsp_stapling"] = $stapling;
} else {
diff --git a/functions/crl.php b/functions/crl.php
index 34cc794..35e57a5 100644
--- a/functions/crl.php
+++ b/functions/crl.php
@@ -15,7 +15,7 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
function crl_verify($raw_cert_data, $verbose=true) {
- global $random_blurp;
+ global $random_blurp, $timeout;
$cert_data = openssl_x509_parse($raw_cert_data);
$cert_serial_nm = strtoupper(bcdechex($cert_data['serialNumber']));
$crl_uris = [];
@@ -35,7 +35,7 @@ function crl_verify($raw_cert_data, $verbose=true) {
if (0 === strpos($uri, 'http')) {
$fp = fopen ("/tmp/" . $random_blurp . "." . $key . ".crl", 'w+');
$ch = curl_init(($uri));
- curl_setopt($ch, CURLOPT_TIMEOUT, 2);
+ curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
curl_setopt($ch, CURLOPT_FILE, $fp);
curl_setopt($ch, CURLOPT_FAILONERROR, true);
curl_setopt($ch, CURLOPT_FRESH_CONNECT, true);
@@ -100,7 +100,7 @@ function crl_verify($raw_cert_data, $verbose=true) {
function crl_verify_json($raw_cert_data) {
- global $random_blurp;
+ global $random_blurp, $timeout;
$result = [];
$cert_data = openssl_x509_parse($raw_cert_data);
$cert_serial_nm = strtoupper(bcdechex($cert_data['serialNumber']));
@@ -121,7 +121,7 @@ function crl_verify_json($raw_cert_data) {
$result[$crl_no]["crl_uri"] = $uri;
$fp = fopen ("/tmp/" . $random_blurp . "." . $key . ".crl", 'w+');
$ch = curl_init(($uri));
- curl_setopt($ch, CURLOPT_TIMEOUT, 2);
+ curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
curl_setopt($ch, CURLOPT_FILE, $fp);
curl_setopt($ch, CURLOPT_FAILONERROR, true);
curl_setopt($ch, CURLOPT_FRESH_CONNECT, true);
diff --git a/functions/json.php b/functions/json.php
index bbd9983..0abed70 100644
--- a/functions/json.php
+++ b/functions/json.php
@@ -15,17 +15,24 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
-function check_json($host,$port) {
+function check_json($host,$ip,$port) {
+ global $timeout;
$data = [];
$stream = stream_context_create (array("ssl" =>
array("capture_peer_cert" => true,
"capture_peer_cert_chain" => true,
"verify_peer" => false,
+ "peer_name" => $host,
"verify_peer_name" => false,
"allow_self_signed" => true,
"capture_session_meta" => true,
"sni_enabled" => true)));
- $read_stream = stream_socket_client("ssl://$host:$port", $errno, $errstr, 2, STREAM_CLIENT_CONNECT, $stream);
+ if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6 )) {
+ $connect_ip = "[" . $ip . "]";
+ } else {
+ $connect_ip = $ip;
+ }
+ $read_stream = stream_socket_client("ssl://$connect_ip:$port", $errno, $errstr, $timeout, STREAM_CLIENT_CONNECT, $stream);
if ( $read_stream === false ) {
$data["error"] = ["Failed to connect: " . htmlspecialchars($errstr)];
return $data;
@@ -44,8 +51,8 @@ function check_json($host,$port) {
$prev = $chain_data[$key-1];
$chain_key = (string)$key+1;
if ($key == 0) {
- $data["connection"] = ssl_conn_metadata_json($host, $port, $read_stream, $chain_data);
- $data["chain"][$chain_key] = cert_parse_json($curr, $next, $host, true);
+ $data["connection"] = ssl_conn_metadata_json($host, $ip, $port, $read_stream, $chain_data);
+ $data["chain"][$chain_key] = cert_parse_json($curr, $next, $host, $ip, true);
} else {
$data["chain"][$chain_key] = cert_parse_json($curr, $next, null, false);
}
diff --git a/functions/ocsp.php b/functions/ocsp.php
index ca8ada6..99b5f2d 100644
--- a/functions/ocsp.php
+++ b/functions/ocsp.php
@@ -14,9 +14,10 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
-function ocsp_stapling($host, $port){
+function ocsp_stapling($host, $ip, $port) {
+ global $timeout;
$result = "";
- $output = shell_exec('echo | timeout 2 openssl s_client -connect "' . escapeshellcmd($host) . ':' . escapeshellcmd($port) . '" -tlsextdebug -status 2>&1 | sed -n "/OCSP response:/,/---/p"');
+ $output = shell_exec('echo | timeout ' . $timeout . ' openssl s_client -servername "' . escapeshellcmd($host) . '" -connect "' . escapeshellcmd($ip) . ':' . escapeshellcmd($port) . '" -tlsextdebug -status 2>&1 | sed -n "/OCSP response:/,/---/p"');
if (strpos($output, "no response sent") !== false) {
$result = array("working" => 0,
"cert_status" => "No response sent");
@@ -45,7 +46,7 @@ function ocsp_stapling($host, $port){
}
function ocsp_verify_json($raw_cert_data, $raw_next_cert_data, $ocsp_uri) {
- global $random_blurp;
+ global $random_blurp, $timeout;
$result = array();
$tmp_dir = '/tmp/';
$root_ca = getcwd() . '/cacert.pem';
@@ -62,9 +63,9 @@ function ocsp_verify_json($raw_cert_data, $raw_next_cert_data, $ocsp_uri) {
//pre_dump('openssl ocsp -no_nonce -CAfile '.$root_ca.' -issuer '.$isser_loc.' -cert '.$tmp_dir.$random_blurp.'.cert_client.pem -url "'. escapeshellcmd($ocsp_uri) . '" -header "HOST" "'. escapeshellcmd($ocsp_host) . '" 2>&1');
- $output = shell_exec('openssl ocsp -no_nonce -CAfile '.$root_ca.' -issuer '.$isser_loc .' -cert '.$tmp_dir.$random_blurp.'.cert_client.pem -url "'. escapeshellcmd($ocsp_uri) . '" -header "HOST" "'. escapeshellcmd($ocsp_host) . '" 2>&1');
+ $output = shell_exec('timeout ' . $timeout . ' | openssl ocsp -no_nonce -CAfile '.$root_ca.' -issuer '.$isser_loc .' -cert '.$tmp_dir.$random_blurp.'.cert_client.pem -url "'. escapeshellcmd($ocsp_uri) . '" -header "HOST" "'. escapeshellcmd($ocsp_host) . '" 2>&1');
- $filter_output = shell_exec('openssl ocsp -no_nonce -CAfile '.$root_ca.' -issuer '.$isser_loc .' -cert '.$tmp_dir.$random_blurp.'.cert_client.pem -url "'. escapeshellcmd($ocsp_uri) . '" -header "HOST" "'. escapeshellcmd($ocsp_host) . '" 2>&1 | grep -v -e "to get local issuer certificate" -e "signer certificate not found" -e "Response Verify" -e "'. $tmp_dir.$random_blurp.'.cert_client.pem"');
+ $filter_output = shell_exec('timeout ' . $timeout . ' | openssl ocsp -no_nonce -CAfile '.$root_ca.' -issuer '.$isser_loc .' -cert '.$tmp_dir.$random_blurp.'.cert_client.pem -url "'. escapeshellcmd($ocsp_uri) . '" -header "HOST" "'. escapeshellcmd($ocsp_host) . '" 2>&1 | grep -v -e "to get local issuer certificate" -e "signer certificate not found" -e "Response Verify" -e "'. $tmp_dir.$random_blurp.'.cert_client.pem"');
$output = preg_replace("/[[:blank:]]+/"," ", $output);
$ocsp_status_lines = explode("\n", $output);
diff --git a/functions/tls_fallback_scsv.php b/functions/tls_fallback_scsv.php
index 3cf0ea1..dc58f11 100644
--- a/functions/tls_fallback_scsv.php
+++ b/functions/tls_fallback_scsv.php
@@ -14,16 +14,13 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
-function tls_fallback_scsv($host,$port) {
-
+function tls_fallback_scsv($host, $ip, $port) {
+ global $timeout;
$result = [];
- $protocols = ssl_conn_protocols($host, $port);
+ $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 2 openssl s_client -connect " . escapeshellcmd($host) . ":" . escapeshellcmd($port) . " -fallback_scsv -no_tls1_2 2>&1 >/dev/null");
- // echo "<pre>";
- // var_dump($fallback_test);
- // echo "</pre>";
+ $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;
}
diff --git a/functions/variables.php b/functions/variables.php
index 28caaa1..7384794 100644
--- a/functions/variables.php
+++ b/functions/variables.php
@@ -14,10 +14,15 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
+# timeout in seconds
+$timeout = 2;
+
+# Don't change stuff down here.
date_default_timezone_set('UTC');
-ini_set('default_socket_timeout', 2);
-$version = 2.4;
+$version = 2.5;
+
+ini_set('default_socket_timeout', 2);
$random_blurp = rand(1000,99999);
@@ -27,24 +32,122 @@ $ev_oids = array("1.3.6.1.4.1.34697.2.1", "1.3.6.1.4.1.34697.2.2", "1.3.6.1.4.1.
$current_folder = get_current_folder();
function parse_hostname($u_hostname){
- # format raymii.org:8080 should auto parse port.
- # parts[0]=hostname, parts[1]=port
+ # format raymii.org:1.2.34.56 should do SNI request to that ip.
+ # parts[0]=host, parts[1]=ip
$port = 0;
$hostname = 0;
- $parts = explode(":", $u_hostname);
- if ((1 <= $parts[1]) && ($parts[1] <= 65535)) {
- $parts[1] = preg_replace('/\\s+/', '', $parts[1]);
- $parts[1] = preg_replace('/[^A-Za-z0-9\._-]/', '', $parts[1]);
- $port = mb_strtolower($parts[1]);
- }
+ $parts = explode(":", $u_hostname, 2);
+
if (idn_to_ascii($parts[0])) {
$parts[0] = idn_to_ascii($parts[0]);
}
$parts[0] = preg_replace('/\\s+/', '', $parts[0]);
- $parts[0] = preg_replace('/[^A-Za-z0-9\.-]/', '', $parts[0]);
+ $parts[0] = preg_replace('/[^A-Za-z0-9\.\:-]/', '', $parts[0]);
$hostname = mb_strtolower($parts[0]);
- $result = array('hostname' => $hostname, 'port' => $port);
+
+ if (count($parts) > 1) {
+ $parts[1] = preg_replace('/\\s+/', '', $parts[1]);
+ $parts[1] = preg_replace('/[^A-Za-z0-9\.\:_-]/', '', $parts[1]);
+ if (filter_var($parts[1], FILTER_VALIDATE_IP, FILTER_FLAG_IPV6 ) or filter_var($parts[1], FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 )) {
+ $ip = mb_strtolower($parts[1]);
+ } else {
+ $ip = fixed_gethostbyname($hostname);
+ }
+ } else {
+ if (filter_var($hostname, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 )) {
+ $ip = $hostname;
+ } else {
+ $dns_a_records = dns_get_record($hostname, DNS_A);
+ $dns_aaaa_records = dns_get_record($hostname, DNS_AAAA);
+ $dns_records = array_merge($dns_a_records, $dns_aaaa_records);
+ if (count($dns_a_records) > 1 or count($dns_aaaa_records) > 1) {
+ $result = array('hostname' => $hostname, 'ip' => $ip, 'multiple_ip' => $dns_records);
+ return $result;
+ } else {
+ $ip = fixed_gethostbyname($hostname);
+ }
+ }
+ }
+ if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
+ $ip = "[" . $ip . "]";
+ }
+
+ $result = array('hostname' => $hostname, 'ip' => $ip);
return $result;
}
+function choose_endpoint($ips, $host, $port, $ciphersuites) {
+ echo "<div id='page-content-wrapper'>\n";
+ echo "<div class='container-fluid'>\n";
+ echo "<div class='row'>\n";
+ // if ajax-ed, don't show header again
+ if(empty($_SERVER['HTTP_X_REQUESTED_WITH']) || strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) != 'xmlhttprequest') {
+ echo "<div class='col-md-10 col-md-offset-1'>\n";
+ echo "<div class='page-header'>\n";
+ echo "<h1><a style='color:black;' href=\"";
+ echo(htmlspecialchars($current_folder));
+ echo "\">SSL Decoder</a></h1>\n";
+ echo "</div>\n";
+ }
+ echo "<div id='preloader'>\n";
+ echo "<p>\n";
+ echo "<img src=\"";
+ echo(htmlspecialchars($current_folder));
+ echo 'img/ajax-loader.gif" />';
+ echo "<br>&nbsp;<br>\n";
+ echo "The SSL Decoder is processing your request. Please wait a few moments.<br>\n";
+ echo "</p>\n";
+ echo "</div>\n";
+ echo "<div id='resultDiv'></div>\n";
+
+ echo "<div class='content'>\n<section id='choose_endpoint'>\n";
+ echo "<header>\n<h2>Multiple endpoints for " . htmlspecialchars($host) . "</h2>\n</header>\n";
+ echo "<p>We've found multiple results for " . htmlspecialchars($host) . ". Please choose the host you want to scan from the list below:</p>\n<br>\n";
+ echo "<ul>\n";
+ foreach ($ips as $ip) {
+ echo "<li>";
+ echo "<a href=\"";
+ echo htmlspecialchars($current_folder);
+ echo "?host=";
+ echo htmlspecialchars($host);
+ echo ":";
+ if ($ip['type'] == 'A') {
+ echo htmlspecialchars($ip['ip']);
+ } elseif ($ip['type'] == 'AAAA') {
+ echo "[";
+ echo htmlspecialchars($ip['ipv6']);
+ echo "]";
+ }
+ echo "&port=";
+ echo htmlspecialchars($port);
+ echo "&ciphersuites=";
+ if ($ciphersuites == 1) {
+ echo "1";
+ } else {
+ echo "0";
+ }
+ echo "\">";
+ if ($ip['type'] == 'A') {
+ echo htmlspecialchars($ip['ip']);
+ } elseif ($ip['type'] == 'AAAA') {
+ echo "[";
+ echo htmlspecialchars($ip['ipv6']);
+ echo "]";
+ }
+ echo " (port: ";
+ echo htmlspecialchars($port);
+ echo ")</a>";
+ echo "</li>";
+ }
+
+ echo "</ul>\n";
+ echo "</section></div>\n";
+ echo "</div>\n";
+ echo "</div>\n";
+ echo "</div>\n";
+
+ require_once("inc/footer.php");
+ exit;
+}
+
?>
diff --git a/inc/form.php b/inc/form.php
index ef00824..be35a6a 100644
--- a/inc/form.php
+++ b/inc/form.php
@@ -23,7 +23,6 @@
<div class="col-md-4 col-md-offset-1">
<div class="checkbox">
<label for="ciphersuites">
- <!-- <input type="checkbox" name="ciphersuites" id="ciphersuites" value="1" checked="checked"> -->
<input type="checkbox" name="ciphersuites" id="ciphersuites" value="1" checked="checked">
Enumerate Ciphersuites (takes longer)
</label>
diff --git a/index.php b/index.php
index 63b640a..990824e 100644
--- a/index.php
+++ b/index.php
@@ -45,17 +45,17 @@ foreach (glob("functions/*.php") as $filename) {
echo '<div id="wrapper">';
$data = [];
$hostname = mb_strtolower(get($_GET['host']));
- $host = parse_hostname($hostname);
- if ($host['port']) {
- $port = $host['port'];
- } else {
- $port = get($_GET['port'], '443');
- }
- $host = $host['hostname'];
+ $hostname = parse_hostname($hostname);
+ $host = $hostname['hostname'];
+ $port = get($_GET['port'], '443');
if ( !is_numeric($port) ) {
$port = 443;
}
- $data["data"] = check_json($host,$port);
+ if ($hostname['multiple_ip']) {
+ choose_endpoint($hostname['multiple_ip'], $host, $port, $_GET['ciphersuites']);
+ }
+ $ip = $hostname['ip'];
+ $data["data"] = check_json($host,$ip,$port);
if(isset($data["data"]["error"])) {
$data["error"] = $data["data"]["error"];
unset($data["data"]);
@@ -147,7 +147,7 @@ foreach (glob("functions/*.php") as $filename) {
// connection data
echo "<div class='content'><section id='conndata'>";
- echo "<header><h2>Connection Data for " . htmlspecialchars($host) . "</h2></header>";
+ echo "<header><h2>Connection Data for " . htmlspecialchars($host) . " / " . htmlspecialchars($ip) . "</h2></header>";
ssl_conn_metadata($data["data"]["connection"]);
echo "</section></div>";
@@ -184,14 +184,10 @@ foreach (glob("functions/*.php") as $filename) {
}
}
-
-
- ?>
- </div>
- </div>
- </div>
+ echo "</div>";
+ echo "</div>";
+ echo "</div>";
-<?php
require_once("inc/footer.php");
if ($write_cache == 1) {
diff --git a/json.php b/json.php
index 72b55fe..a915c38 100644
--- a/json.php
+++ b/json.php
@@ -10,13 +10,13 @@ foreach (glob("functions/*.php") as $filename) {
if ( isset($_GET['host']) && !empty($_GET['host'])) {
$data = [];
$hostname = mb_strtolower(get($_GET['host']));
- $host = parse_hostname($hostname);
- if ($host['port']) {
- $port = $host['port'];
- } else {
- $port = get($_GET['port'], '443');
- }
- $host = $host['hostname'];
+ $hostname = parse_hostname($hostname);
+ if ($hostname['multiple_ip']) {
+ $data["error"] = ["Host format is incorrect. (use \$host:\$ip.)"];
+ }
+ $host = $hostname['hostname'];
+ $ip = $hostname['ip'];
+ $port = get($_GET['port'], '443');
if ( !is_numeric($port) ) {
$port = 443;
}
@@ -25,7 +25,7 @@ if ( isset($_GET['host']) && !empty($_GET['host'])) {
$hostfilename = preg_replace("([\.]{2,})", '', $host);
$hostfilename = preg_replace("([^a-z0-9])", '', $host);
$cache_filename = (string) "results/saved." . $hostfilename . "." . $epoch . "." . $random_bla . ".api.json";
- $data["data"] = check_json($host,$port);
+ $data["data"] = check_json($host, $ip, $port);
} elseif(isset($_GET['csr']) && !empty($_GET['csr'])) {
$write_cache = 1;
$cache_filename = (string) "results/saved.csr." . $epoch . "." . $random_bla . ".api.json";