Part of our job as security researchers is keeping up with new tools and techniques used to monitor for malicious or unauthorized activity. Strong encryption is an important security pillar that provides essential privacy and access controls, but of course criminals take advantage of encryption as well to hide their own activity. When it comes to the network, figuring out how to monitor encrypted traffic for malicious behavior without breaking the privacy that is so vital for security is an age old problem.
While some solutions actually perform what boils down to a full man-in-the-middle attack in order to decrypt and inspect the traffic, it can be costly, slow, hard to implement, and could actually introduce more security and privacy concerns. However, it may not be necessary to actually decrypt the traffic in order to flag it as malicious. For instance, the Suricata IDPS engine can monitor the use of specific TLS certificates which can then be combined with known-bad certificates or an SSL blacklist like this one maintained by abuse.ch for alerting or blocking.
A new method of TLS fingerprinting was recently put together called JA3. Rather than simply looking at the certificate used, JA3 parses multiple fields set in the TLS client hello packet sent over during the SSL handshake. The resulting fingerprint can then be used to identify, log, alert and/or block specific traffic.
JA3 looks at the client hello packet in the SSL handshake to in order to gather the SSL version and list of supported ciphers. If supported by the client, it will also use all supported SSL extensions, all supported Elliptic Curves, and finally the Elliptic Curve Point Format. The fields are comma delimited with multiple values separated with a dash (for instance, each supported cipher will be listed with dashes between them). The format of:
Might hold a fingerprint like so:
This JA3 fingerprint is actually specific to the traffic generated by a PoSeidon Point of Sale malware sample. After we capture the packets the malware generates, we feed it to the JA3 tool available on their github. You can see the output below:
$ ja3 -j Poseidon.pcap
If we take the output from JA3 and compare that to the pcap, we can see where JA3 is getting the information to create the fingerprint.
SSLVersion = 0301 = 769
Cipher = 0xc014 = 49172
Cipher = 0xc013 = 49171
Cipher = 0x0035 = 53
SSLExtension = 0x0000 = 0
SSLEXtension = 0x0005 = 5
SSLExtension = 0x000a = 10
SSLExtension = 0x000b = 11
SSLExtension = 0xff01 = 65281
EllipticCurve = 0x0017 = 23
EllipticCurve = 0x0018 = 24
EllipticCurve = 0x0019 = 25
EllipticCurvePointFormat = 0x0000 = 0
Fig 1: decode of the Poseidon Client Hello Packet and JA3 fingerprint generation
Now that we have an understanding of how JA3 works, let's see how we can use it in practice. JA3 is supported by all sorts of software like NGINX and Bro and the list continues to grow. In this post we'll use it with the open source IDPS software Suricata to detect some malware traffic.
Let's continue to use the PoSeidon malware for testing the JA3 feature in Suricata. PoSeidon has both encrypted and unencrypted traffic that can be used to detect its presence. It's also been around for a while and has multiple versions that we can test against.
So we have the JA3 Fingerprint of "769,49172-49171-53-47-49162-49161-56-50-10-19-5-4,0-5-10-11-65281,23-24-25,0" and a JA3 Hash (which is just the MD5 hash of the fingerprint) of "1eede9d19dc45c2cb66d2f5c6849e843".
Suricata supports two keywords for JA3; ja3_hash and ja3_string which are used with the content keyword like so:
ja3_hash; content: "1eede9d19dc45c2cb66d2f5c6849e843";
ja3_string; content: "769,49172-49171-53-47-49162-49161-56-50-10-19-5-4,0-5-10-11-65281,23-24-25,0";
So our Suricata signature might look something like this:
I used this signature against multiple versions of PoSeidon and you can see the triggered alerts and packet summaries below:
Fig 2: Test against PoSeidon v11.97
Fig 3: Test against PoSeidon v13
Fig 4: Test against PoSeidon v15
With one signature using a ja3_hash, we are able to detect not just one version of the PoSeidon malware but multiple. Traffic typically will change between different versions of malware either as just an update to their process or to evade detection, however, if they use encryption, they often continue to use the same code/client across versions. Having the ability to create one signature to detection multiple versions is significant. Probably the most significant point would be the chance to detect a new variant with signatures built from older samples! When used in a Suricata signature it can detect malicious traffic regardless of IP or domain names of a C&C which can constantly change.
In addition to all of this, since Suricata implements a portless configuration, we get an added bonus when using JA3. While doing some testing with Dridex malware pcaps I got from www.malware-traffic-analysis.net, I noticed there was an alert for port 443 as might be expected and 4 alerts for port 8043 which is an odd port for TLS. If we were trying to write a signature which requires following specific ports then those other alerts for 8043 would have been missed.
Fig 5: Triggering on Dridex regardless of destination port
Another great example of using Suricata and JA3 with the portless configuration is with TrickBot. All of the alerts from this pcap was on a non-standard port.
Fig 6: Triggering on Trickbot regardless of destination port
Encrypted traffic has always been a hard problem when it comes to IDPS. Now, with the addition of JA3 it's much less of a hinderance and has the potential of providing a highly confident form of IOC. With more testing, this can be a great tool for stopping C&C communication and prevent further infection. Here at Trustwave we are continuing our testing and plan on implementing JA3 as a feature in our IDS and UTM as soon as it's ready for inclusion.