<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/" version="2.0">
  <channel>
    <title>topic Re: How to Create &amp;quot;Impossible Travel&amp;quot; Security Monitoring Use Case with pure SPL in Splunk Search</title>
    <link>https://community.splunk.com/t5/Splunk-Search/How-to-Create-quot-Impossible-Travel-quot-Security-Monitoring/m-p/448810#M127141</link>
    <description>&lt;P&gt;Interesting.&lt;/P&gt;</description>
    <pubDate>Mon, 29 Oct 2018 21:08:16 GMT</pubDate>
    <dc:creator>wrangler2x</dc:creator>
    <dc:date>2018-10-29T21:08:16Z</dc:date>
    <item>
      <title>How to Create "Impossible Travel" Security Monitoring Use Case with pure SPL</title>
      <link>https://community.splunk.com/t5/Splunk-Search/How-to-Create-quot-Impossible-Travel-quot-Security-Monitoring/m-p/448805#M127136</link>
      <description>&lt;P&gt;I have some reservations about the usefulness of this with so much more usage of IaaS/PaaS/SaaS these days...but since this is non-trivial to produce, I thought I would save everyone the work of developing from scratch if it is something you'd like to monitor.  I would also like to note, this has bubbled up activity that was unauthorized/malicious in my experience...so maybe it's not useless...&lt;/P&gt;

&lt;P&gt;This uses a macro built on the search string provided by @MuS in this post: &lt;A href="https://answers.splunk.com/answers/90694/find-the-distance-between-two-or-more-geolocation-coordinates.html#answer-568450"&gt;https://answers.splunk.com/answers/90694/find-the-distance-between-two-or-more-geolocation-coordinates.html#answer-568450&lt;/A&gt;&lt;/P&gt;

&lt;P&gt;Prerequisites:&lt;/P&gt;

&lt;OL&gt;
&lt;LI&gt;normalized fields: user, src_ip&lt;/LI&gt;
&lt;LI&gt;geodistance macro&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;&lt;EM&gt;well filtered&lt;/EM&gt;&lt;/STRONG&gt; base search of 10000 or less events  &lt;STRONG&gt;OR&lt;/STRONG&gt;&lt;/LI&gt;
&lt;LI&gt;streamstats  &lt;CODE&gt;limits.conf&lt;/CODE&gt;  &lt;CODE&gt;max_stream_window = &amp;lt;adjusted for base search&amp;gt;&lt;/CODE&gt; &lt;STRONG&gt;DO NOT RAISE THIS ARBITRARILY&lt;/STRONG&gt; in my environment I have raised this to an upper limit of +10% of my average base events (to include my max) over the past month after doing a LOT of filtering in the base search&lt;/LI&gt;
&lt;LI&gt;filtering clauses to get this down to a manageable number of results&lt;/LI&gt;
&lt;/OL&gt;</description>
      <pubDate>Mon, 29 Oct 2018 18:13:44 GMT</pubDate>
      <guid>https://community.splunk.com/t5/Splunk-Search/How-to-Create-quot-Impossible-Travel-quot-Security-Monitoring/m-p/448805#M127136</guid>
      <dc:creator>marycordova</dc:creator>
      <dc:date>2018-10-29T18:13:44Z</dc:date>
    </item>
    <item>
      <title>Re: How to Create "Impossible Travel" Security Monitoring Use Case with pure SPL</title>
      <link>https://community.splunk.com/t5/Splunk-Search/How-to-Create-quot-Impossible-Travel-quot-Security-Monitoring/m-p/448806#M127137</link>
      <description>&lt;P&gt;create a new macro with no arguments: "geodistance"&lt;/P&gt;

&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper" image-alt="alt text"&gt;&lt;img src="https://community.splunk.com/t5/image/serverpage/image-id/5995iC0DCACAC02CC9E01/image-size/large?v=v2&amp;amp;px=999" role="button" title="alt text" alt="alt text" /&gt;&lt;/span&gt;&lt;/P&gt;

