How do I list the SSL/TLS cipher suites a particular website offers?
How can I retrieve a list of the SSL/TLS cipher suites a particular website offers?
I've tried openssl, but if you examine the output:
$ echo -n | openssl s_client -connect www.google.com:443
CONNECTED(00000003)
depth=1 /C=ZA/O=Thawte Consulting (Pty) Ltd./CN=Thawte SGC CA
verify error:num=20:unable to get local issuer certificate
verify return:0
---
Certificate chain
0 s:/C=US/ST=California/L=Mountain View/O=Google Inc/CN=www.google.com
i:/C=ZA/O=Thawte Consulting (Pty) Ltd./CN=Thawte SGC CA
1 s:/C=ZA/O=Thawte Consulting (Pty) Ltd./CN=Thawte SGC CA
i:/C=US/O=VeriSign, Inc./OU=Class 3 Public Primary Certification Authority
---
Server certificate
-----BEGIN CERTIFICATE-----
MIIDITCCAoqgAwIBAgIQL9+89q6RUm0PmqPfQDQ+mjANBgkqhkiG9w0BAQUFADBM
MQswCQYDVQQGEwJaQTElMCMGA1UEChMcVGhhd3RlIENvbnN1bHRpbmcgKFB0eSkg
THRkLjEWMBQGA1UEAxMNVGhhd3RlIFNHQyBDQTAeFw0wOTEyMTgwMDAwMDBaFw0x
MTEyMTgyMzU5NTlaMGgxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlh
MRYwFAYDVQQHFA1Nb3VudGFpbiBWaWV3MRMwEQYDVQQKFApHb29nbGUgSW5jMRcw
FQYDVQQDFA53d3cuZ29vZ2xlLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkC
gYEA6PmGD5D6htffvXImttdEAoN4c9kCKO+IRTn7EOh8rqk41XXGOOsKFQebg+jN
gtXj9xVoRaELGYW84u+E593y17iYwqG7tcFR39SDAqc9BkJb4SLD3muFXxzW2k6L
05vuuWciKh0R73mkszeK9P4Y/bz5RiNQl/Os/CRGK1w7t0UCAwEAAaOB5zCB5DAM
BgNVHRMBAf8EAjAAMDYGA1UdHwQvMC0wK6ApoCeGJWh0dHA6Ly9jcmwudGhhd3Rl
LmNvbS9UaGF3dGVTR0NDQS5jcmwwKAYDVR0lBCEwHwYIKwYBBQUHAwEGCCsGAQUF
BwMCBglghkgBhvhCBAEwcgYIKwYBBQUHAQEEZjBkMCIGCCsGAQUFBzABhhZodHRw
Oi8vb2NzcC50aGF3dGUuY29tMD4GCCsGAQUFBzAChjJodHRwOi8vd3d3LnRoYXd0
ZS5jb20vcmVwb3NpdG9yeS9UaGF3dGVfU0dDX0NBLmNydDANBgkqhkiG9w0BAQUF
AAOBgQCfQ89bxFApsb/isJr/aiEdLRLDLE5a+RLizrmCUi3nHX4adpaQedEkUjh5
u2ONgJd8IyAPkU0Wueru9G2Jysa9zCRo1kNbzipYvzwY4OA8Ys+WAi0oR1A04Se6
z5nRUP8pJcA2NhUzUnC+MY+f6H/nEQyNv4SgQhqAibAxWEEHXw==
-----END CERTIFICATE-----
subject=/C=US/ST=California/L=Mountain View/O=Google Inc/CN=www.google.com
issuer=/C=ZA/O=Thawte Consulting (Pty) Ltd./CN=Thawte SGC CA
---
No client certificate CA names sent
---
SSL handshake has read 1777 bytes and written 316 bytes
---
New, TLSv1/SSLv3, Cipher is AES256-SHA
Server public key is 1024 bit
Compression: NONE
Expansion: NONE
SSL-Session:
Protocol : TLSv1
Cipher : AES256-SHA
Session-ID: 748E2B5FEFF9EA065DA2F04A06FBF456502F3E64DF1B4FF054F54817C473270C
Session-ID-ctx:
Master-Key: C4284AE7D76421F782A822B3780FA9677A726A25E1258160CA30D346D65C5F4049DA3D10A41F3FA4816DD9606197FAE5
Key-Arg : None
Start Time: 1266259321
Timeout : 300 (sec)
Verify return code: 20 (unable to get local issuer certificate)
---
it just shows that the cipher suite is something with AES256-SHA. I know I could grep through the hex dump of the conversation, but I was hoping for something a little more elegant.
I would prefer to do this on Linux, but Windows (or other) would be fine. This question is motivated by the security testing I do for PCI and general penetration testing.
Update:
GregS points out below that the SSL server picks from the cipher suites of the client. So it seems I would need to test all cipher suites one at a time. I think I can hack something together, but is there a simpler, more future-proof (e.g. new ciphers) way to do this?
Solution 1:
I wrote a bash script to test cipher suites. It gets a list of supported cipher suites from OpenSSL and tries to connect using each one. If the handshake is successful, it prints YES
. If the handshake isn't successful, it prints NO
, followed by the OpenSSL error text.
#!/usr/bin/env bash
# OpenSSL requires the port number.
SERVER=$1
DELAY=1
ciphers=$(openssl ciphers 'ALL:eNULL' | sed -e 's/:/ /g')
echo Obtaining cipher list from $(openssl version).
for cipher in ${ciphers[@]}
do
echo -n Testing $cipher...
result=$(echo -n | openssl s_client -cipher "$cipher" -connect $SERVER 2>&1)
if [[ "$result" =~ ":error:" ]] ; then
error=$(echo -n $result | cut -d':' -f6)
echo NO \($error\)
else
if [[ "$result" =~ "Cipher is ${cipher}" || "$result" =~ "Cipher :" ]] ; then
echo YES
else
echo UNKNOWN RESPONSE
echo $result
fi
fi
sleep $DELAY
done
Here's sample output showing 3 unsupported ciphers, and 1 supported cipher:
[@linux ~]$ ./test_ciphers 192.168.1.11:443
Obtaining cipher list from OpenSSL 0.9.8k 25 Mar 2009.
Testing ADH-AES256-SHA...NO (sslv3 alert handshake failure)
Testing DHE-RSA-AES256-SHA...NO (sslv3 alert handshake failure)
Testing DHE-DSS-AES256-SHA...NO (sslv3 alert handshake failure)
Testing AES256-SHA...YES
EDIT: Add flexibility as host and port are provided as parameter to the script
Solution 2:
Nmap with ssl-enum-ciphers
There is no better or faster way to get a list of available ciphers from a network service. Plus, nmap will provide a strength rating of strong, weak, or unknown for each available cipher.
First, download the ssl-enum-ciphers.nse nmap script (explanation here). Then from the same directory as the script, run nmap as follows:
List ciphers supported by an HTTP server
$ nmap --script ssl-enum-ciphers -p 443 www.example.com
List ciphers supported by an IMAP server
$ nmap --script ssl-enum-ciphers -p 993 mail.example.com
Here is a snippet of output from a Dovecot IMAP server:
993/tcp open imaps
| ssl-enum-ciphers:
| SSLv3:
| ciphers:
| TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA - strong
| TLS_DHE_RSA_WITH_AES_128_CBC_SHA - strong
| TLS_DHE_RSA_WITH_AES_256_CBC_SHA - strong
| TLS_RSA_WITH_IDEA_CBC_SHA - weak
...
| TLSv1.0:
| ciphers:
| TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA - strong
| TLS_DHE_RSA_WITH_AES_128_CBC_SHA - strong
| TLS_DHE_RSA_WITH_AES_256_CBC_SHA - strong
| TLS_RSA_WITH_IDEA_CBC_SHA - weak
...
|_ least strength: weak
Nmap done: 1 IP address (1 host up) scanned in 1.03 seconds
Solution 3:
Is there a tool that can test what SSL/TLS cipher suites a particular website offers?
Yes, you could use the online tool on SSL Labs' website to query the Public SSL Server Database.
Here is a snippet of information that it provides:
(screenshot from results of google.com)
Solution 4:
sslscan is a nice little utility.
It tests connecting with TLS and SSL (and the build script can link with its own copy of OpenSSL so that obsolete SSL versions are checked as well) and reports about the server's cipher suites and certificate.
Example output for google.com
(trimmed down for readability):
$ sslscan google.com
Testing SSL server google.com on port 443
TLS renegotiation:
Secure session renegotiation supported
TLS Compression:
Compression disabled
Heartbleed:
TLS 1.2 not vulnerable to heartbleed
TLS 1.1 not vulnerable to heartbleed
TLS 1.0 not vulnerable to heartbleed
Supported Server Cipher(s):
Preferred TLSv1.2 128 bits ECDHE-RSA-AES128-GCM-SHA256 Curve P-256 DHE 256
Accepted TLSv1.2 128 bits ECDHE-RSA-AES128-SHA Curve P-256 DHE 256
Accepted TLSv1.2 128 bits ECDHE-RSA-RC4-SHA Curve P-256 DHE 256
Accepted TLSv1.2 128 bits AES128-GCM-SHA256
Accepted TLSv1.2 128 bits AES128-SHA
<snip>
Preferred TLSv1.1 128 bits ECDHE-RSA-AES128-SHA Curve P-256 DHE 256
Accepted TLSv1.1 128 bits ECDHE-RSA-RC4-SHA Curve P-256 DHE 256
Accepted TLSv1.1 128 bits AES128-SHA
<snip>
Preferred TLSv1.0 128 bits ECDHE-RSA-AES128-SHA Curve P-256 DHE 256
Accepted TLSv1.0 128 bits ECDHE-RSA-RC4-SHA Curve P-256 DHE 256
Accepted TLSv1.0 128 bits AES128-SHA
<snip>
Preferred SSLv3 128 bits RC4-SHA
Accepted SSLv3 128 bits RC4-MD5
<snip>
SSL Certificate:
Signature Algorithm: sha256WithRSAEncryption
RSA Key Strength: 2048
Subject: *.google.com
Altnames: DNS:*.google.com, DNS:*.android.com, <snip>
Issuer: Google Internet Authority G2
Not valid before: Apr 7 08:24:31 2016 GMT
Not valid after: Jun 30 08:20:00 2016 GMT
Solution 5:
Since this is such a great reference thread for SSL scanning tools, I'll list CipherScan which was created a year ago and can also identify problems with key exchange ciphers. https://github.com/jvehent/cipherscan
If you want my fork which supports SNI and FreeBSD, the URL is https://github.com/oparoz/cipherscan
It's a script which calls openssl s_client
and supports using your own OpenSSL binary so that you can test upcoming features or new ciphers (chacha20+poly1305 per example).
It also lets you connect to any port you want and use starttlss.
Here is a typical output
# ./cipherscan -o ./openssl api.mycompany.com:443
...................
prio ciphersuite protocols pfs_keysize
1 DHE-RSA-AES256-GCM-SHA384 TLSv1.2 DH,4096bits
2 DHE-RSA-AES256-SHA256 TLSv1.2 DH,4096bits
3 ECDHE-RSA-AES256-GCM-SHA384 TLSv1.2 ECDH,P-384,384bits
4 ECDHE-RSA-AES256-SHA384 TLSv1.2 ECDH,P-384,384bits
5 DHE-RSA-AES128-GCM-SHA256 TLSv1.2 DH,4096bits
6 DHE-RSA-AES128-SHA256 TLSv1.2 DH,4096bits
7 ECDHE-RSA-AES128-GCM-SHA256 TLSv1.2 ECDH,P-384,384bits
8 ECDHE-RSA-AES128-SHA256 TLSv1.2 ECDH,P-384,384bits
9 DHE-RSA-CAMELLIA256-SHA TLSv1,TLSv1.1,TLSv1.2 DH,4096bits
10 DHE-RSA-AES256-SHA TLSv1,TLSv1.1,TLSv1.2 DH,4096bits
11 ECDHE-RSA-AES256-SHA TLSv1,TLSv1.1,TLSv1.2 ECDH,P-384,384bits
12 DHE-RSA-CAMELLIA128-SHA TLSv1,TLSv1.1,TLSv1.2 DH,4096bits
13 DHE-RSA-AES128-SHA TLSv1,TLSv1.1,TLSv1.2 DH,4096bits
14 ECDHE-RSA-AES128-SHA TLSv1,TLSv1.1,TLSv1.2 ECDH,P-384,384bits
15 CAMELLIA256-SHA TLSv1,TLSv1.1,TLSv1.2
16 AES256-SHA TLSv1,TLSv1.1,TLSv1.2
17 CAMELLIA128-SHA TLSv1,TLSv1.1,TLSv1.2
18 AES128-SHA TLSv1,TLSv1.1,TLSv1.2
Certificate: trusted, 4096 bit, sha256WithRSAEncryption signature
TLS ticket lifetime hint: 300
OCSP stapling: supported
And here are a list of options
-a | --allciphers Test all known ciphers individually at the end.
-b | --benchmark Activate benchmark mode.
-d | --delay Pause for n seconds between connections
-D | --debug Output ALL the information.
-h | --help Shows this help text.
-j | --json Output results in JSON format.
-o | --openssl path/to/your/openssl binary you want to use.
-v | --verbose Increase verbosity.
The json output is useful if you're calling this from other scripts.