Decrypting TLS with Wireshark

Did you know that you can easily decrypt TLS (mostly HTTPS) traffic with Wireshark? Well, only if you have the keys. ;) This really is a game-changer if you’re stuck with troubleshooting encrypted data. Let’s do an example:

TL;DR: You can decrypt TLS traffic with Wireshark, but only if you have the session keys! Those can be exported by browsers if you set the SSLKEYLOGFILE environment variable *before* using the browser.

The server’s private key (certificate) is no longer of interest, since all modern ciphers use (EC)DHE, in which the session keys are derived by both parties. With TLS 1.3, RSA key exchange is gone completely. All ciphers use forward secrecy.

Getting the Session Keys

In this example, I’m using a browser with HTTPS. Of course, you can decrypt any other TLS traffic with Wireshark, as long as you have the session keys. However, in most of my daily business scenarios, decrypting HTTPS is the most relevant.

You have to set the SSLKEYLOGFILE variable, which then creates a file with the session keys. No admin privileges are needed for this step. After that, open your browser of choice and start surfing. In my example, I opened my fairly simple website at https://ip.webernetz.net.

(For some reason, various variables/fields are still named “SSL” rather than “TLS”.)

At the start of the browser, many different HTTPS sessions are already initiated by the browser itself. That is: The sslkeys.log is kind of crowded. Be aware that it contains any session keys since your start. Keep them to yourself!

In my sample, I copied only the relevant session keys for my single session. Those can be correlated by the “Random” value within the client TLS hello, field  tls.handshake.random in Wireshark. Different lines are present in the file, such as CLIENT_HANDSHAKE_TRAFFIC_SECRET, SERVER_HANDSHAKE_TRAFFIC_SECRET, CLIENT_TRAFFIC_SECRET_0, SERVER_TRAFFIC_SECRET_0, EXPORTER_SECRET. My sample keys are:

Decryption, Please!

Now, within Wireshark, go to Edit -> Preferences -> Protocols -> TLS and select your sslkey.log file at the “(Pre)-Master-Secret log filename”:

After hitting OK, Wireshark will decrypt all applicable TLS sessions directly. The following screenshot shows the original (encrypted) PCAP on the left-hand side, while the decrypted traffic on the right-hand side. While the original TLS traffic shows only “Application Data”, which is de facto random data, the decrypted part shows the actual protocol, an HTTP GET in this scenario:

On the Packet Bytes section (bottom right), you can switch between the original Packet vs. the Decrypted TLS view:

If you want to distribute the PCAP *with* the session keys, you can inject them into the capture file, which then turns into a *.pcapng file format: Edit -> Inject TLS Secrets:

Sample in the Ultimate PCAP

The sample of HTTPS traffic shown here, including the injected TLS keys, is part of the Ultimate PCAP. Please download and analyse it by yourself – the display filter to find those packets could be: http and tcp.port eq 443.

Follow {HTTP|TCP|TLS} Stream

Note the differences between the three “Follow …” methods. The well-known “Follow TCP Stream” will still show the encrypted data:

while the “Follow TLS Stream” shows the DEcrypted data, but still with the HTTP Content-Encoding such as gzip. Hence: still not completely readable (though decrypted):

Finally, the “Follow HTTP Stream“, when clicked on an HTTP packet (rather than on a mere TCP packet), brings us readable plain-text HTTP completely:

That’s it. Happy decrypting. ;)

Further Reading/Watching

Soli Deo Gloria!

Photo by Markus Spiske on Unsplash.

Leave a Reply

Your email address will not be published. Required fields are marked *