1

I am trying to check which cipher suites can make a handshake with a server. I am using the script in the end of the post, which on his behalf is calling OpenSSL and the output is with the OpenSSL equvalents of the suites names.For example:

$./ciphers.sh stackoverflow.com:443
stackoverflow.com:443,SSL2(),SSL3(),TLS1(ECDHE-RSA-AES256-SHA:AES256-SHA:ECDHE-RSA-AES128-SHA:AES128-SHA),TLS1.1(ECDHE-RSA-AES256-SHA:AES256-SHA:ECDHE-RSA-AES128-SHA:AES128-SHA),TLS1.2(ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:AES256-SHA256:AES256-SHA:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:AES128-SHA256:AES128-SHA)

I can't figure out how to map them with the SSL/TLS cipher suites names. What I need is a list of the cipher names, like

TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA 
TLS_DHE_RSA_WITH_AES_128_CBC_SHA   
TLS_RSA_WITH_AES_128_CBC_SHA       
TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA
SSL_RSA_WITH_3DES_EDE_CBC_SHA 

but I just can't figure it out... Thank you for your help and time!

#!/usr/bin/env bash
ciphers2=$(openssl ciphers -ssl2 'ALL:eNULL' | sed -e 's/:/ /g')
ciphers3=$(openssl ciphers -ssl3 'ALL:eNULL' | sed -e 's/:/ /g')
cipherst1=$(openssl ciphers -tls1 'ALL:eNULL' | sed -e 's/:/ /g')
cipherst11=$(openssl ciphers -tls1.1 'ALL:eNULL' | sed -e 's/:/ /g')
cipherst12=$(openssl ciphers -tls1.2 'ALL:eNULL' | sed -e 's/:/ /g')

SSL2="SSL2("
for cipher in ${ciphers2[@]}
do
result=$(echo -n | openssl s_client -ssl2 -cipher "$cipher" -connect $1 2>&1)
if [[ "$result" =~ "Cipher is ${cipher}" ]] ; then
  SSL2="${SSL2}${cipher}:"
fi
done
SSL2=$(echo "${SSL2})" | sed -e 's/:)/)/g')

SSL3="SSL3("
for cipher in ${ciphers3[@]}
do
result=$(echo -n | openssl s_client -ssl3 -cipher "$cipher" -connect $1 2>&1)
if [[ "$result" =~ "Cipher is ${cipher}" ]] ; then
  SSL3="${SSL3}${cipher}:"
fi
done
SSL3=$(echo "${SSL3})" | sed -e 's/:)/)/g')
TLS1="TLS1("
for cipher in ${cipherst1[@]}
do
result=$(echo -n | openssl s_client -tls1 -cipher "$cipher" -connect $1 2>&1)
if [[ "$result" =~ "Cipher is ${cipher}" ]] ; then
  TLS1="${TLS1}${cipher}:"
fi
done
TLS1=$(echo "${TLS1})" | sed -e 's/:)/)/g')

TLS11="TLS1.1("
for cipher in ${cipherst11[@]}
do
result=$(echo -n | openssl s_client -tls1_1 -cipher "$cipher" -connect $1 2>&1)
if [[ "$result" =~ "Cipher is ${cipher}" ]] ; then
  TLS11="${TLS11}${cipher}:"
fi
done
TLS11=$(echo "${TLS11})" | sed -e 's/:)/)/g')

TLS12="TLS1.2("
for cipher in ${cipherst12[@]}
do
result=$(echo -n | openssl s_client -tls1_2 -cipher "$cipher" -connect $1 2>&1)
if [[ "$result" =~ "Cipher is ${cipher}" ]] ; then
  TLS12="${TLS12}${cipher}:"
fi
done
TLS12=$(echo "${TLS12})" | sed -e 's/:)/)/g')

