Oftentimes we are required to determine impossible or improbably access events. Typically, this is a relatively simple thing to do in a modern SIEM, however Splunk, without ESS, does not have a “great” way to handle this type of temporal correlation aside from appends or joins back to the original data. I constructed the following search parameters, but feel free to modify based on any log source you’d like to validate authentication probability for.Use Case:
Use Case: A user logs in from Canada at 1300 and the same user authenticates from another country at 1305. This is typically indicative of a hijacked session, leaked credentials, etc.
index= sourcetype= (typically network) | eventstats dc(src) as src_count by user | search src_count>1 | sort 0 + _time | iplocation src | where isnotnull(lat) AND isnotnull(lon) | streamstats window=2 earliest(lat) as prev_lat, earliest(lon) as prev_lon, earliest(_time) as prev_time, earliest(src) as prev_src, earliest(City) as prev_city, earliest(Country) as prev_country, earliest(app) as prev_app by user | where (src != prev_src) | eval lat1_r=((lat * 3.14159265358) / 180), lat2_r=((prev_lat * 3.14159265358) / 180), delta=(((prev_lon - lon) * 3.14159265358) / 180), distance=(3959 * acos(((sin(lat1_r) * sin(lat2_r)) + ((cos(lat1_r) * cos(lat2_r)) * cos(delta))))), distance=round(distance,2) | fields - lat1_r, lat2_r, long1_r, long2_r, delta | eval time_diff=if((('_time' - prev_time) == 0),1,('_time' - prev_time)), speed=round(((distance * 3600) / time_diff),2) | where (speed > 500) | eval prev_time=strftime(prev_time,"%Y-%m-%d %H:%M:%S") | table user, src, _time, City, Country, app, prev_src, prev_time, prev_city, prev_country, prev_app, distance, speed