PowerShell application for IT security. Part II: file access analysis

Original author: Andy Green
When working on this series of articles, I almost believed that with PowerShell we had a technology that inexplicably came to us from the future. Remember the Star Trek series - the original, of course - when the senior officer of the Enterprise starship Spock looked into his visor, scanning the parses of space? Actually, Spock was looking at the results of the StarFleet approved PowerShell script.


Tricoders? They also work on the basis of PowerShell technology.

Yes, I am a fan of PowerShell technology, and boldly explore a topic that none of the bloggers had previously considered. For those educated in the elementary languages ​​of the Linux shell, PowerShell looks like super-advanced technology. One of the high-tech features of PowerShell, as I mentioned earlier in my article, is the ability to track low-level OS events, such as file updates.

Detailed Analysis of the Register-WmiEvent Request

Let's go back to the wonderful PS code for monitoring files from just one line, which I presented last time.

1.	Register-WmiEvent -Query "SELECT * FROM __InstanceModificationEvent WITHIN 5 WHERE TargetInstance ISA 'CIM_DataFile' and TargetInstance.Path = '\\Users\\bob\\' and targetInstance.Drive = 'C:' and (targetInstance.Extension = 'doc' or targetInstance.Extension = 'txt)' and targetInstance.LastAccessed > '$($cur)' " -sourceIdentifier "Accessor" -Action $action
 

As you might have guessed, the logic of what is being tracked is contained in WQL in the Register-WmiEvent query parameter.

As we recall, WQL allows script authors to get general information about events in the Windows system and, as in our case, about file events — creating, updating or changing files. With this query, I can easily get information about file modification events from the dark depths of Windows, which are presented in the form of the CIM_DataFile class.
WQL allows you to specify the media and folder in which to search. To do this, use the above properties of Drive and Path.

Although I cannot use wildcard search, this is a language feature, not an error - instead, I can search for specific file extensions. In developing the script for this note, my goal was to help IT security professionals detect the excessive activity associated with text files. Therefore, I set a logical condition for finding files with doc or txt extensions. Is it logical?

Now consider one non-obvious point.

I need to collect information about events that occur when someone tries to access a file, including cases when they only read Microsoft Word documents without making changes.

Is it possible to do this?

We are all familiar with the “Modified Date” field, available when viewing a list of files in Windows Explorer. But did you know that there is also an Access Date field? Each time you read a Windows file, this field theoretically indicates the current timestamp. You can verify this yourself (see below) by clicking on the column headings and turning on the access information field.



However, in practice, Windows computers are usually not configured to update this internal field when the file is opened for reading only, and not for editing. Microsoft claims that this reduces performance. But let's cast aside doubts.
To configure continuous updating of file access time in Windows, use the underestimated fsutil utility (administrator rights will be required) with the following parameters:

fsutil set behavior disablelastaccess 0

By setting up file access events in my test environment, I also enabled Windows to record read-only events.

As a result, I indicated in the above WQL code such a logical search criterion:

targetInstance.LastAccessed > '$($cur)'

It means that I am only interested in file events in which files are accessed after starting Register-WmiEvent. The $ cur variable, by the way, is assigned the current time value obtained from the Get-Date cmdlet.

File Access Analysis

We looked at the WQL language, now let's move on to the remaining Register-WmiEvent parameters.

SourceIdentifer allows you to specify the name of the event. Naming - people, tabby cats or terriers - is recommended to be used, as this allows you to call them if necessary.

And it is suitable for events! There are several cmdlets that require this identifier. For beginners: Unregister-Event is used to delete a given subscription to events, Get-Event allows you to view all events that have been queued, Remove-Event is used to delete current events in the queue, and finally, Wait-Event is used to explicitly wait synchronously . We will use some of these cmdlets in the final code.

I made out the main components of my script.

It remains to consider the Action parameter. Since Register-WmiEvent responds to events asynchronously, a code is required that processes the reaction to triggering events, and, let’s say, this is what the action consists in - a block of transmitted PowerShell code.

And this leads us to what I'm actually trying to achieve with my script, so I have to reveal my grandiose plans to conquer the whole world of analyzing user behavior with a few lines of PowerShell code.

Here is the plan. This PS script will track the intensity of file access events, compare it with a reference value, and decide whether this intensity falls into a range of uncharacteristic values ​​that could indicate a potential hack attempt. When this threshold is reached, an excellent dashboard is displayed with recent activity data.

In other words, I will have a threat tracking system with an alert that will note unusual behavior regarding text files in a given directory.

Will Powershell push other security solutions out of the market?

No, Varonis does not have to worry about this for several reasons.

First of all, event tracking in Windows cannot be called effective. In fact, Microsoft is warning that the inclusion of updates about the last access to the file through fsutil increases the load on the system. In addition, Register-WmiEvent accelerates the flywheel of internal events: I came across comments that state that cmdlets can slow down the system.

