Monday, August 1, 2011

Scripts for monitoring session logon, connect, logout, lock/unlock events across domain

Ok, here is a nice script to use for security purposes, time tracking or whatever fancy name you give to this solution
It is possible since Windows 2008 to use triggers like session lock, unlock, remote connect (RDP) in scheduled tasks. Moreover, the tasks run in the context of the user that triggered the event.
So basically we have to deploy tasks on all Vista/7/2008 R2 computers, tasks that will run when these events are triggered and will, for instance, insert in a database the user various session events (in our case we report by sending an HTTP request with additional data to a linux web server)
Additional data that is available is : user samaccountname, computer name where the event fired, client computer name in a RDP connect/logon event, type of event, of course event time is calculated at the database level.
To make all this work, we must first deploy the tasks on all computers. That will be done with a startup batch script in a GPO
but first you have to create all the tasks that will run our master script (the one that reports events) on a reference computer :
do not forget :
One task = one trigger = one command line with the type of event as a script argument
and do not forget to allow an adequate user group to run the task. Windows will run the task in the context of a user if he is member of the group.
now define the scheduled task action :
Easy : path to the script + EVENT TYPE as argument
(I could not find a way to know during script runtime what trigger fired the task) so we have to create as much scripts than the events we wish to monitor.
command line exemple :
c:\windows\scripts\user-event-monitor.vbs RCONNECT
You may use any moniker, i use these :
LOGON (session logon)
LOGOFF (session logoff / task trigger DOES NOT EXIST, you have to use a GPO logoff script))
RCONNECT (remote, RDP connect)
RDISCONNECT (RDP disconnect)
LCONNECT (connect to a user session by console, when switching users on Vista/7)
LDISCONNECT (see above, disconnect)
LOCK (session lock)
UNLOCK (session unlock)
So it makes a bunch of tasks, now you have to export their definition using SCHTASKS and the XML switch and create a batch to import them on all client computers and RDS servers. (by GPO as said above)
Here is the deployment batch :

mkdir %windir%\scripts
xcopy file://domain.local/NETLOGON/User-Monitor.vbs %windir%\scripts\User-Monitor.vbs
xcopy file://domain.local/NETLOGON/User-Monitor-RConnect.xml %windir%\scripts\User-Monitor-RConnect.xml
xcopy file://domain.local/NETLOGON/User-Monitor-LConnect.xml %windir%\scripts\User-Monitor-LConnect.xml
xcopy file://domain.local/NETLOGON/User-Monitor-RDisconnect.xml %windir%\scripts\User-Monitor-RDisconnect.xml
xcopy file://domain.local/NETLOGON/User-Monitor-LDisconnect.xml %windir%\scripts\User-Monitor-LDisconnect.xml
xcopy file://domain.local/NETLOGON/User-Monitor-Logon.xml %windir%\scripts\User-Monitor-Logon.xml
xcopy file://domain.local/NETLOGON/User-Monitor-Lock.xml %windir%\scripts\User-Monitor-Lock.xml
xcopy file://domain.local/NETLOGON/User-Monitor-Unlock.xml %windir%\scripts\User-Monitor-Unlock.xml
schtasks /create /xml %windir%\scripts\User-Monitor-LConnect.xml /tn "User-Monitor-LConnect"
schtasks /create /xml %windir%\scripts\User-Monitor-RConnect.xml /tn "User-Monitor-RConnect"
schtasks /create /xml %windir%\scripts\User-Monitor-LDisonnect.xml /tn "User-Monitor-LDisconnect"
schtasks /create /xml %windir%\scripts\User-Monitor-RDisconnect.xml /tn "User-Monitor-RDisconnect"
schtasks /create /xml %windir%\scripts\User-Monitor-Logon.xml /tn "User-Monitor-Logon"
schtasks /create /xml %windir%\scripts\User-Monitor-Lock.xml /tn "User-Monitor-Lock"
schtasks /create /xml %windir%\scripts\User-Monitor-Unlock.xml /tn "User-Monitor-Unlock"

and here is the master reporting script :

on error resume next
set onet = createobject("wscript.network")
set oshell = createobject("wscript.shell")
Set objWinHttp = CreateObject("WinHttp.WinHttpRequest.5.1")
set oargs = wscript.arguments
set regex = new regexp
lngTimeout = 59000
regex.pattern = ">rdp-tcp#\d+\s+\S+\s+(\d+)"
set oexec = oshell.exec("query session " & onet.username)
oexec.stdout.readline
line = oexec.stdout.readline
set omatches = regex.execute(line)
set submatches = omatches(0).submatches
sessionid =  submatches(0)
clientname = oshell.regread("HKCU\Volatile Environment\" & sessionid & "\CLIENTNAME")
objWinHttp.SetTimeouts lngTimeout, lngTimeout, lngTimeout, lngTimeout
objWinHttp.open "GET" , "https://example.local/usermonitor.php?nav_user=" & onet.username & "&nav_file=" & oargs(0) & "&nav_module=" & onet.computername & "&nav_session=" & clientname
objwinhttp.send


I had to make some strange code in order to get the RDS "CLIENTNAME" variable. It is specific to Windows 2008 / R2  i never had trouble to get the var on Windows 2003
Also, the logoff event is not managed by a task since the trigger DOES NOT EXIST, the solution is to create a GPO with a logoff script.
Have a nice day !