Learn How To Create a Custom Threat Map in Splunk: Part 1

This tutorial series will be going through the steps of creating a custom Threat Map. During this process we will be using Google Maps, which is fortunately already built into Splunk. We will be using the Splunk Web Framework to build out our app.

One of my recent blog posts/screencasts discusses how to integrate CartoDB into Splunk in order to provide a cool map with some animations. Now, we’re going to move on to the next level. This three-part blog post/screencast combo allows for even more visual control and enables you to drill deeper into the details you’re looking for.

More specifically, we will be going through the steps of creating a custom Threat Map. During this process we will be using Google Maps, which is fortunately already built into Splunk. We will be using the Splunk Web Framework to build out our app.

Part 1 will cover the basics of setting up a Google Map in Splunk with the Splunk Web Framework. Part 2 will show how to customize the map and add our awesome custom threat skull icons. Finally, part 3 portrays how to pass token values from this map to another visualization (in this case, an area chart that will show how many times a source ip hit our firewall over a period of time).

UFW logs indexed by Splunk will be used for these examples, but can replace them with your own logs. Any will do as long as you can pull out the latitude and longitude properties in your search.

The attractive thing about Google Maps is we can use some custom icons. In this specific scenario, we are going to use skulls to represent the amount of times a specific IP hits our firewall. The more times a specific ip hits our firewall the bigger the skull icon will get (as they represent a potentially bigger threat), and they will change color as well.

And just as a friendly reminder, if you'd rather watch a screencast on this, you can go here as well.

A Note about http vs https:

If your Splunk install is using https, you will need to change some core Splunk files in order to get this to work properly. By default, Splunk loads Google Maps through http - I REALLY hope they fix this in the future so it loads whatever you have set by default in order to prevent the necessity to override core files.

The following files need to be updated, so any instance of http, needs to be changed to https:

Part 1: Set It Up

First, go to $SPLUNK_HOME/etc/apps/framework and run ./splunkdj createapp , it will then prompt you for your username and password. It will then say something like

After you restart Splunk go to your template in >span class="theme:twilight font:consolas font-size:16 line-height:25 toolbar:2 lang:default decode:true crayon-inline"><appname>/templates/home.html and open that up. You should now have something like this:

Default app view

Before moving on, make sure you upload the skulls folder I provided in a zip file above. You want to upload this so the ‘skulls’ folder is in$SPLUNK_HOME/etc/apps/<appname>/django/<appname>/static/<appname>/

Part 2: The Search
Obviously, we need a search. Here is the one I will be using:

I have a sourcetype of UFW and will be using the iplocation command to to pull out the lon and lat fields from the SRC field, which are source ips hitting my firewall. I then rename the lon field to lng as Google Maps will be expecting lng instead of lon. I perform a stats count by the latitude, longitude, County, City and SRC (source ip). I then want to be able to create a range value depending on the amount of times a specific IP is hitting my firewall. So, I use the eval command with case in order to split up ips into low, medium, moderate, critical and severe categories.

The categories we create are important, as they are how we determine what type of skull icon we will use in the visualization on the map. So, a category of low will load a different skull than a category of critical.

Here, I’ve created a new Search Manager with an id and managerid of “googlemap-search”. These don’t have to be named the same, but the managerid is the important one. It’s what we will be referencing this search by in our maps visualization to pull the search results.