How to test which SSL/TLS protocols & ciphersuites are offered by a server

Solution Verified - Updated

Environment

  • some service offering SSL/TLS

Issue

  • How can we confirm what SSL or TLS protocol versions are allowed by an SSL/TLS service on a server?

  • How can we programmatically determine what SSL ciphersuites are being offered to clients of our server without looking at the server configuration?

Resolution

Two choices are detailed in this article:

See also: Securing Application 'X' with SSL/TLS in RHEL 'Y'


Option 1: Use openssl s_client to probe a target server

  • The openssl s_client command supports choosing a specific TLS protocol and disabling specific protocols

    1. Start by checking what client protocols are supported by the local openssl s_client command
      The following example output is from a RHEL 7.2 system

      [user@host ~]$ openssl s_client help 2>&1 | egrep 'just.use|no_tls'
        -ssl2         - just use SSLv2
        -ssl3         - just use SSLv3
        -tls1_2       - just use TLSv1.2
        -tls1_1       - just use TLSv1.1
        -tls1         - just use TLSv1
        -dtls1        - just use DTLSv1
        -no_tls1_2/-no_tls1_1/-no_tls1/-no_ssl3/-no_ssl2 - turn off that protocol
       
    2. Test whether a target server supports a specific protocol
      The following example output shows that the target server does not support SSLv3

      [user@host ~]$ openssl s_client -connect localhost:443 -ssl3 <<<"" 2>/dev/null | grep -A2 ^New
       New, (NONE), Cipher is (NONE)
       Secure Renegotiation IS NOT supported
       Compression: NONE
       

      The following example output shows that the target server supports TLSv1.2

      [user@host ~]$ openssl s_client -connect localhost:443 -tls1_2 <<<"" 2>/dev/null | grep -A2 ^New
       New, TLSv1/SSLv3, Cipher is ECDHE-RSA-AES256-GCM-SHA384
       Server public key is 2048 bit
       Secure Renegotiation IS supported
       
    *Note that the target server in this case was "localhost"; change as necessary by specifying a DNS name or IP address*
    
  • The openssl s_client command also supports choosing specific ciphers for the connection attempt

    1. Start by checking what client ciphersuites are supported by the local openssl s_client command
      The following example output is from a RHEL 7.2 system

      [user@host ~]$ openssl s_client help 2>&1 | grep -A1 cipher
        -serverpref   - Use server's cipher preferences (only SSLv2)
        -cipher       - preferred cipher to use, use the 'openssl ciphers'
                        command to see what is available
       [user@host ~]$ openssl ciphers -h
       usage: ciphers args
        -v          - verbose mode, a textual listing of the SSL/TLS ciphers in OpenSSL
        -V          - even more verbose
        -ssl2       - SSL2 mode
        -ssl3       - SSL3 mode
        -tls1       - TLS1 mode
       [user@host ~]$ openssl ciphers
       ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-DSS-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA256:DHE-RSA-AES256-SHA:DHE-DSS-AES256-SHA:DHE-RSA-CAMELLIA256-SHA:DHE-DSS-CAMELLIA256-SHA:ECDH-RSA-AES256-GCM-SHA384:ECDH-ECDSA-AES256-GCM-SHA384:ECDH-RSA-AES256-SHA384:ECDH-ECDSA-AES256-SHA384:ECDH-RSA-AES256-SHA:ECDH-ECDSA-AES256-SHA:AES256-GCM-SHA384:AES256-SHA256:AES256-SHA:CAMELLIA256-SHA:PSK-AES256-CBC-SHA:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:DHE-DSS-AES128-GCM-SHA256:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES128-SHA256:DHE-DSS-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:ECDHE-ECDSA-DES-CBC3-SHA:DHE-RSA-SEED-SHA:DHE-DSS-SEED-SHA:DHE-RSA-CAMELLIA128-SHA:DHE-DSS-CAMELLIA128-SHA:EDH-RSA-DES-CBC3-SHA:EDH-DSS-DES-CBC3-SHA:ECDH-RSA-AES128-GCM-SHA256:ECDH-ECDSA-AES128-GCM-SHA256:ECDH-RSA-AES128-SHA256:ECDH-ECDSA-AES128-SHA256:ECDH-RSA-AES128-SHA:ECDH-ECDSA-AES128-SHA:ECDH-RSA-DES-CBC3-SHA:ECDH-ECDSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES128-SHA256:AES128-SHA:SEED-SHA:CAMELLIA128-SHA:DES-CBC3-SHA:IDEA-CBC-SHA:PSK-AES128-CBC-SHA:PSK-3DES-EDE-CBC-SHA:KRB5-IDEA-CBC-SHA:KRB5-DES-CBC3-SHA:KRB5-IDEA-CBC-MD5:KRB5-DES-CBC3-MD5:ECDHE-RSA-RC4-SHA:ECDHE-ECDSA-RC4-SHA:ECDH-RSA-RC4-SHA:ECDH-ECDSA-RC4-SHA:RC4-SHA:RC4-MD5:PSK-RC4-SHA:KRB5-RC4-SHA:KRB5-RC4-MD5
       
    2. Test whether a target server supports a specific ciphersuite (or colon-separated list of ciphersuites)
      The following example output shows requesting a very restrictive list of ciphersuites and confirms that the target server doesn't support any of them

      [user@host ~]$ openssl s_client -connect localhost:443 -cipher RC4-SHA:RC4-MD5:PSK-RC4-SHA <<<"" 2>/dev/null | grep -A2 ^New
       New, (NONE), Cipher is (NONE)
       Secure Renegotiation IS NOT supported
       Compression: NONE
       
    *Note that many ciphersuites can be used by multiple protocols and in some cases it might be useful to combine the `-cipher CIPHERLIST` option with one of the protocol options*
    

Option 2: Use open source 3rd-party cipherscan tool

Content from github.com is not included.cipherscan is a 3rd-party unsupported tool; however, it is extremely simple to use

Important note: cipherscan uses openssl to act as an SSL/TLS client, so what it sees will depend on the openssl version used.1

  1. Clone the cipherscan git repository (via git clone) or download the static zip file
    Note: this does not need to be done as root
    The following example shows downloading and extracting the zip file

    [user@host ~]$ curl -sLO https://github.com/mozilla/cipherscan/archive/master.zip
     [user@host ~]$ unzip -q master.zip 
     [user@host ~]$ cd cipherscan-master/
     [user@host cipherscan-master]$
     
  2. Use the cipherscan command against the target (local or remote)
    For advanced usage, check cipherscan --help (e.g., using -starttls option for specific protocols like smtp or ftp)
    The following is an example of testing against the localhost webserver running on port 443

    [user@host cipherscan-master]$ ./cipherscan $(hostname):443
     ............................................
     Target: host.example.com:443
    
     prio  ciphersuite                  protocols              pfs                 curves
     1     ECDHE-RSA-AES256-GCM-SHA384  TLSv1.2                ECDH,P-256,256bits  prime256v1,secp384r1,secp521r1
     2     ECDHE-RSA-AES256-SHA384      TLSv1.2                ECDH,P-256,256bits  prime256v1,secp384r1,secp521r1
     3     ECDHE-RSA-AES128-GCM-SHA256  TLSv1.2                ECDH,P-256,256bits  prime256v1,secp384r1,secp521r1
     4     ECDHE-RSA-AES128-SHA256      TLSv1.2                ECDH,P-256,256bits  prime256v1,secp384r1,secp521r1
     5     ECDHE-RSA-AES256-SHA         TLSv1,TLSv1.1,TLSv1.2  ECDH,P-256,256bits  prime256v1,secp384r1,secp521r1
     6     ECDHE-RSA-AES128-SHA         TLSv1,TLSv1.1,TLSv1.2  ECDH,P-256,256bits  prime256v1,secp384r1,secp521r1
     7     DHE-RSA-AES256-GCM-SHA384    TLSv1.2                DH,2048bits         None
     8     DHE-RSA-AES256-SHA256        TLSv1.2                DH,2048bits         None
     9     DHE-RSA-AES128-GCM-SHA256    TLSv1.2                DH,2048bits         None
     10    DHE-RSA-AES128-SHA256        TLSv1.2                DH,2048bits         None
     11    DHE-RSA-AES256-SHA           TLSv1,TLSv1.1,TLSv1.2  DH,2048bits         None
     12    DHE-RSA-AES128-SHA           TLSv1,TLSv1.1,TLSv1.2  DH,2048bits         None
     13    DHE-RSA-CAMELLIA256-SHA      TLSv1,TLSv1.1,TLSv1.2  DH,2048bits         None
     14    DHE-RSA-CAMELLIA128-SHA      TLSv1,TLSv1.1,TLSv1.2  DH,2048bits         None
     15    AES256-GCM-SHA384            TLSv1.2                None                None
     16    AES256-SHA256                TLSv1.2                None                None
     17    AES128-GCM-SHA256            TLSv1.2                None                None
     18    AES128-SHA256                TLSv1.2                None                None
     19    AES256-SHA                   TLSv1,TLSv1.1,TLSv1.2  None                None
     20    AES128-SHA                   TLSv1,TLSv1.1,TLSv1.2  None                None
     21    CAMELLIA256-SHA              TLSv1,TLSv1.1,TLSv1.2  None                None
     22    CAMELLIA128-SHA              TLSv1,TLSv1.1,TLSv1.2  None                None
    
     Certificate: untrusted, 2048 bits, sha256WithRSAEncryption signature
     TLS ticket lifetime hint: 300
     OCSP stapling: not supported
     Cipher ordering: server
     Curves ordering: server - fallback: no
     Server supports secure renegotiation
     Server supported compression methods: NONE
     TLS Tolerance: yes
     
  3. Optionally use analyze.py to compare target server against the TLS guidelines from Content from wiki.mozilla.org is not included.wiki.mozilla.org/Security/Server_Side_TLS
    This will return recommendations to meet each configuration level
    The following example shows testing this against a local webserver running on port 443

    [user@host cipherscan-master]$ ./analyze.py -t $(hostname):443
     host.example.com:443 has bad ssl/tls
    
     Things that are bad:
     * don't use an untrusted or self-signed certificate
    
     Changes needed to match the old level:
     * enable TLSv1
     * enable SSLv3
     * add cipher DES-CBC3-SHA
     * use a certificate with sha1WithRSAEncryption signature
     * use DHE of 1024bits and ECC of 160bits
     * consider enabling OCSP Stapling
    
     Changes needed to match the intermediate level:
     * remove cipher DHE-RSA-CAMELLIA256-SHA
     * remove cipher DHE-RSA-CAMELLIA128-SHA
     * remove cipher CAMELLIA256-SHA
     * remove cipher CAMELLIA128-SHA
     * consider enabling TLSv1
     * consider enabling OCSP Stapling
    
     Changes needed to match the modern level:
     * remove cipher ECDHE-RSA-AES256-SHA
     * remove cipher ECDHE-RSA-AES128-SHA
     * remove cipher DHE-RSA-AES256-GCM-SHA384
     * remove cipher DHE-RSA-AES256-SHA256
     * remove cipher DHE-RSA-AES128-GCM-SHA256
     * remove cipher DHE-RSA-AES128-SHA256
     * remove cipher DHE-RSA-AES256-SHA
     * remove cipher DHE-RSA-AES128-SHA
     * remove cipher DHE-RSA-CAMELLIA256-SHA
     * remove cipher DHE-RSA-CAMELLIA128-SHA
     * remove cipher AES256-GCM-SHA384
     * remove cipher AES256-SHA256
     * remove cipher AES128-GCM-SHA256
     * remove cipher AES128-SHA256
     * remove cipher AES256-SHA
     * remove cipher AES128-SHA
     * remove cipher CAMELLIA256-SHA
     * remove cipher CAMELLIA128-SHA
     * disable TLSv1.1
     * consider enabling OCSP Stapling
     
1

Note that the cipherscan tool comes with an openssl binary which requires GLIBC 2.14 (so it works on RHEL7, but not RHEL6). cipherscan also allows specifying a custom path to an openssl binary with the -o option.

Components
Category

This solution is part of Red Hat’s fast-track publication program, providing a huge library of solutions that Red Hat engineers have created while supporting our customers. To give you the knowledge you need the instant it becomes available, these articles may be presented in a raw and unedited form.