&lt;PRE&gt;&lt;CODE&gt;iplocation src_ip 
| rename lat as src_lat lon as src_lon City as src_city Region as src_region Country as src_country 
| iplocation dest_ip 
| rename lat as dest_lat lon as dest_lon City as dest_city Region as dest_region Country as dest_country 
| search src_lat!="," src_lon!="," dest_lat!="," dest_lon!="," 
| eval lat=(dest_lat-src_lat)*pi()/180 
| eval lon=(dest_lon-src_lon)*pi()/180 
| eval dest_rad=dest_lat*pi()/180 
| eval src_rad=src_lat*pi()/180 
| eval a=pow(sin(lat/2),2)+pow(sin(lon/2),2)*cos(dest_rad)*cos(src_rad) 
| eval miles=(12742*atan2(sqrt(a),sqrt(1-a)))*0.621371 
| eval km=12742*atan2(sqrt(a),sqrt(1-a)) 
| eval hours=if(((dest_time-src_time)/60/60)=0,".01",(abs(((dest_time-src_time)/60/60)))) 
| eval mph=miles/hours 
| eval kph=km/hours 
| fillnull value=""
&lt;/CODE&gt;&lt;/PRE&gt;</description>
      <pubDate>Mon, 29 Oct 2018 18:57:36 GMT</pubDate>
      <guid>https://community.splunk.com/t5/Splunk-Search/How-to-Create-quot-Impossible-Travel-quot-Security-Monitoring/m-p/448806#M127137</guid>
      <dc:creator>marycordova</dc:creator>
      <dc:date>2018-10-29T18:57:36Z</dc:date>
    </item>
    <item>
      <title>Re: How to Create "Impossible Travel" Security Monitoring Use Case with pure SPL</title>
      <link>https://community.splunk.com/t5/Splunk-Search/How-to-Create-quot-Impossible-Travel-quot-Security-Monitoring/m-p/448807#M127138</link>
      <description>&lt;P&gt;As an add-on here is my macro I use to get distances based on lat's and lon's &lt;span class="lia-unicode-emoji" title=":slightly_smiling_face:"&gt;🙂&lt;/span&gt;&lt;/P&gt;

&lt;PRE&gt;&lt;CODE&gt;[distance(4)]
args = lat1,lon1,lat2,lon2
definition = eval rlat1 = pi()*$lat1$/180, rlat2=pi()*$lat2$/180, rlat = pi()*($lat2$-$lat1$)/180, rlon= pi()*($lon2$-$lon1$)/180\
| eval a = sin(rlat/2) * sin(rlat/2) + cos(rlat1) * cos(rlat2) * sin(rlon/2) * sin(rlon/2) \
| eval c = 2 * atan2(sqrt(a), sqrt(1-a)) \
| eval distance = 6371 * c |  fields - a c r*
iseval = 0
&lt;/CODE&gt;&lt;/PRE&gt;

&lt;P&gt;It is part of my Dark Sky app featured in this .conf2017 talk &lt;A href="https://conf.splunk.com/files/2017/slides/take-a-talk-into-the-art-of-dark-sky-photography-with-a-splunk-ninja.pdf"&gt;https://conf.splunk.com/files/2017/slides/take-a-talk-into-the-art-of-dark-sky-photography-with-a-splunk-ninja.pdf&lt;/A&gt;&lt;/P&gt;

&lt;P&gt;cheers, MuS&lt;/P&gt;</description>
      <pubDate>Mon, 29 Oct 2018 19:09:21 GMT</pubDate>
      <guid>https://community.splunk.com/t5/Splunk-Search/How-to-Create-quot-Impossible-Travel-quot-Security-Monitoring/m-p/448807#M127138</guid>
      <dc:creator>MuS</dc:creator>
      <dc:date>2018-10-29T19:09:21Z</dc:date>
    </item>
    <item>
      <title>Re: How to Create "Impossible Travel" Security Monitoring Use Case with pure SPL</title>
      <link>https://community.splunk.com/t5/Splunk-Search/How-to-Create-quot-Impossible-Travel-quot-Security-Monitoring/m-p/448808#M127139</link>
      <description>&lt;OL&gt;
