Verifying preferred SSL/TLS ciphers with Nmap

Published: 2014-08-11
Last Updated: 2014-08-11 09:45:56 UTC
by Bojan Zdrnja (Version: 1)
10 comment(s)

In last year or two, there has been a lot of talk regarding correct usage of SSL/TLS ciphers on web servers. Due to various incidents more or less known incidents, web sites today should use PFS (Perfect Forward Secrecy), a mechanism that is used when an SSL/TLS connection is established and symmetric keys exchanged. PFS ensures that, in case an attacker obtains the server??s private key, he cannot decrypt previous SSL/TLS connections to that server. If PFS is not used (if RSA is used to exchange symmetric keys), then the attacker can easily decrypt *all* previous SSL/TLS connections. That??s bad.

However, the whole process of choosing a cipher is not all that trivial. By default, the client will present its preferred cipher to use and as long as the server supports that cipher it will be selected. This is, obviously, not optimal in environments where we want to be sure that the most secure cipher will always be selected, so administrators quite often enable their servers so they get to pick the preferred cipher.

This allows an administrator to enable only ciphers he wants to have used, and additionally to define their priorities ?? the server will always try to pick the cipher with the highest priority (which should be ??the most secure one?). Only if the client does not support that cipher, the server will move to the next one and so on, until it finds one that is supported by the client (or, if it doesn??t, the SSL/TLS connection will fail!).

This is good and therefore I started recommending web server administrators to configure their servers so that PFS ciphers are turned on. However, at several occasions I noticed that the administrators incorrectly set the preferred cipher suite order on the server. This can result in non-PFS cipher suites selected, although both the server and the client support PFS.

As mentioned previously, this happens because the client sends the list of the supported ciphers and the server picks "the strongest one" according to its preferred list. 
SSL Labs' (https://www.ssllabs.com/ssltest) shows this when testing with reference browsers, but I wanted to be able to check this myself, from command line, especially when I'm testing servers that are not reachable to SSL Labs (or I don't want them to see the results).

So I modified the Nmap's ssl-enum-ciphers.nse script to list preferred ciphers in addition to just enumerating ciphers. I use this script a lot to list the supported ciphers, but I was missing the preferred ciphers list. Let??s take a look at the following example:

$ nmap -sT -PN -p 443 127.0.0.1 --script ssl-enum-ciphers.nse
Starting Nmap 6.46 ( http://nmap.org ) at 2014-08-11 09:15 UTC
Nmap scan report for 127.0.0.1
Host is up (0.00021s latency).
PORT    STATE SERVICE
443/tcp open  https
| ssl-enum-ciphers:
|   SSLv3: No supported ciphers found
|   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_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA - strong
|       TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA - strong
|       TLS_RSA_WITH_3DES_EDE_CBC_SHA - strong
|       TLS_RSA_WITH_AES_128_CBC_SHA - strong
|       TLS_RSA_WITH_AES_256_CBC_SHA - strong
|       TLS_RSA_WITH_CAMELLIA_128_CBC_SHA - strong
|       TLS_RSA_WITH_CAMELLIA_256_CBC_SHA - strong

|     preferred ciphers order:
|       TLS_RSA_WITH_AES_128_CBC_SHA
|       TLS_DHE_RSA_WITH_AES_128_CBC_SHA
|       TLS_DHE_RSA_WITH_AES_256_CBC_SHA
|       TLS_RSA_WITH_AES_256_CBC_SHA
|       TLS_RSA_WITH_3DES_EDE_CBC_SHA
|       TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA
|       TLS_RSA_WITH_CAMELLIA_256_CBC_SHA
|       TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA
|       TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA
|       TLS_RSA_WITH_CAMELLIA_128_CBC_SHA

|     compressors:
|       NULL

Now, things get interesting. You can see that the server supports the PFS ciphers (those starting with TLS_DHE are the PFS ciphers) in the original list ( in green). However, take a look at the preferred cipher list (in red). Since the TLS_RSA_WITH_AES_128_CBC_SHA is the preferred cipher by the server, absolutely every browser today (Mozilla, Chrome, IE, Safari) will end up using this cipher ?? since they all support it. So, even though PFS ciphers are enabled, they will never get used!

Of course, this is an error in the web server??s configuration. Let??s fix it so the PFS ciphers have higher priority and rerun the nmap script:

$ nmap -sT -PN -p 443 127.0.0.1 --script ssl-enum-ciphers.nse
Starting Nmap 6.46 ( http://nmap.org ) at 2014-08-11 09:15 UTC
Nmap scan report for 127.0.0.1
Host is up (0.00021s latency).
PORT    STATE SERVICE
443/tcp open  https
| ssl-enum-ciphers:
|   SSLv3: No supported ciphers found
|   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_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA - strong
|       TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA - strong
|       TLS_RSA_WITH_3DES_EDE_CBC_SHA - strong
|       TLS_RSA_WITH_AES_128_CBC_SHA - strong
|       TLS_RSA_WITH_AES_256_CBC_SHA - strong
|       TLS_RSA_WITH_CAMELLIA_128_CBC_SHA - strong
|       TLS_RSA_WITH_CAMELLIA_256_CBC_SHA - strong

|     preferred ciphers order:
|       TLS_DHE_RSA_WITH_AES_128_CBC_SHA
|       TLS_DHE_RSA_WITH_AES_256_CBC_SHA
|       TLS_RSA_WITH_AES_128_CBC_SHA
|       TLS_RSA_WITH_AES_256_CBC_SHA
|       TLS_RSA_WITH_3DES_EDE_CBC_SHA
|       TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA
|       TLS_RSA_WITH_CAMELLIA_256_CBC_SHA
|       TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA
|       TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA
|       TLS_RSA_WITH_CAMELLIA_128_CBC_SHA

|     compressors:
|       NULL

Much better! Now the PFS ciphers are preferred and most browser will use them. We can even confirm this with SSL Labs ?? all relatively new browsers, that support PFS will pick those ciphers.

So, if you want to use this script to test your servers, you can find it at https://github.com/bojanisc/nmap-scripts - please report any bugs to me.

Finally, I also submitted it to Nmap so hopefully it will get added into the official distribution. There is a bug that Daniel Miller noticed ?? in case a server supports more than 64 ciphers, and the server is running on Microsoft Windows, the script will fail to list the preferred ciphers.

The reason for this is that, when a client connects, Microsoft (the Schannel component I presume) takes into account only the first 64 ciphers listed by the client. The other ciphers are ignored. This is the reason why the original ssl-enum-ciphers.nse Nmap script splits ciphers into chunks of 64. No idea why Microsoft did it this was (since the spec says that the client can include as many as it wants). However, it??s clearly a problem.

Now, I haven??t seen any web servers that support more than 64 ciphers in the wild ?? let me know if you find one. Additionally, according to this article: http://msdn.microsoft.com/en-us/library/windows/desktop/bb870930%28v=vs.85%29.aspx, the list of cipher suites on Windows is limited to 1023 characters.
Since most cipher names are 20+ characters, this could mean that you can't really have more than ~50 ciphers active on a Windows machine - I haven't tested this though.

 

--
Bojan
bojanz@twitter
INFIGO IS

Keywords: nmap pfs ssl tls
10 comment(s)
ISC StormCast for Monday, August 11th 2014 http://isc.sans.edu/podcastdetail.html?id=4099

Comments


Diary Archives