Summary
CrowdStrike creates logs in JSON format and sends 2 different datasets to the same sourcetype; security events from their detection tools and audit events from their management tool. These audit tools contain analyst data about when they mark events as true positive, and withing CrowdStrike these are joined with the security event itself. To recreate that functionality within Splunk we must find the true positive marker, grab the uid and then search for the security events that match to pull back the relevant TTP’s for further analysis and threat monitoring.
Challenge
Crowdstrike uses 1 sourcetype for 2 different types of logs. Additionally, the JSON is poorly formed, so the fields with the unique data are multi-value fields. Two fields of interest, AuditKeyValues.Key contains the field name, AuditKeyValues.ValueString contains the field values. Both of these are multi-valued fields, so we must join them together properly before we can readily use that information.
Solution
index="main" sourcetype="crowdstrike:falconhost:json" TERM(true_positive) |eval keyjoin=mvzip('result.event.AuditKeyValues{}.Key{}','result.event.AuditKeyValues{}.ValueString{}') | mvexpand keyjoin | rex field=keyjoin "^(?<key>[^,]+),(?<value>.*)$" | eval {key} = value | stats values(new_state) as new_state, values(assigned_to) as assigned_to, values(detection_id) as detection_id, by date | join detection_id [ search index="main" sourcetype="crowdstrike:falconhost:json" NOT TERM(true_positive) | stats values(result.event.DetectId) as detection_id, values(result.dest) as result.dest, values(result.file_name) as file_name, values(result.file_path) as file_path, values(result.event.SHA256String) as SHA256,values(result.event.MD5String) as MD5, values(result.dest_nt_domain) as Domain, values(result.url) as URL by date] | dedup date, detection_id | eval Date=strftime(date,"%m/%d/%y %H:%M:%S") | table Date, new_state, assigned_to, detection_id, Domain, MD5, SHA256, URL, file_name, file_path, result.dest | rename new_state as "New State", assigned_to AS "Assigned To", detection_id AS "Detection ID", file_name AS "File Name", result.dest AS "Destination"
First we find events with TruePositive. These events are where we must get the GUID. We work with the multi-value fields, first by zipping them together, then by expanding them out. This gives us KV pairs in the keyjoin field. Then we split them out to be new fields in the event data. Finally we use stats to table out the event data. This is used because the standard table command will not result in these new fields showing on the same line as the events are duplicated by the number of new fields created. We have to use a unique value in the origin data to act as the joining key, so date was selected as these events are the result of human action, we shouldn’t have key collision.
Then we do a subsearch. This is fairly strait forward, but assumes that the true positive action and the event happen within the same search window, so be aware of that, you may need to tweak the search if you are not a 24×7 shop.