Splunk Search

Windows Session Tracking

dfarr
Observer

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!

.conf25 technical session recap of Observability for Gen AI: Monitoring LLM ...

If you’re unfamiliar, .conf is Splunk’s premier event where the Splunk community, customers, partners, and ...

A Season of Skills: New Splunk Courses to Light Up Your Learning Journey

There’s something special about this time of year—maybe it’s the glow of the holidays, maybe it’s the ...

Announcing the Migration of the Splunk Add-on for Microsoft Azure Inputs to ...

Announcing the Migration of the Splunk Add-on for Microsoft Azure Inputs to Officially Supported Splunk ...