I am trying to find a way to correlate two Windows events together to detect a few forms of lateral movement. The caveat here is that the username will not be known prior to the activity occurring otherwise this would be a lot easier. Lets use WMIC as an example.
Executing this command: wmic /node:[IP address] process call create "cmd.exe /c calc.exe" yields two events similar to this (username and IP information purposely omitted):
An account was successfully logged on.
Subject:
Security ID: NULL SID
Account Name: -
Account Domain: -
Logon ID: 0x0
Logon Type: 3
Impersonation Level: Impersonation
New Logon:
Security ID: [domain\account name]
Account Name: [account name]
Account Domain: [domain]
Logon ID: 0x11CB611B
Logon GUID: {00000000-0000-0000-0000-000000000000}
Process Information:
Process ID: 0x0
Process Name: -
Network Information:
Workstation Name: [hostname]
Source Network Address: [IP]
Source Port: 63790
and:
A new process has been created.
Subject:
Security ID: [domain\account name]
Account Name: [account name]
Account Domain: [domain]
Logon ID: 0x11CB611B
Process Information:
New Process ID: 0x2d3c
New Process Name: C:\Windows\System32\calc.exe
Token Elevation Type: TokenElevationTypeDefault (1)
Creator Process ID: 0x1cbc
Process Command Line: calc.exe
As you can see, the value for "Logon ID" is the same for both events. What I want to do is correlate the Logon ID field from both the logon event (EventCode 4672) and the new process created event (EventCode 4688) that follows and get results that contains the username, source IP, destination IP and the process executed along with the command line (if available).
I've gotten this search to work pretty reliably, but occasionally get some mixed results:
index=wineventlog sourcetype=WinEventLog:Security (EventCode=4688 OR EventCode=4624) NOT (New_Process_Name="C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe" OR New_Process_Name="C:\\Windows\\system32\\conhost.exe") | transaction Account_Name startswith=EventCode=4624 endswith=EventCode=4688 maxspan=0s | eval Account_Name=mvindex(Account_Name,1) | table _time Account_Name Source_Network_Address dest_nt_host New_Process_Name Process_Command_Line
To be 100% accurate though, in my mind you’d have to take the Login_ID value, set it as a variable somehow, and then look for that variable in the next event. Is that possible? The eval command lets you use if statements, is there a way to use an if statement like “if Login_ID from EventCode=4624 is Login_ID value from EventCode=4688" then match. Is that even possible?
Try changing from Transaction to Stats. Investigate your missing/incorrect correlated events by adjusting the search filter
| search CorrelatedEventCount>1 AND EventCode=4688 AND EventCode=4624
before stats.
index=wineventlog sourcetype=WinEventLog:Security (EventCode=4688 OR EventCode=4624) NOT (New_Process_Name="C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe" OR New_Process_Name="C:\\Windows\\system32\\conhost.exe")
|stats count as CorrelatedEventCount min(_time) as MinTime max(_time) as MaxTime values(EventCode) as EventCode values(Source_Network_Address) as Source_Network_Address values(dest_nt_host) as dest_nt_host values(New_Process_Name) as New_Process_Name values(Process_Command_Line) as Process_Command_Line by Account_Name
| search CorrelatedEventCount>1 AND EventCode=4688 AND EventCode=4624
| eval duration = MaxTime-MinTime
| eval _time=MinTime
| fields - MinTime
| table _time Account_Name CorrelatedEventCount duration Source_Network_Address dest_nt_host New_Process_Name Process_Command_Line
Thank you, but that just brings up a table with two columns - MaxTime and EventCode. Is there a mistake in that search string?
Is there no way to tie events together with the Login_ID field? I do have access to Enterprise Security and Extreme Search, will either of those provide the means to do that?
@aqstevens... I had taken the field names from your previous query, can you please ensure that field name and case is same as that in your data being searched?
You can add the following before stats to make sure you are getting all the fields as required for stats.
| table _time Account_Name Source_Network_Address dest_nt_host New_Process_Name Process_Command_Line
Run the query with table command and without stats to ensure all fields being displayed as expected,
Then run the stats (match all the field names in stats command and run without search criteria to ensure stats is correlating events as expected.
Finally you can add in the search condition as per your need. Let us know how it goes.