Monday, July 18, 2011

Decrypting SSL traffic with Wireshark, and ways to prevent it


A neat feature of Wireshark is the ability to decrypt SSL traffic. This post is about why you might want to do it, how to do it, why it works, and how to decrease the chances of other people being able to decrypt your “secure” traffic.

Why decrypt SSL?

Aside from the obvious malicious uses, decrypting SSL has uses such as:
  • Debugging applications that run over SSL (HTTP, SMTP, POP3, IMAP, FTP, etc).
  • Feeding a decrypted traffic stream to an IDS. Having the best signatures in the world won’t help if all your sensors see is encrypted traffic.
  • Learning about SSL. What better way to understand something than to take it apart and put it back together again?

How to decrypt SSL with Wireshark

Step one – set up an SSL-protected server to use as a testbed
To illustrate the process, we’re going to use OpenSSL to generate a certificate and act as a web server running HTTP over SSL (aka HTTPS) – it’s quite straightforward.
To begin with, we need to get ourselves a self-signed certificate that our HTTPS server can use. We can do this with a single command:
openssl req -x509 -nodes -newkey rsa:1024 -keyout testkey.pem -out testcert.pem
OpenSSL will ask you for some input to populate your certificate with; once you’ve answered all the questions, the output of this command is two files, testkey.pem (containing a 1024 bit RSA private key) and testcert.pem (containing a self signed certificate). PEM (Privacy Enhanced Mail) format files are plaintext, and consist of a BASE64 encoded body with header and footer lines. You can look at the contents of your key and certificate files in more detail like this:
openssl rsa -in testkey.pem -text -noout (output here)
openssl x509 -in testcert.pem -text -noout (output here; more infohere)
We need to perform one tiny tweak to the format of the private key file (Wireshark will use this later on, and it won’t work properly until we’ve done this):
openssl rsa -in testkey.pem -out testkey.pem
Now we’re ready to fire up our HTTPS server:
openssl s_server -key testkey.pem -cert testcert.pem -WWW -cipher RC4-SHA -accept 443
The -key and -cert parameters to the s_server command reference the files we’ve just created, and the -WWW parameter (this one is case sensitive) causes OpenSSL to act like a simple web server capable of retrieving files in the current directory (I created a simple test file called myfile.html for the purposes of the test).
The -cipher parameter tells the server to use a particular cipher suite – I’m using RC4-SHA because that’s what’s used when you go tohttps://www.google.com. The RC4-SHA cipher suite will use RSA keys for authentication and key exchange, 128-bit RC4 for encryption, and SHA1 for hashing.
Having got our server up and running, we can point a browser at https://myserver/myfile.html and retrieve our test file via SSL (you can ignore any warnings about the validity of the certificate). If you’ve got this working, we can move on to…
Step two – capture some traffic with Wireshark
Fire up Wireshark on the server machine, ideally with a capture filter like “tcp port 443″ so that we don’t capture any unnecessary traffic. Once we’re capturing, point your browser (running on a different machine) at https://myserver/myfile.html and stop the capture once it’s complete.
Right-click on any of the captured frames and select “Follow TCP stream” – a window will pop up that’s largely full of SSL-protected gobbledegook:

Step three – configuring Wireshark for decryption
Close the TCP Stream window and select Preferences from Wireshark’s Edit menu. Expand the “Protocols” node in the tree on the left and scroll down to SSL (in newer versions of Wireshark, you can open the node and type SSL and it will take you there).
Once SSL is selected, there’s an option on the right to enter an “RSA keys list”. Enter something like this:
10.16.8.5,443,http,c:\openssl-win32\bin\testkey.pem
You’ll need to edit the server IP address and path to testkey.pem as appropriate. If this has worked, we’ll notice two things:
  • Wireshark’s SSL dissector can look into otherwise encrypted SSL packets and dissect the protocol inside:
  • We can right-click on any of the captured frames that are listed as SSL or TLS and select “Follow SSL stream”:
Nice :)
You can read about this step in the Wireshark Wiki here.

Why it works

So, why does this work? Our test server, in common with a very large proportion of HTTP-over-SSL webservers, is using RSA to exchange the symmetric session key that will be used by the encryption algorithm (RC4 in this case). Below is an extract from RFC2246:
F.1.1.2. RSA key exchange and authentication
With RSA, key exchange and server authentication are combined. The public key may be either contained in the server’s certificate or may be a temporary RSA key sent in a server key exchange message.
After verifying the server’s certificate, the client encrypts a pre_master_secret with the server’s public key.
The server can of course decrypt the pre_master_secret passed to it by the client (by using the server’s private key in testkey.pem), and subsequently both the client and the server derive the master_secret from it – this is the symmetric key that both parties will use with RC4 to encrypt the session.
But the server isn’t the only one with the private key that corresponds to the public key in the server’s certificate – Wireshark has it as well. This means it is able to decrypt the pre_master_secret on its way from the client to the server, and thereafter derive the master_secret needed to decrypt the traffic.

How to prevent decryption

There are at least two methods to approach this:
Method one – Protect the server’s private key
Protection of one’s private key is at the core of any system using asymmetric keys. If your private key is compromised, the attacker can either masquerade as you or they can attempt to carry out decryption as outlined above. Keys stored in separate files like the ones above are particularly vulnerable to theft if access permissions are not set strictly enough, or if some other vulnerability allows access. Certain operating systems like Windows and Cisco’s IOS will try to protect the keys on your behalf by marking them as “non-exportable”. This is meant to mean that the OS won’t divulge the private key to anyone under any circumstances, but clearly there comes a point where some software running on the box has to access the key in order to use it. This simple fact can sometimes be exploited to export non-exportable keys – a practical attack is described in a past edition of Hakin9 magazine. You can download it for free; here’s a quote from the article:
The Operating System (Windows XP in this case) does not let you export the private key of a certificate if it is marked as non-exportable. However, the OS must have access to read the private key in order to use it for signing and encrypting. If the OS can access the private key and we control the OS, then we can also access the private key.
Method two – Don’t use RSA for key exchange
As we’ve seen, the RSA key exchange is susceptible to interception if one is fortunate enough to have the server’s private key. By using a flavour of Diffie-Hellman for key exchange instead, we can rule out any chance of an attacker feasibly decrypting our SSL traffic even if they are in possession of the server’s private key. With your existing server certificates and keys, run the server like this and get your browser to fetch https://myserver/myfile.html again:
openssl s_server -key testkey.pem -cert testcert.pem -WWW -cipher AES256-SHA -accept 443
We’ve changed the cipher from RC4 to 256 bit AES – this step is just to prove that Wireshark can decrypt AES as well as RC4.
Now, to break the decryption, alter the cipher suite to use Diffie-Hellman instead of RSA for key exhcange:
openssl s_server -key testkey.pem -cert testcert.pem -WWW -cipher DHE-RSA-AES256-SHA -accept 443
If you’re using a browser other than IE (my IE8 doesn’t seem to support DH with RSA certificates), Wireshark is totally unable to decrypt the HTTP traffic, even though it is in possession of the server’s private key.
DH key exchange is by design resistant to eavesdropping, although can be susceptible to a man-in-the-middle attack unless both parties identify themselves with certificates. It’s also, as we’ve seen, not universally supported by common SSL clients. But at least it rules out the possibility of some wiseguy with Wireshark sticking his fins where they’re not wanted!
If you are interested in becoming an IT professional
you may want to consider a CCNA training course.