&lt;LI&gt;&lt;STRONG&gt;base search:&lt;/STRONG&gt; as many indexes/data sources as might contain authentication, authorization, or access data that may be relevant for monitoring potential unauthorized or malicious activity&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;filter out garbage IP addresses:&lt;/STRONG&gt;  &lt;CODE&gt;src_ip!=&amp;lt;rfc 1918 addresses&amp;gt; src_ip!=&amp;lt;whatever other garbage you don't need&amp;gt;&lt;/CODE&gt; maybe you don't really want to try to deal with IPv6 addresses, maybe you have a lookup that you can drop all your known public ip space&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;filter out garbage user data:&lt;/STRONG&gt;  &lt;CODE&gt;user!=*test* user!=&amp;lt;whatever other garbage you don't need&amp;gt;&lt;/CODE&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;normalize user:&lt;/STRONG&gt; in my case I take whatever user attribute is in the base search, username or email address or whatever, and then query my IAM provider to return a standard value type for my user field, for example email address&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;dedup for each user:&lt;/STRONG&gt; from your base search you want each unique ip address and _time for each individual user, for me this took about 250K events down to about 30K, you would think including _time in the dedup would render the dedup useless but in this case it did not and _time is a critical field, you may also want to include index or sourcetype (whichever is applicable)&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;prep for streamstats, the "current" data becomes the "destination":&lt;/STRONG&gt; dest_time, dest_ip &lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;prep for streamstats, sort your data for each user and _time:&lt;/STRONG&gt; streamstats needs to work a single user's data _time sorted so the results aren't broken into different sets (default limit of 10K)&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;streamstats to create the "source" for each "destination":&lt;/STRONG&gt; from the users previous event src_time, src_ip are generated (default limit of 10K)&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;filter out garbage streamstats data:&lt;/STRONG&gt; the first event for every user will have a null src_ip, and events with the same src and dest ip addresses are useless&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;calculate geo statistics:&lt;/STRONG&gt; the  &lt;CODE&gt;geodistance&lt;/CODE&gt; macro will take src_ip and dest_ip as arguments and return the city, region and country for each ip, the distance traveled in km and miles, hours it took to travel, and the kph and mph&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;additional filtering logic:&lt;/STRONG&gt; in my case I dropped all events where mph are less than the speed of a commercial airplane as well as any events where the src and dest regions (such as a single U.S. state) are the same&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;pretty print the output&lt;/STRONG&gt;&lt;/LI&gt;
&lt;/OL&gt;</description>
      <pubDate>Tue, 29 Sep 2020 21:46:26 GMT</pubDate>
      <guid>https://community.splunk.com/t5/Splunk-Search/How-to-Create-quot-Impossible-Travel-quot-Security-Monitoring/m-p/448808#M127139</guid>
      <dc:creator>marycordova</dc:creator>
      <dc:date>2020-09-29T21:46:26Z</dc:date>
    </item>
    <item>
      <title>Re: How to Create "Impossible Travel" Security Monitoring Use Case with pure SPL</title>
      <link>https://community.splunk.com/t5/Splunk-Search/How-to-Create-quot-Impossible-Travel-quot-Security-Monitoring/m-p/448809#M127140</link>
      <description>&lt;P&gt;thanks! &lt;span class="lia-unicode-emoji" title=":slightly_smiling_face:"&gt;🙂&lt;/span&gt;&lt;/P&gt;</description>
      <pubDate>Mon, 29 Oct 2018 20:17:10 GMT</pubDate>
      <guid>https://community.splunk.com/t5/Splunk-Search/How-to-Create-quot-Impossible-Travel-quot-Security-Monitoring/m-p/448809#M127140</guid>
      <dc:creator>marycordova</dc:creator>
      <dc:date>2018-10-29T20:17:10Z</dc:date>
    </item>
    <item>
      <title>Re: How to Create "Impossible Travel" Security Monitoring Use Case with pure SPL</title>
      <link>https://community.splunk.com/t5/Splunk-Search/How-to-Create-quot-Impossible-Travel-quot-Security-Monitoring/m-p/448810#M127141</link>
      <description>&lt;P&gt;Interesting.&lt;/P&gt;</description>
      <pubDate>Mon, 29 Oct 2018 21:08:16 GMT</pubDate>
      <guid>https://community.splunk.com/t5/Splunk-Search/How-to-Create-quot-Impossible-Travel-quot-Security-Monitoring/m-p/448810#M127141</guid>
      <dc:creator>wrangler2x</dc:creator>
      <dc:date>2018-10-29T21:08:16Z</dc:date>
    </item>
    <item>
      <title>Re: How to Create "Impossible Travel" Security Monitoring Use Case with pure SPL</title>
      <link>https://community.splunk.com/t5/Splunk-Search/How-to-Create-quot-Impossible-Travel-quot-Security-Monitoring/m-p/448811#M127142</link>
      <description>&lt;PRE&gt;&lt;CODE&gt;| index=x OR index=y OR index=z src_ip!=192.168.* src_ip!=*:* user!=*test*
