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
Get Updates on the Splunk Community!

Splunkers, Pack Your Bags: Why Cisco Live EMEA is Your Next Big Destination

The Power of Two: Splunk &#43; Cisco at "Ludicrous Scale"   You know Splunk. You know Cisco. But have you seen ...

Data Management Digest – January 2026

Welcome to the January 2026 edition of Data Management Digest! Welcome to the January 2026 edition of Data ...

Splunk SOAR Now Available on Google Cloud Platform

We’re excited to announce that Splunk SOAR is now natively available as a SaaS solution on Google Cloud ...