Security – 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 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