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 CAverify error:num=20:unable to get local issuer certificateverify 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+mjANBgkqhkiG9w0BAQUFADBMMQswCQYDVQQGEwJaQTElMCMGA1UEChMcVGhhd3RlIENvbnN1bHRpbmcgKFB0eSkgTHRkLjEWMBQGA1UEAxMNVGhhd3RlIFNHQyBDQTAeFw0wOTEyMTgwMDAwMDBaFw0xMTEyMTgyMzU5NTlaMGgxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHFA1Nb3VudGFpbiBWaWV3MRMwEQYDVQQKFApHb29nbGUgSW5jMRcwFQYDVQQDFA53d3cuZ29vZ2xlLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA6PmGD5D6htffvXImttdEAoN4c9kCKO+IRTn7EOh8rqk41XXGOOsKFQebg+jNgtXj9xVoRaELGYW84u+E593y17iYwqG7tcFR39SDAqc9BkJb4SLD3muFXxzW2k6L05vuuWciKh0R73mkszeK9P4Y/bz5RiNQl/Os/CRGK1w7t0UCAwEAAaOB5zCB5DAMBgNVHRMBAf8EAjAAMDYGA1UdHwQvMC0wK6ApoCeGJWh0dHA6Ly9jcmwudGhhd3RlLmNvbS9UaGF3dGVTR0NDQS5jcmwwKAYDVR0lBCEwHwYIKwYBBQUHAwEGCCsGAQUFBwMCBglghkgBhvhCBAEwcgYIKwYBBQUHAQEEZjBkMCIGCCsGAQUFBzABhhZodHRwOi8vb2NzcC50aGF3dGUuY29tMD4GCCsGAQUFBzAChjJodHRwOi8vd3d3LnRoYXd0ZS5jb20vcmVwb3NpdG9yeS9UaGF3dGVfU0dDX0NBLmNydDANBgkqhkiG9w0BAQUFAAOBgQCfQ89bxFApsb/isJr/aiEdLRLDLE5a+RLizrmCUi3nHX4adpaQedEkUjh5u2ONgJd8IyAPkU0Wueru9G2Jysa9zCRo1kNbzipYvzwY4OA8Ys+WAi0oR1A04Se6z5nRUP8pJcA2NhUzUnC+MY+f6H/nEQyNv4SgQhqAibAxWEEHXw==-----END CERTIFICATE-----subject=/C=US/ST=California/L=Mountain View/O=Google Inc/CN=www.google.comissuer=/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-SHAServer public key is 1024 bitCompression: NONEExpansion: NONESSL-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:
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=$1DELAY=1ciphers=$(openssl ciphers 'ALL:eNULL' | sed -e 's/:/ /g')echo Obtaining cipher list from $(openssl version).for cipher in ${ciphers[@]}doecho -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 fifisleep $DELAYdone
Here’s sample output showing 3 unsupported ciphers, and 1 supported cipher:
[@linux ~]$ ./test_ciphers 192.168.1.11:443Obtaining 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