Tall Tales of Hunting with TLS/SSL Certificates


This is part twelve of the "Hunting with Splunk: The Basics" series. I've wanted to work on SSL hunting with Splunk ever since I saw my friend @markpars0ns present on the idea at a security conference in 2016. I hope you enjoy - Ryan Kovar

Recently, my beloved colleague Steve Brant and I presented "Hunting the Known Unknowns: Finding Evil With SSL Traffic" at .conf2017. Turns out it was an extremely popular talk with over 500 attendees. However, not everyone has time to work their way through 120+ slides and 50 minutes of two bearded gentlemen mumbling and bumbling their way through a talk, so we thought we would synthesize the content downTall Tales Hunting SSL  to one or two blog posts. This blog post will specifically focus on how to use SSL certificate information to find evil in your network! Look forward to a new post by Steve Brant coming out soon on JA3.

Why should I care about hunting with SSL certificates?

First though, let's clear up a couple things.  This is not going to be a complicated discussion of the cryptographic innards of TLS and SSL. Furthermore, for those of you who are as pedantic as James or David (you know who you are!)—yes, I use the abbreviation SSL interchangeably with TLS. Why? Because I am an elderly security dude and TLS is just the newest version of SSL. So there. If this is a problem, please feel free to think poorly of me. There is a fan club:… you can join. :-) Finally, if you want more in-depth SSL hunting info, check out our .conf2017 session. Okay, MOVING ON.

Just like banks, airlines and every other industry, advanced adversaries are moving to SSL encrypted communications to evade detection by our tribe of network defenders. Five years ago, we could decode PoisonIvy C2 communications via clear text HTTP! Fast forward to today and now the baddies cavalierly use SSL encryption to hide their PowerShell Empire connections as they run rampant in our networks like Roundheads chasing Royalists! However, all is not doom and gloom for blue teamers:

  1. Adversaries (like me) are lazy
  2. SSL has unencrypted information that you can pivot with via Splunk

This blog post only covers what to do *if* you have captured SSL metadata in Splunk. If you DON'T, check out our .conf2017 session to learn how. :-)

What is this unencrypted information that SSL leaves? 

A very succinct definition of TLS/SSL certificates are “small [unencrypted] data files that digitally bind a cryptographic key to an organization’s details.” [1] This is a huge deal for blue teamers because the information in these certificates are static and can be tracked.

Splunk TSL/SSL certificate

These fields are either generated by ciphers and algorithms used to create the certificate or by manual input at the time of the cert creation. How does this help you? Because these fields can be unique and are often shared by adversaries across their backend infrastructure. So… what are some unique fields? The ones that we are primarily interested in are: ssl_cert_self_signed, ssl_subject_country, ssl_subject_state, ssl_issuer, ssl_subject_locality, ssl_subject_unit, ssl_subject_organization, ssl_validity_end, ssl_subject_common_name, ssl_serialnumber, and ssl_cert_sha1. But honestly… almost every field that you can extract from the SSL certificate is of interest.

What do we do with the fields when we have them?

Let’s start with the basics. A commonly held belief is that malware often uses unusual ports to communicate. Since we have a hypothesis that malware is beginning to use SSL to encrypt its communications, I believe it is reasonable to assume that they would use SSL to encrypt communication on alternative ports! For nearly all the following examples, we will be using SSL data captured in Stream. Let’s look:

sourcetype=stream:tcp ssl_cert_sha1=* NOT (dest_port=443 OR dest_port=993 OR dest_port=995 OR dest_port=465 OR dest_port=9001) 
 | stats VALUES(ssl_issuer) VALUES(dest_port) VALUES(ssl_subject_common_name) VALUES(dest_ip) count(ssl_subject_common_name) BY ssl_cert_sha1

BOOM! You’ll notice the 3rd and 4th entry have very suspicious metadata and link to some nasty looking domains and IP addresses. A quick pivot to VirusTotal shows that there have been malicious files hosted on that IP address in the past:

For our next search, let’s try and find values in SSL certificates that are unique. We will do a little pre-parsing by showing only SSL certificates that are not part of the Alexa 1 Million top sites. This is done with the UT_PARSE macro (which you can install with URL Toolbox) and the Alexa 1 Million list. You can download a sample of Alexa 1 Million from my github as a properly formatted lookup table.

sourcetype=stream:tcp ssl_cert_sha1=*
 | stats VALUES(ssl_issuer) AS ssl_issuer VALUES(ssl_subject_common_name) AS ssl_subject_common_name VALUES(dest_ip) AS dest_ip count(ssl_subject_common_name)  AS count BY ssl_cert_sha1
 | search count=1
 | eval list="*"
 | lookup alexa-1MM domain AS ut_domain
 | fillnull value=NULL rank
 | search rank=NULL
 | stats VALUES(ssl_cert_sha1) VALUES(ssl_subject_common_name) AS ssl_subject_common_name VALUES(dest_ip) AS dest_ip values(ut_domain) AS ut_domain count(ssl_subject_common_name)  AS count BY ssl_issuer

Right away we see some very odd values in the ssl_issuer and ssl_subject_common_name fields. If we search for that SHA1 certificate value (ssl_cert_sha1) in google we find that various websites have identified that SHA1 hash as malicious.

Finally, what about detecting certificates that are “known bad”? The most common repository of externally identified certificates is from  With minimal effort, you can turn that list of malicious SHA1 SSL certificates into a lookup table in Splunk. The example below assumes that you have done that already, but if you want an example, check out my github and download the ssl_blacklist_2.csv file. 

index=* sourcetype=stream:tcp ssl_cert_sha1=*
 | lookup ssl_block_list sha1_cert AS ssl_cert_sha1 
 | search reason=*
 | stats VALUES(ssl_issuer) AS issuer VALUES(dest_port) AS "Destination Port" VALUES(ssl_subject_common_name) AS "Subject Common Name"  VALUES(reason) AS Reason  VALUES(ssl_cert_sha1) AS SHA1 count(ssl_cert_sha1) AS count by dest_ip

The results below show that we have five hits against our data and a quick explanation of each malicious certificate. 

Now what?!?!

Finding malicious SSL/TLS in your environment is just the first step. Just like finding malicious IP addresses or file hashes you will need to pivot and research using tools like,, and Once you understand how to use these certificates, try creating workflow actions in Splunk to pivot “automagically”. If you’d like an example, check out my sample workflow action for located on my github page. If you are interested in more information on hunting and pivoting with TLS certificates, check out this great talk from my good friend Mark Parsons (@markpars0ns) on hunting a TLS certificate. Until then…

Happy Hunting! :-)


Ryan Kovar
Posted by

Ryan Kovar

NY. AZ. Navy. SOCA. KBMG. DARPA. Splunk.