echo "$1,$SSL2,$SSL3,$TLS1,$TLS11,$TLS12";
  • What output are you getting? You may also want to disable all the protocols you're not using in each `openssl`invocation with `-no_ssl2` or `-no_tls1_1` as appropriate for each invocation. And try emitting some debug data such as the cipher in question for each invocation. – Andrew Henle Apr 06 '16 at 22:47
  • And which version of OpenSSL are you running? I don't see `openssl ciphers` as having anything other than `-ssl2`, `-ssl3`, and `-tls1` options, for OpenSSL 1.0.2.f. There are no `-tls1.1` or `-tls1.2` options listed for `ciphers`. – Andrew Henle Apr 06 '16 at 22:59
  • A translation between openssl and RFC cipher names can be found at https://testssl.sh/openssl-rfc.mappping.html. – Steffen Ullrich Apr 07 '16 at 04:39
  • @AndrewHenle Specifying a single protocol in `s_client` like `-tls1` already disables all other protocols; the `-no_` options are only needed when you want to keep the default 'auto-negotiate' functionality (the now-badly-misnamed SSLv23_method) but partially restrict it. – dave_thompson_085 Apr 07 '16 at 06:05
  • @dave_thompson_085 But restricting that 'auto-negotiate' functionality seems to be exactly what's needed, since an arbitrary cipher suite may be implemented for multiple SSL/TLS versions, but the posted script looks to be testing if the cipher suite being tested is supported by the server on a specific SSL/TLS level. – Andrew Henle Apr 07 '16 at 12:59
  • @SteffenUllrich *A translation between openssl and RFC cipher names can be found at testssl.sh/openssl-rfc.mappping.html.* Nice. And `man ciphers | egrep 'SSL_|TLS_'` also provides a mapping for the OpenSSL version installed on a system, assuming the proper man page is accessed in the case of multiple installations. `openssl ciphers -V 'ALL:eNULL:aNULL'` will provide the hex cipher IDs, for OpenSSL >= 1.0.0, IIRC. [ssl-cipher-suite-enum.pl](https://github.com/portcullislabs/ssl-cipher-suite-enum) is a Perl script that does a good job of testing SSL connections. There's also `sslscan`. – Andrew Henle Apr 07 '16 at 13:03
  • Here's a thought I don't have time to script up and test: replace the lines like `TLS1="${TLS1}${cipher}:"` in each loop with `man ciphers | grep ${cipher} | grep TLS | awk '{ print $1 }'`. The `grep TLS` selects the TLS version of the cipher if there's a TLS and an SSL version. You'll have to replace `TLS` with `SSL` for the SSLv2 and SSLv3 tests. – Andrew Henle Apr 07 '16 at 13:26
  • @AndrewHenle yes this script wants to test each cipher in a specific protocol, but it DOES NOT NEED `-no_ssl2` or `-no_tls1_1` etc as you said; `s_client -ssl3` already does ONLY SSL3. Also: for the suites common to SSL3 and TLS(all) the actual code in Hello and the OpenSSL name is the same either way so selecting the TLS or SSL 'version' is meaningless; and OpenSSL actually implements in SSL3 all (AFAICT) suites defined for (not in) TLS1.0/1.1 with 'TLS_' names -- even EC suites without using the Hello extensions for EC! OTOH most 'SSL_' suites don't work in SSL2, and the rest not in SSL3. – dave_thompson_085 Apr 07 '16 at 21:51

1 Answers1

3

NAME MAPPING: OpenSSL uses its own set of ciphersuite names which are related to, but not the same as, the names in the RFCs used by most other implementations and documentation. See the man page for ciphers on your system (if Unix-like, and bash is mostly on Unix-like systems although it can be ported to others) under the heading "CIPHER SUITE NAMES" about halfway down. On some systems you may need to specify a section something like man 1ssl ciphers. Or online at (updated) https://www.openssl.org/docs/manmaster/man1/openssl-ciphers.html (use links at the right for specific release if necessary).

To manually convert an RFC name to OpenSSL: discard (leading) TLS or SSL and (embedded) WITH and change all _ to -; where the keyexchange is plain RSA (not [EC]DH[E]-RSA) discard it entirely; in some cases swap DHE to EDH (older versions only) and always swap DH_anon to ADH or ECDH_anon to AECDH; change 3DES_EDE_CBC in most cases to DES-CBC3; shorten EXPORT to EXP and move it to the beginning; drop bitlengths and CBC in some cases if not needed to disambiguate.

Note that anonymous suites have never been in included in the default list offered or accepted; export suites were removed from default starting with 1.0.0r 1.0.1m and 1.0.2a in 2015-03, and removed entirely and single-DES removed from default starting with 1.0.1s and 1.0.2g in 2016-03; 3DES RC4 SEED IDEA Camellia and DSS authentication (aka DSA) are not default in 1.1.0; SSL2 protocol has been disabled by default since 1.0.0 and is removed entirely in 1.1.0 released 2016-08; SSL3 is compiled out by default in 1.1.0 but can be added back (although you shouldn't use it, nor on lower releases, because it is broken by POODLE except for RC4 which has other flaws).

AVAILABILITY: ciphersuites fall in three classes in OpenSSL below 1.1.0: those for SSL2; those for SSL3 and up; and those for TLS1.2. SSL2 uses a different code scheme, so SSL2 suites can't be used for newer protocols or vice versa. To be pedantic, TLS1.0 dropped the Fortezza suites (which OpenSSL doesn't implement anyway) and TLS1.1 dropped the export suites, but OpenSSL still allowed them except as noted above. TLS1.2 on the other hand added a new format (AEAD) and a new PRF/KDF scheme, and with them a bunch of new ciphersuites that only work on TLS1.2; it also kept everything from TLS1.1 except single-DES and IDEA, which OpenSSL again still allowed except as above.

The -ssl2 -ssl3 -tls1 options on ciphers below 1.1.0 only limit you to suites compatible with that format, and all SSL3-up and TLS1.2 suites are compatible with both -ssl3 and -tls1; see the man page again. As @Andrew noted there were no options for -tls1.1 or -tls1.2 below 1.1.0 (edit) which adds options -tls1_1 and -tls1_2 (underscore not dot) which are still actually the same, and also adds an option -stdname to display the standard (RFC) name, avoiding the mapping issue -- but making the lines very long, IMHO unreadably so.

PS: if your goal is just to match, or pass, some audit scan that stupidly enumerates ciphers, this approach can work. If you are hoping to determine something useful about the security of a server, this is mostly a waste of time. It is enough that the server doesn't do SSL2 or SSL3 AT ALL (with any ciphersuite) and supports some decent ciphersuites and doesn't apply a bad preference (which this scan doesn't test); beyond that exactly which ciphersuites are supported matters much less to security than things like using good auth key and cert chain and maybe stapling, which this doesn't test; using good ephemeral parameters and randomness which are nearly impossible to test and this doesn't try; supporting features like 5746 and fallback and not having bugs like Heartbleed and CCS which this doesn't test; avoiding or mitigating compression issues which this doesn't test and in general may not be testable, and using record splitting as a best practice against BEAST which isn't practically testable; as well as all manner of issues above the SSL/TLS level.

Update: the above was written before TLS1.3 was published in 2018, and implemented by OpenSSL 1.1.1. TLS1.3 uses a completely new set of ciphersuites which specify only AEAD symmetric encryption (GCM, CCM, or ChaCha+Poly) which no longer uses HMAC at all, and KDF hash (the KDF being substantially changed and no longer called PRF); a 1.3 ciphersuite does not specify keyexchange and server authentication, as previous versions did. (Those are now handled by other parts of the protocol. See RFC 8446 for details.) For 1.3 suites OpenSSL uses the standard names, and also a separate, new API; commandline ciphers covers both 1.0-1.2 and 1.3 APIs. As noted above, SSL2 was entirely deleted as of 1.1.0, including all its unique ciphersuites.

dave_thompson_085
  • 34,712
  • 6
  • 50
  • 70