Splunk Search

Windows Session Tracking

dfarr
Explorer

Hello, I am trying to build a search to identify windows user sessions. The main goal was a list/track of users who do not log off of shared systems at the end of the day. There are more use cases I would like to get like identifying concurrent sessions. I think I am close, but I only get open sessions and some weird durations that are not correct. Any suggestions would be appreciated. 

index="main" sourcetype=WinEventLog:Security ((EventCode=4624 AND (Logon_Type=2 OR Logon_Type=3 OR Logon_Type=10 OR Logon_Type=11)) OR EventCode=4634 OR EventCode=4647)
| eval TargetUserName=coalesce(TargetUserName, Account_Name)
| where TargetUserName!="$*" AND TargetUserName!="SYSTEM" AND TargetUserName!="LOCAL SERVICE" AND TargetUserName!="NETWORK SERVICE"
| eval EventType = case(EventCode=4624, "Logon", EventCode=4634 OR EventCode=4647, "Logoff")
| sort 0 TargetUserName host -_time
| streamstats count(eval(EventType="Logoff")) as session_rev by TargetUserName host
| stats earliest(eval(if(EventType="Logon", _time, null()))) as firstLogOnEpoch
       latest(eval(if(EventType="Logoff", _time, null()))) as lastLogOffEpoch
        min(_time) as SessionStartEpoch
        max(_time) as SessionEndEpoch
        count(eval(EventType="Logon")) as LogonCount
        count(eval(EventType="Logoff")) as LogoffCount
    by TargetUserName host session_rev
| eval SessionDurationSec = SessionEndEpoch - SessionStartEpoch
| eval SessionDuration = if(isnull(SessionDurationSec),"N/A", tostring(SessionDurationSec,"duration"))
| eval SessionStart = strftime(SessionStartEpoch,"%Y-%m-%d %H:%M:%S")
| eval SessionEnd   = strftime(SessionEndEpoch,"%Y-%m-%d %H:%M:%S")
| eval firstLogOn = if(isnull(firstLogOnEpoch),"", strftime(firstLogOnEpoch,"%Y-%m-%d %H:%M:%S"))
| eval lastLogOff  = if(isnull(lastLogOffEpoch),"", strftime(lastLogOffEpoch,"%Y-%m-%d %H:%M:%S"))
| eval IsOpenSession = if(isnull(lastLogOffEpoch), 1, 0)
| eval Notes = case(
    IsOpenSession=1, "Open session: No logoff found after this logon",
    firstLogOn==SessionStart, "SessionStart is first event in search window: firstLogOn may precede search window", 1==1, "")
| table TargetUserName host firstLogOn lastLogOff SessionStart SessionEnd SessionDuration LogonCount LogoffCount IsOpenSession Notes
| sort -SessionStartEpoch
Labels (3)
0 Karma

bowesmana
SplunkTrust
SplunkTrust

There are many ways to achieve this with streamstats, but my example goes with sorting in ascending time and calculating duration in the streamstats.

See this example which creates 10 dummy logon/off events for a single user/host (SPL can demo up to 4 by changing the 'random() mod value from 1 to 4 in user/host eval)

| makeresults count=10
| eval EventType=mvindex(split("Logon,Logoff", ","), random() % 2)
| eval TargetUserName="USER".mvindex(split("ABCD", ""), random() % 1)
| eval host="HOST".mvindex(split("ABCD", ""), random() % 1)
| eval _time=_time - random() % 3600
| fields EventType Target* host _time
| sort 0 TargetUserName host  _time
| streamstats range(_time) as SessionDurationSec reset_after="("EventType=\"Logoff\"")" by TargetUserName host
| streamstats count(eval(SessionDurationSec=0)) as session by TargetUserName host
| eval SessionStart=if(EventType="Logoff", _time - SessionDurationSec, null())
``` Change this to stats to collapse data ```
| eventstats 
  max(SessionDurationSec) as SessionDurationSec
  min(SessionStart) as SessionStart
  count(eval(EventType="Logon")) as LogonCount
  min(eval(if(EventType="Logon", _time, null()))) as firstLogOn
  max(eval(if(EventType="Logoff", _time, null()))) as lastLogOff
  by TargetUserName host session
| eval SessionDuration = if(SessionDurationSec=0,"N/A", tostring(SessionDurationSec,"duration"))
| eval IsOpenSession = if(isnull(lastLogOff), 1, 0)
| eval Notes = case(
    IsOpenSession=1, "Open session: No logoff found after this logon",
    isnull(firstLogOn), "No prior login state found in search window", 1==1, "")
| foreach SessionStart firstLogOn lastLogOff [ eval <<FIELD>>=if(isnull(<<FIELD>>),null(), strftime(<<FIELD>>,"%F %T")) ]
```| table EventType TargetUserName host firstLogOn lastLogOff SessionStart SessionEnd SessionDuration LogonCount LogoffCount IsOpenSession Notes```

I've used an eventstats rather than stats so you can see the effect of the decisions made in the SPL, but you can change that to stats to get rid of the unwanted events.

The example ignores multiple logoff events and treats a logoff with no prior login (since a previous logoff) as a 0 length session.

Hope this helps

 

0 Karma
Got questions? Get answers!

Join the Splunk Community Slack to learn, troubleshoot, and make connections with fellow Splunk practitioners in real time!

Meet up IRL or virtually!

Join Splunk User Groups to connect and learn in-person by region or remotely by topic or industry.

Get Updates on the Splunk Community!

Step into “Hunt the Insider: An Splunk ES Premier Mystery” to catch a cybercriminal ...

After a whole week of being on call, you fell asleep on your keyboard, and you hit a sequence of buttons that ...

SplunkTrust Application Period is Officially OPEN!

It's that time, folks! The application/nomination period for the 2026-2027 SplunkTrust is officially open. If ...

Announcing Modern Navigation: A New Era of Splunk User Experience

We are excited to introduce the Modern Navigation feature in the Splunk Platform, available to both cloud and ...