Secondly, I noticed that this monitoring is not carried out in real or near real time: there is a delay in receiving file events, which reaches 30 or more minutes. At least that was my experience running scripts on my AWS virtual machine. Perhaps the results will be better on your particular machine, but I do not think that Microsoft can promise anything about this.

Thirdly, no matter how I tried, I could not connect the file change event with the user of the application, which was the cause of the event. In other words, I know that a file event has occurred, but, sadly, it is not possible using Register-WMIEvent to find out who did it.

Therefore, I received a script that can track access to files, but without establishing an identity. Hmmm ... let's create a new security control category called file access analysis that collects data about my activities. Gartner, can you hear me?

Of course, analyzing user behavior is a much more effective way to identify threats, as the actions of specific users are interesting information. My less detailed analysis of file access, although useful, cannot pinpoint illegal behavior because it collects data about events from multiple users.

However, for small companies with a small number of registered accounts, file access analysis may be sufficient. For example, an administrator can use these scripts if he finds the behavior of a user who is too often interested in a directory with sensitive data to be suspicious. This code also has some more attractive features.

And even if my script does not completely do its job, an even more important argument is understanding the complexity of working with Windows events using PowerShell (or another language you use), which forces you to pay attention to enterprise-class solutions.

Now we are ready to look at the Powershell script block of my Register-WmiEvent cmdlet:

1.	$action = { 
2.	$Global:Count++ 
3.	$d=(Get-Date).DayofWeek
4.	$i= [math]::floor((Get-Date).Hour/8) 
5.	
6.	$Global:cnts[$i]++ 
7.	
8.	#event auditing!
9.	
10.	$rawtime = $EventArgs.NewEvent.TargetInstance.LastAccessed.Substring(0,12)
11.	$filename = $EventArgs.NewEvent.TargetInstance.Name
12.	$etime= [datetime]::ParseExact($rawtime,"yyyyMMddHHmm",$null)
13.	
14.	$msg="$($etime)): Access of file $($filename)"
15.	$msg|Out-File C:\Users\bob\Documents\events.log -Append
16.	
17.	
18.	$Global:evarray.Add(@($filename,$etime))
19.	if(!$Global:burst) {
20.	$Global:start=$etime
21.	$Global:burst=$true 
22.	}
23.	else { 
24.	if($Global:start.AddMinutes(15) -gt $etime ) { 
25.	$Global:Count++
26.	#File behavior analytics
27.	$sfactor=2*[math]::sqrt( $Global:baseline["$($d)"][$i])
28.	write-host "sfactor: $($sfactor))"
29.	if ($Global:Count -gt $Global:baseline["$($d)"][$i] + 2*$sfactor) {
30.	
31.	
32.	"$($etime): Burst of $($Global:Count) accesses"| Out-File C:\Users\bob\Documents\events.log -Append 
33.	$Global:Count=0
34.	$Global:burst =$false
35.	New-Event -SourceIdentifier Bursts -MessageData "We're in Trouble" -EventArguments $Global:evarray
36.	$Global:evarray= [System.Collections.ArrayList] @();
37.	}
38.	}
39.	else { $Global:burst =$false; $Global:Count=0; $Global:evarray= [System.Collections.ArrayList] @();}
40.	} 
41.	} 
 

Yes, I check the login using the Out-File cmdlet to create timestamped entries for each access case. And comparing the number of events with the reference value in the $ Global: baseline array, I detect file access spikes every 15 minutes.
Here I fantasized a little and set up a mythical average value for the number of events in the reference value for each day of the week, dividing each day into three eight-hour periods. When the peak activity for a given period falls at the far end of the tail of the normal distribution curve, it can be considered that a threat has been detected.

File Access Analysis Dashboard

Having received data on the peak increase in the number of events in $ Global: evarray (opening files with timestamps), I decided that it would be a good idea to display this data in the form of a stylish information panel. But instead of adding this code to the script block, I “queue” this data in a separate event, which can be processed by individual applications.

What?!

Let me explain. This is where the New-Event cmdlet comes into play at the end of the script block above. It just allows me to send signals to another application or script asynchronously, without binding this code to the script block so that I can then process the next file access event.

I will present the full code of my PowerShell script to analyze file access in the next note. Now I just say that I configured the Wait-Event cmdlet, the sole purpose of which is to select these bursts of events and then send them to the output of a beautiful table using Out-GridView.

Here is the final result, which will be displayed in the admin console:



A great solution, given that the entire "platform" for analyzing file access is implemented in 60 lines of PS code.

We examined a lot of material, enough for today.

We’ll talk more about the file access analysis script next time, then we’ll move on to discuss the excellent PowerShell content classification features.

Also popular now: