Skip to content

Instantly share code, notes, and snippets.

@padraic
Last active October 29, 2020 01:10
Show Gist options
  • Star 14 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save padraic/8743811 to your computer and use it in GitHub Desktop.
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)
<?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
Copy link

rdlowrey commented Feb 1, 2014

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.

@padraic
Copy link
Author

padraic commented Feb 1, 2014

@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.

@josecelano
Copy link

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