Quick shout-out to my good friend and colleague Dan Spier who helped put this content together.
Data alone is not always enough to help analysts find threats. Meaningful data requires context. In this blog we will demonstrate features that help provide context around packet data and methods you can use to reduce hunting ambiguity. We will cover augmenting SSL data with JA3 calculation, adapting to external data sources, passing parameters via URL using Context Menu Actions,and querying with dynamic lists.
The topics in this blog are meant to serve as a jumping-off point, not an exhaustive list. Adapt these methods as needed in your environment:
Passive TLS fingerprinting with JA3
Custom feed manipulation to adapt to and integrate with non-standard third-party data sources
Context Menu Actions to easily pivot to external applications
Reporting Engine dynamic lists to streamline hunting
These features have very few requirements.
Netwitness for Networks (Packets) 11.3.1+
HTTPS parser enabled
Regex/Command Line knowledge recommended for feed manipulation
To verify that the HTTPS parser is enabled, view the Decoder > Config Parser Configuration settings.
As with enabling any parser enhancements, it is also recommended to have a procedure in place for monitoring decoder performance for packet drops. Review your Health & Wellness monitoring policies to ensure that they are enabled with proper notification settings.
The Springboard is an analyst centric view that is enabled by default in NetWitness 11.5+. The Springboard allows for a customizable initial first glance into an environment. From this view an analyst can easily pivot into a hunt (NW: Managing the Springboard).
Once in the Events tab we can start carving data by clicking the “Filter” button.
Red Box: Meta queries and navigation
Green Box: Table from initial landing. The columns can be adjusted via the "Column Group" drop down.
Blue Box: Event reconstruction and meta
JA3 and JA3S TLS Fingerprints
JA3 and JA3S is an effective way to provide insight into encrypted traffic. The method looks at specific parameters of the client <---> server connection and creates unique hashes that can be utilized as contextual data. (TLS Fingerprinting with JA3 and JA3S)
The Network Decoder can produce the JA3 value of TLS clients and the JA3S value of TLS servers that are observed in a Network session. The values that are produced conform to the values generated by the open source JA3 tools (https://github.com/salesforce/ja3). The JA3 features are disabled by default.
To enable JA3 features:
In the NetWitness Platform User Interface, go to (Admin) > Services.
Select a Decoder service and click > View > Explore.
In the left panel, select decoder > parsers > config.
In parsers.options, add HTTPS="ja3=true ja3s=true".
In the left panel, right click on parsers and select properties.
In the right panel, in the lower pane, set the value in the first drop down to Reload.
Context Menu Actions and Feeds
If there is a firewall or proxy between the Netwitness admin server and the online sites to be queried, those connections will need to be allowed.
One of the most frequent questions we get from customers utilizing NetWitness Packets is "what about my encrypted traffic?". This is one of a few options for acquiring some useful insight if decrypting the data is not an option. The contextual data provided by JA3 is not perfect, as is the case with any data but it does help paint a picture for the analyst.
JA3 comes with a fair amount of noise and false positives (lots of Chrome). With that said, we aren't after a JA3 or JA3s alone. The value is in the combination of the two. The client - server relationships for your production devices are unique and don't often change drastically.
Lets look at a simulated scenario. We have a traditional Windows 10 machine (standard install for all intents and purposes). My attacker machine is Kali. I have used Ja3er (right-click context menu action) to determine the ja3.desc value (windows 10 built tls connection to domain) and manually added that to my feed. I have tracked the associated JA3s values over the course of a week and they have not changed. What's that mean? Well, if I take some time to map out the unique combination of fingerprints to the associated alias.host meta and add those values to a custom feed, I have context unique to my environment. This does take effort to accomplish but it will provide helpful context when hunting in the future. I recommend starting with a list of critical assets for this process and growing the list over time as needed by the SOC. In the image below we can see that I ran the query "ja3.desc = windows 10 built tls connection to domain". That description is based off of the single JA3 value in the JA3 meta (a quick ja3er context menu action makes these lookups a little easier, though not every hash is in the database).
The workstation has a decent amount of "noise" associated with this JA3 value. The majority of the noise is typical Microsoft traffic. However, by using the ja3.desc context, we can quickly pivot into examining specific connections. The values in green stand out against the noise and the traffic between those hosts could be investigated further. The combination of these values is not enough to create a 100% accurate detection method. Some human intuition is required, but once the combination is discovered with confidence, it can be used for automated detection.
For reference, the unique combination of Meterpreter on Kali 2021.1 and Windows 10 TLS connection to domain is below.
a0e9f5d64349fb13191bc781f81f42e1 (JA3 Windows 10 TLS to Domain), ec74a5c51106f0419184d0dd08fb05bc ( JA3s Kali 2021.1 Meterpreter)
Custom Feed Manipulation
Frequently, third-party data sources can be inconsistent or in varying formats. The ability to adapt, merge, and utilize external data is a valuable asset in threat hunting. For this example, we are augmenting our enabled JA3 fingerprinting feature with fingerprints provided by three different sources.
Two of these sources are in CSV format which is straightforward to parse with common command line tools. The other is in JSON format which can be more difficult to work with without the correct tool.
The first column is typically the indexed column. You may also choose to duplicate this column to a custom key for ease of investigation. The remaining columns are determined by the dataset and how the feed will be utilized. In cases where several third-party sources will be merged into one feed, having placeholder columns can simplify the integration of new sources if it has more fields than others. Netwitness will use the first line in the feed to determine how many columns are to be created.
The indexed column
Optional: a duplicate of the indexed column to populate a custom key
A custom key to store details from the various feeds
Contains the name of the list
Example: Note that pipes have been used for delimiting the fields due to the presence of commas and other special characters in the data.
All of these commands can be combined into a cron job or script to automate this process. The semicolon at the end of each command can be removed if running the commands individually. Sites such as ExplainShell (https://explainshell.com/) or regex training sites can be useful for understanding commands. Particularly, it is helpful to understand field and capture groups with “awk” and “sed.” The commands below are examples but not necessarily the most optimal way to accomplish the task.
Note: These were written in the Netwitness environment. Non-Netwitness servers may have a different implementation of command line utilities and therefore different syntax or behavior.
The first dataset is in JSON format and contains fields that may be excessive in length so we are trimming those to a max of 100 characters. We are also deleting duplicate lines that are provided by other feeds. The “jq” command line utility is an efficient way to process JSON’s individual elements, followed by “sed” to arrange them and add additional context.
This source was added after the initial creation of this blog post. Rather than rework the above examples, appending it here demonstrates the value of having placeholders in the feed layout.
curl --silent https://ja3er.com/getAllUasJson | sed 's/|/+/g' | jq '. | select(."User-Agent" != "" and .Count >= 500) | [.md5, ."User-Agent"[0:100], .Count, ."Last_seen"] | join("|")' | sed 's/"\(.*\)|\(.*\)|\(.*\)|\(.*\)"/\1|\1|\2|ja3er gt500|\3|\4/' > ja3er-final.csv
The Ja3er dataset contains hundreds of thousands of samplings that map user agents to JA3. Many mappings have very small sample sizes which could raise fidelity concerns. Some fields also have the delimiter character that we’re using for the final feed.
The first step is to use “sed” to replace the pipe character with something else because pipe is reserved for our delimiter. Next, “jq” is used with a filter so that no entries with null user-agent records are included. It also requires the count (number of samples) to be greater than or equal to 500, although this can be tuned as needed.
The final feed can be uploaded manually or stored in a location reachable by Netwitness for automated ingestion.
Custom Context Menu Actions
These little right-click functions have a lot of power to make an anylsts life more efficient. Often, these functions are used to create lookups to various third-party resources. The below list is an example of what customers have asked for in the past.
A dynamic reporting list is used when the results of one query need to be used in the “where” clause of another query. A common example of this is running a report to identify additional domains associated with a domain IOC. This can help enumerate domains that are sharing hosting infrastructure.
We want to see all sessions to or from the IPs where the domain is hosted. The example below shows how the reporting engine results simulate an Investigate query.
Step 1) Query for alias.host contains "baddomain"
Step 1a) Copy the IPs from the alias.ip field
Step 2) Create a new query,service != 53 && (ip.src = <ip list> || ip.dst = <ip list>)
Step 0) Create an empty Reporting Engine list.
Note: you will need to enter a value into the list before it can be saved. This value will be temporary.
Step 1) Create the base rule.
Step 2) Create and schedule a report.
Note: Be sure to check the button to overwrite the list values when defining the dynamic list. Otherwise, the list may be filled with stale values.
Step 3) Create a new rule and report using the dynamic list.
The image of report results is truncated, but the full report would be the equivalent of the Investigate query we ran in step two of the previous section. It reveals all communication with the IPs on which the original domain IOC are hosted.
This will allow security teams to decide the appropriate response, for example whether to block:
only one domain,
all of the associated domains,
the IPs revealed with the queries,
connections from that hosting organization (meta keys org.srcand org.dst),
Hunting requires analysts to be flexible and the availability of additional datapoints can greatly increase their effectiveness. When more context is needed,Netwitness features can be leveraged to supplement datasets and streamline investigations.