You might need to search for rarest JA3/JA3s hashes when doing the following:
To succeed in implementing this use case, you need the following dependencies, resources, and information.
- People: Security analyst, threat hunter
- Technologies: Splunk Cloud Platform or Splunk Enterprise
- Data: Deep packet inspection data
You can run a search which uses JA3 and JA3s hashes to detect abnormal activity on critical servers which are often targeted in supply chain attacks. JA3 is an open-source methodology that allows for creating an MD5 hash of specific values found in the SSL/TLS handshake process, and JA3s is a similar methodology for calculating the JA3 hash of a server session.
This search is most effectively run in the following circumstances:
- with an allow list that limits the number of perceived false positives.
- against network connectivity that is not encrypted over SSL/TLS.
- with internal hosts or netblocks that have limited outbound connectivity as a client.
- in networks without SSL/TLS interceptions or inspection.
To optimize the search shown below, you should specify an index and a time range. In this example, Zeek is used to generate JA3 and JA3s data but you can use any other tool which can generate that data.
Run the following search:
sourcetype="bro:ssl:json" ja3="*" ja3s="*" src_ip IN (192.168.70.0/24) | eventstats count AS total | stats values(ja3), values(dest_ip), values(src_ip), values(total) AS total count BY server name ja3s | eval perc=round((count/total)*100,4) | sort + perc
The table provides an explanation of what each part of this search achieves. You can adjust this query based on the specifics of your environment.
|sourcetype="bro:ssl:json" ja3="*" ja3s="*" src_ip IN (192.168.70.0/24)||
Search Zeek data for JA3 and JA3s hashes within the critical server defined.
This part of the search uses critical server netblock, 192.168.70.0/24. It's important that you adjust this part of the search to include your own critical servers.
|| eventstats count AS total||Generates a count for each hash in a "total" column.|
|| stats values(ja3), values(dest_ip), values(src_ip), values(total) AS total count BY server name ja3s||Shows results in a table with the JA3, dest_ip, src_ip and total in columns grouped by server name and JA3s.|
|| eval perc=round((count/total)*100,4)||Shows the percentage of times the JA3 and server combination occurred, rounded to 4 decimal places.|
|| sort + perc||Sort with the least frequently occuring combination first.|
This search returns the rarest JA3s and server combinations. In the example below, you can see two TLS sessions which look suspicious for update.lunarstiiiness.com within the top ten rarest results.
However, the results of this search can be inconsistent. It is most useful as an addendum to other searches in this use case.
Performing additional whitelisting by using allow lists can also help you identify additional potentially malicious results, as shown in the example below.