There are two approaches I would use for this. The first is with raw text -- yours is probably just fine, given the relatively small number of events you're likely to see, and the extremely short time window. Any alternatives that don't use transaction would probably be so much harder to write while respecting the very short time window, that it wouldn't be worthwhile. That said, if I were looking at this, I might want to look for a longer time window to respect malware that delays execution specifically for sandboxing. Alternatively, if you are using the sandboxing technology in Wildfire (as opposed to the IOC database), I think the wildfire alert might actually come after the endpoint hit. You could allow for some of this complication by scheduling the following search to run every 15 minutes (note the overlapping time window -- employ throttling based on the dest_ip field, or maybe dest_ip + the wildfire hash to control excess notifications):
earliest=-30m@m sourcetype=pan_threat from!=DMZ to!=DMZ category=spyware OR category=file OR category=malware action!=sinkhole
| stats count(eval(searchmatch("wildfire"))) as wildfire count(eval(searchmatch("spyware OR malware"))) as malware values(signature) as signature values(other_useful_context) as other_useful_context [...etc...] by dest_ip
| where wildfire>0 AND malware>0
(Better yet, use by dest, and maybe even vendor_product so that it is CIM compliant!)
For how to accelerate this, I would expect both of these to show up in the malware data model, in which case you could do something like the following. The tstats definitely does need to be first, unless you're doing prestats=t and append=t, in which case you can combine them. (You can even do eval, rename, etc., between them.. but that gets into a little more voodoo, which is hard to feel out on your own):
| tstats count from datamodel=Malware where earliest=-30m@m groupby "Malware.dest" "Malware.vendor_product"
| stats sum(eval(if('Malware_Attacks.vendor_product' = "Palo Alto Networks Wildfire", count, 0))) as wildfire sum(eval(if('Malware_Attacks.vendor_product' = "Palo Alto Networks Endpoint", count, 0))) as malware by "Malware_Attacks.dest"
| where wildfire>0 AND malware>0
(Double check in your data that there are now src/dest issues, etc. Let me know if that's the case, happy to adapt it). That said, this is one of those searches which you may not actually need to accelerate, because the dataset should be really low, and the speed should thus be really fast.
Does that sound reasonable? Let me know if this response is off base in any way! And thank you for providing a clear question with example searches -- that's really helpful!
... View more