By Splunk October 17, 2012
I got a question about extending Enterprise Security yesterday, and would like to jot down some notes about the solution.
While ES comes with several automated blocklists, customers often want to expand with their own static blocklist. There are two simple steps here:
- Copy an existing blocklist. These are kept in $SPLUNK_HOME/etc/apps/SA-ThreatIntelligence/lookups/, and begin with ip_. Let’s create an ip_myblocklist.csv:
- Copy an existing correlation search (such as Network – Tor Router Activity – Rule) and change the blocklist references from *tor* to *myblocklist*:
| inputlookup append=T src_dest_tracker | lookup local=true ip_myblocklist_lookup src OUTPUTNEW src_ip as src_myblocklist_ip,src_is_myblocklist | lookup local=true ip_myblocklist_lookup dest OUTPUTNEW dest_ip as dest_myblocklist_ip,dest_is_myblocklist | search dest_is_myblocklist=true OR src_is_myblocklist=true | eval myblocklist_ip=if(dest_is_myblocklist=="true",dest_myblocklist_ip,myblocklist_ip) | eval myblocklist_ip=if(src_is_myblocklist=="true",src_myblocklist_ip,myblocklist_ip) | fields + sourcetype,src,dest,myblocklist_ip
This is an effective solution to generate notable events and provide notifications when policy violations occur. However, maintaining the static blocklist is kind of a pain, so let’s add some workflow actions so that analysts can add items to the blocklist:
Edit $SPLUNK_HOME/etc/apps/SplunkEnterpriseSecuritySuite/local/workflow_actions.conf and add these two stanzas:
[block_dest_ip] display_location = field_menu fields = dest_ip label = Add $dest_ip$ to blocklist type = search search.earliest = -1h search.search_string = dest_ip="$@field_value$" | head 1 | fields dest_ip,is_blocked,description| fillnull value=true is_blocked | fillnull value="Private blocklist" description | rename dest_ip as ip | inputlookup append=T ip_myblocklist.csv | dedup ip | table ip,is_blocked,description | outputlookup ip_myblocklist.csv [block_src_ip] display_location = field_menu fields = src_ip label = Add $src_ip$ to blocklist type = search search.earliest = -1h search.search_string = src_ip="$@field_value$" | head 1 | fields src_ip,is_blocked,description| fillnull value=true is_blocked | fillnull value="Private blocklist" description | rename src_ip as ip | inputlookup append=T ip_myblocklist.csv | dedup ip | table ip,is_blocked,description | outputlookup ip_myblocklist.csv
The goal of this search is to get a single instance of the ip address in question, label it ip, and then generate KV pairs for is_blocked=true and description=”Private blocklist”. It also pulls in the existing blocklist and deduplicates before writing.
Restart splunk and you should be good to go. One gotcha is that the workflow action will cause a new window to pop open; I suspect there’s a search.target value which will stop that from happening or at least make it more useful, but I haven’t found it yet. Another really useful way to use this technique is to POST them off to some other system where a more active response can be offered, such as a firewall’s deny listing.
For more information, here’s some of what I read while figuring this out: