Decrypting SSL with ChopShopMay 22, 2014
This is a continuation in the series on extending ChopShop, a network protocol analyzer framework, with new modules to meet the needs of CND.
In the life of a threat researcher there inevitably comes a time when a particular network session stands out as suspicious. But because it's encrypted, you don't know what you're dealing with. If you could decrypt the SSL layer and get at the underlying protocol, you'd be in a better position to understand your adversary and defend yourself. The network session might be malware communicating outbound from your network via SSL, in which case you could perform an MITM attack to grab the traffic. Or perhaps it's an adversary executing a web-shell on your DMZ over an SSL connection, but you don't have logs from the system. In either case, being able to get at the plaintext equivalent of the network session is an important element for understanding the threat actor.
Decrypting SSL with ChopShop
We recently released a ChopShop library called SSLim, (SSL inspection module, pronounced "slim"), which is intended to be an SSL decryption capability for ChopShop. I'll introduce you to it by starting off with some caveats about the code, talk a bit about the design and how to use it, and then finish up with some next steps we hope to take.
SSL is a complex protocol, which has gotten more complex with each new iteration and extension. SSLim began as a proof of concept to decrypt the most basic SSL sessions and still handles only the basics. It does not handle renegotiations or many of the extensions to SSL, and it only handles a very small handful of cipher suites. Essentially, I implemented only what was absolutely required for the simple HTTPS sessions I was decrypting.
To be perfectly clear, SSLim is not doing anything fancy to decrypt the SSL: it requires the private key to decrypt a session. It isn’t some fancy SSL breaking piece of code, but rather something similar to Wireshark or other SSL decryption capabilities. However, the nice thing about SSLim is that it gives you, the module author, the plaintext as output. It fits in nicely with the ChopShop way of doing things: it's simple to use and flexible.
Like any good library, the internals of SSLim are abstracted for ease of use. If you would like to understand them, I suggest reading the comments at the top of SSLim.py. I'll only be focusing on the external interfaces that a module author will use.
SSLim is an "external library" (in ChopShop terms) that can be imported and used by any module that needs to decrypt SSL traffic. I didn't want to be in the business of writing my own cryptography bits, so to keep things simple, I decided to use the open source toolkit called M2Crypto to do the heavy lifting. This made SSLim much easier to write and also minimized the introduction of bugs presented by the complex cryptography inherent in SSL decryption.
SSLim has an intentionally minimal interface, with only a single object required. This means that when you write a module that uses SSLim, all you have to do, after initializing the module, is create a SSLim object. Be sure to keep that object around for the lifetime of your module rather than on a per-stream basis. By this I mean it should be created in
init() and stored in
module_data. Instantiating a SSLim object requires the private key as an argument. Currently this must be a path on the disk to where the key file is located—and the key must not be passphrase protected.
Once you have instantiated a SSLim object, you must set the two callback functions you want to use. SSLim will call these functions for each message it successfully decrypts. The two callbacks are exposed via the
res_callback attributes on your SSLim object. The
req_callback is called once per request message and the
res_callback is called once per response message. Note that the definitions of "request" and "response" used here match those used by ChopShop. Due to the internal mechanisms used by SSLim, once you start parsing SSL data you cannot change the callbacks for that stream. The callbacks will be covered in more detail later.
module_data['sslim'] = sslim('/home/wxs/mykey')
module_data['sslim'].req_callback = ssl_request_callback
module_data['sslim'].res_callback = ssl_response_callback
Once you have your SSLim object instantiated and your callbacks set, you can begin to send your data into the SSLim object for parsing. There are two functions to do this:
parse_to_client(). As mentioned before, these directly match the directionality used by ChopShop. Each of these functions requires as arguments the data to parse and the
# We have identified this connection as SSL, so just process the packets
if tcp.server.count_new > 0:
chop.tsprnt("%s:%s -> %s:%s (%i)" % (src, sport, dst, dport,
if tcp.client.count_new > 0:
chop.tsprnt("%s:%s -> %s:%s (%i)" % (dst, dport, src, sport,
At this point SSLim will take your data and parse it. Once a message has been decrypted (and decompressed if necessary) the plaintext data is passed into your callbacks where you can do with it as you please. If the data is HTTP, you can feed it into something like htpy, which I have written about in the past, to get HTTP parsing capabilities. If it is some other protocol, you can parse it in a manner suitable to you.
What's Next for SSLim
In the future I would like to adapt SSLim to better fit module chaining, which was introduced in ChopShop 4.0. The code also needs to support more cipher suites. At this time, it supports six of the most common cipher suites, but it would be great to grow support for new ones as they come into use.
Ultimately, the SSL protocol is both simple and complex. The on-the-wire format is the simple part, but the complexities in the state machine and the various ciphers make the task of writing a robust SSL decryption capability daunting. It is my hope that by releasing SSLim in this basic state, it will serve as an example of the interesting capabilities you can build using ChopShop.