Last active
October 29, 2020 01:10
-
-
Save padraic/8743811 to your computer and use it in GitHub Desktop.
Correct SSL/TLS Context Settings for file_get_contents() and other PHP stream calls under PHP 5.5 (or earlier)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
ini_set('display_errors', 1); | |
/** | |
* This script check how PHP makes HTTPS (SSL/TLS) requests using PHP Streams | |
* or cURL. Configuration options are passed as GET parameters, for example: | |
* http://localhost/checksslcontext.php?reconfigure=1 | |
* | |
* Configuration: | |
* http://localhost/checksslcontext.php | |
* Basic PHP Streams using file_get_contents(). Default settings. | |
* http://localhost/checksslcontext.php?reconfigure=1 | |
* As above but reconfigures SSL Context for PHP Streams to be secure. | |
* It will also reconfigure cURL (if selected) to use the Mozilla ciphersuite. | |
* http://localhost/checksslcontext.php?curl=1 | |
* Use cURL instead of PHP Streams (good to compare!) | |
* http://localhost/checksslcontext.php?qualys=1 | |
* Use the Qualys SSL Labs service instead of http://www.howsmyssl.com | |
* | |
* This script reflects result output from howsmyssl.com and ssllabs.com to your browser. | |
*/ | |
$reconfigure = isset($_GET['reconfigure']) ? (bool) $_GET['reconfigure'] : false; | |
$usecurl = isset($_GET['curl']) ? (bool) $_GET['curl'] : false; | |
$checkqualys = isset($_GET['qualys']) ? (bool) $_GET['qualys'] : false; | |
/** | |
* https://wiki.mozilla.org/Security/Server_Side_TLS#Recommended_Ciphersuite | |
*/ | |
$ciphers = implode(':', array( | |
'ECDHE-RSA-AES128-GCM-SHA256', | |
'ECDHE-ECDSA-AES128-GCM-SHA256', | |
'ECDHE-RSA-AES256-GCM-SHA384', | |
'ECDHE-ECDSA-AES256-GCM-SHA384', | |
'DHE-RSA-AES128-GCM-SHA256', | |
'DHE-DSS-AES128-GCM-SHA256', | |
'kEDH+AESGCM', | |
'ECDHE-RSA-AES128-SHA256', | |
'ECDHE-ECDSA-AES128-SHA256', | |
'ECDHE-RSA-AES128-SHA', | |
'ECDHE-ECDSA-AES128-SHA', | |
'ECDHE-RSA-AES256-SHA384', | |
'ECDHE-ECDSA-AES256-SHA384', | |
'ECDHE-RSA-AES256-SHA', | |
'ECDHE-ECDSA-AES256-SHA', | |
'DHE-RSA-AES128-SHA256', | |
'DHE-RSA-AES128-SHA', | |
'DHE-DSS-AES128-SHA256', | |
'DHE-RSA-AES256-SHA256', | |
'DHE-DSS-AES256-SHA', | |
'DHE-RSA-AES256-SHA', | |
'AES128-GCM-SHA256', | |
'AES256-GCM-SHA384', | |
'ECDHE-RSA-RC4-SHA', | |
'ECDHE-ECDSA-RC4-SHA', | |
'AES128', | |
'AES256', | |
'RC4-SHA', | |
'HIGH', | |
'!aNULL', | |
'!eNULL', | |
'!EXPORT', | |
'!DES', | |
'!3DES', | |
'!MD5', | |
'!PSK' | |
)); | |
if (!$checkqualys) { | |
$url = 'https://www.howsmyssl.com'; | |
$domain = 'howsmyssl.com'; | |
} else { | |
$url = 'https://www.ssllabs.com/ssltest/viewMyClient.html'; | |
$domain = 'www.ssllabs.com'; | |
} | |
$context = stream_context_create(array( | |
'ssl' => array( | |
'ciphers' => $ciphers, | |
'verify_peer' => true, | |
'cafile' => '/etc/ssl/certs/ca-certificates.crt', // <-- EDIT FOR NON-DEBIAN/UBUNTU SYSTEMS | |
'CN_match' => $domain, | |
'verify_depth' => 3, | |
'disable_compression' => true, | |
'SNI_enabled' => true, | |
'SNI_server_name' => $domain | |
) | |
)); | |
if (!$usecurl) { | |
if ($reconfigure) { | |
$html = file_get_contents($url, null, $context); | |
} else { | |
$html = file_get_contents($url); // This default will be BAD! | |
} | |
} else { | |
$ch = curl_init($url); | |
if ($reconfigure) { | |
curl_setopt($ch, CURLOPT_SSL_CIPHER_LIST, $ciphers); | |
} | |
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); | |
$html = curl_exec($ch); | |
curl_close($ch); | |
} | |
if (!$checkqualys) { | |
$html = str_replace('href="/', 'href="https://www.howsmyssl.com/', $html); | |
} else { | |
$html = str_replace('href="/', 'href="https://www.ssllabs.com/', $html); | |
} | |
echo $html; |
@rdlowrey, quite correct. Fixed that while adding the Qualys check. Thinking of now hitting the cURL guys to consider reordering their cipher list to emphasis perfect forward secrecy - worth a go! That would pretty much sync things up assuming PHP (or OpenSSL) follow through on updating the default ciphersuite.
Ciphers list updated:
// Ciphers recommended by Mozilla.
// https://wiki.mozilla.org/Security/Server_Side_TLS#Recommended_Ciphersuite
$ciphers = implode(':', array(
'ECDHE-RSA-AES128-GCM-SHA256',
'ECDHE-ECDSA-AES128-GCM-SHA256',
'ECDHE-RSA-AES256-GCM-SHA384',
'ECDHE-ECDSA-AES256-GCM-SHA384',
'DHE-RSA-AES128-GCM-SHA256',
'DHE-DSS-AES128-GCM-SHA256',
'kEDH+AESGCM',
'ECDHE-RSA-AES128-SHA256',
'ECDHE-ECDSA-AES128-SHA256',
'ECDHE-RSA-AES128-SHA',
'ECDHE-ECDSA-AES128-SHA',
'ECDHE-RSA-AES256-SHA384',
'ECDHE-ECDSA-AES256-SHA384',
'ECDHE-RSA-AES256-SHA',
'ECDHE-ECDSA-AES256-SHA',
'DHE-RSA-AES128-SHA256',
'DHE-RSA-AES128-SHA',
'DHE-DSS-AES128-SHA256',
'DHE-RSA-AES256-SHA256',
'DHE-DSS-AES256-SHA',
'DHE-RSA-AES256-SHA',
'!aNULL',
'!eNULL',
'!EXPORT',
'!DES',
'!RC4',
'!3DES',
'!MD5',
'!PSK',
));
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Oh, one comment: you also need to add the
"SNI_server_name" => 'howsmyssl.com'
in addition to the"SNI_enabled"
flag. As of PHP 5.6 where SNI and all the rest is auto-enabled for you this is no longer necessary.