| lookup src_ips.csv src_ip as src_ip outputnew description
| where isnull(description)
| lookup users.csv attr1 as user outputnew email 
| lookup users.csv attr2 as user outputnew email &amp;lt;etc iterate as necessary or however you do user normalization&amp;gt;
| eval src_user='email'
| dedup src_user src_ip index _time
| rex field=_time "(?&amp;lt;dest_time&amp;gt;^\d+)"
| rename src_ip as dest_ip
| sort 0 src_user dest_time
| streamstats values(dest_ip) as src_ip values(dest_time) as src_time by src_user window=1 current=false &amp;lt;the window and current options are KEY here&amp;gt;
| where isnotnull(src_ip) AND (NOT 'src_ip'=='dest_ip')
| `geodistance(src_ip,dest_ip)`
| where mph&amp;gt;575 AND 'src_region'!='dest_region'
| stats values(src_ip) as src_ip values(dest_ip) as dest_ip list(src_city) as src_city list(src_region) as src_region list(src_country) as src_country list(dest_city) as dest_city list(dest_region) as dest_region list(dest_country) as dest_country avg(miles) as miles avg(hours) as hours avg(mph) as mph by src_user
| eval miles=round(miles,2)
| eval km=round(km,2)
| eval hours=round(hours,2)
| eval mph=round(mph,2)
| eval kph=round(kph,2)
| eval src_ip=mvdedup(split((mvjoin((mvzip(src_ip,dest_ip)),",")),","))
| eval src_city=mvdedup(split((mvjoin((mvzip(src_city,dest_city)),",")),","))
| eval src_region=mvdedup(split((mvjoin((mvzip(src_region,dest_region)),",")),","))
| eval src_country=mvdedup(split((mvjoin((mvzip(src_country,dest_country)),",")),","))
| table src_user src_ip src_city src_region src_country miles km hours mph kph
&lt;/CODE&gt;&lt;/PRE&gt;</description>
      <pubDate>Tue, 30 Oct 2018 17:28:20 GMT</pubDate>
      <guid>https://community.splunk.com/t5/Splunk-Search/How-to-Create-quot-Impossible-Travel-quot-Security-Monitoring/m-p/448811#M127142</guid>
      <dc:creator>marycordova</dc:creator>
      <dc:date>2018-10-30T17:28:20Z</dc:date>
    </item>
    <item>
      <title>Re: How to Create "Impossible Travel" Security Monitoring Use Case with pure SPL</title>
      <link>https://community.splunk.com/t5/Splunk-Search/How-to-Create-quot-Impossible-Travel-quot-Security-Monitoring/m-p/709544#M239809</link>
      <description>&lt;P data-unlink="true"&gt;A thing of beauty &lt;A href="https://community.splunk.com/t5/user/viewprofilepage/user-id/159620" target="_blank"&gt;marycordova&lt;/A&gt;&amp;nbsp;- thank you!&lt;/P&gt;</description>
      <pubDate>Thu, 23 Jan 2025 02:06:10 GMT</pubDate>
      <guid>https://community.splunk.com/t5/Splunk-Search/How-to-Create-quot-Impossible-Travel-quot-Security-Monitoring/m-p/709544#M239809</guid>
      <dc:creator>bgriffis</dc:creator>
      <dc:date>2025-01-23T02:06:10Z</dc:date>
    </item>
  </channel>
</rss>

