Researchers at INRIA have published a new attack against TLS they called SLOTH. More details about it can be found at http://sloth-attack.org.
The problematic part, is that many frameworks (that is GnuTLS, OpenSSL, NSS) even if they don’t advertise support for MD5 hashes, would in fact accept messages signed with this obsolete and insecure hash.
Thus, to test properly if a server is vulnerable against this attack, we need a client that is misbehaving.
For easy writing of such test cases I have been working on the tlsfuzzer. Just released version of it was extended to be able test servers for vulnerability against the SLOTH attack (to be more precise, just the client impersonation attack – the most severe of the described ones).
Client impersonation attack
To test vulnerability of server to client impersonation attack, you will need the TLS server, set of a client certificate and key trusted by server and Python (any version since 2.6 or 3.2 will do). The full procedure for testing a server is as follows.
For testing we will need a set of certificates trusted by the server, in this case we will cheat a little and tell the server to trust a certificate directly.
openssl req -x509 -newkey rsa -keyout localuser.key \ -out localuser.crt -nodes -batch -subj /CN=Local\ User
openssl req -x509 -newkey rsa -keyout localhost.key -out localhost.crt -nodes -batch -subj /CN=localhost
The test client expects an HTTP server on localhost, on port 4433 that requests client certificates:
openssl s_server -key localhost.key -cert localhost.crt -verify 1 -www -tls1_2 -CAfile localuser.crt
The reproducer has a bit of dependencies on the system.
First thing, you will need python pip command. In case your distribution doesn’t provide it, download it from https://bootstrap.pypa.io/get-pip.py and run using python:
After that, install dependencies of tlsfuzzer:
pip install --pre tlslite-ng
Note: Installation may print an error: “error: invalid command ‘bdist_wheel'”, it can be ignored, it doesn’t break installation of package. In case you want to fix it anyway, upgrade setuptools package installed on your system by running:
pip install --upgrade setuptools
Finally download the reproducer itself:
git clone https://github.com/tomato42/tlsfuzzer.git
Once we have all pieces in place, we can run the reproducer as follows:
cd tlsfuzzer PYTHONPATH=. python scripts/test-certificate-verify.py -k /tmp/localuser.key -c /tmp/localuser.crt
(if you generated user certificates in /tmp directory)
If the execution finished with
MD5 CertificateVerify test version 4 MD5 forced... OK Sanity check... OK Test end successful: 2 failed: 0
That means that the server is not vulnerable.
In case the “MD5 forced” failed, but “Sanity check” resulted in “OK”, it means that the server is vulnerable.
Example failure may look like this:
MD5 CertificateVerify (CVE-2015-7575 aka SLOTH) test version 4 MD5 forced... Error encountered while processing node <tlsfuzzer.expect.ExpectClose object at 0xe3a410> with last message being: <tlslite.messages.Message object at 0xe3a8d0> Error while processing Traceback (most recent call last): File "scripts/test-certificate-verify.py", line 140, in main runner.run() File "/root/tlsfuzzer/tlsfuzzer/runner.py", line 139, in run msg.write())) AssertionError: Unexpected message from peer: ChangeCipherSpec() Sanity check... OK Test end successful: 1 failed: 1
(if the error was caused by Unexpected message from peer: ChangeCipherSpec, as shown above, it means that the server is definitely vulnerable)
In case the Sanity check failed, that may mean one of few things:
- the server is not listening on localhost on port 4433
- the server does not support TLS v1.2 protocol, in that case it is not vulnerable (note: this is NOT a good workaround)
- the server does not support TLS_RSA_WITH_AES_128_CBC_SHA cipher (AES128-SHA in OpenSSL naming system)
- the server did not ask for certificate on first connection attempt