Skip to main content
Splunk Lantern

File write spikes

This search looks for a sharp increase in the number of files written to a particular host, a common signature of ransomware attacks.

Data required 

Endpoint data

Procedure

  1. Content developed by the Splunk Security Research team requires the use of consistent, normalized data provided by the Common Information Model (CIM). For information on installing and using the CIM, see the Common Information Model documentation. To run this search, your deployment needs to be populating the Endpoint Filesystem data model node. This is typically populated via endpoint detection and response products, such as Carbon Black or endpoint data sources such as Sysmon. The data used for this search is typically generated via logs that report reads and writes to the file system.
  2. Run the following search. You can optimize it by specifying an index and adjusting the time range.
| tstats allow_old_summaries=true count FROM datamodel=Endpoint.Filesystem WHERE "Filesystem.action"=created BY _time span=1h, "Filesystem.dest" 
| rename "Filesystem.*" AS "*" 
| eventstats max(_time) AS maxtime 
| stats count AS num_data_samples max(eval(if(_time >= relative_time(maxtime, "-1d@d"), count, null))) AS "count" avg(eval(if(_time<relative_time(maxtime, "-1d@d"), count,null))) AS avg stdev(eval(if(_time<relative_time(maxtime, "-1d@d"), count, null))) AS stdev BY "dest" 
| eval upperBound=(avg + (stdev * 4)), isOutlier=if(((count > upperBound) AND (num_data_samples >= 20)),1,0)
| search isOutlier=1

Search explanation

The table provides an explanation of what each part of this search achieves. You can adjust this query based on the specifics of your environment.

Splunk Search Explanation
| tstats allow_old_summaries=true count FROM datamodel=Endpoint.Filesystem WHERE "Filesystem.action"=created BY _time span=1h, "Filesystem.dest"  Query the Endpoint.Filesystem data model object to search for file writes. Sort by a time span of an hour, then the data model field Filesystem.dest.
| rename "Filesystem.*" AS "*"  Rename data model fields for better readability.
| eventstats max(_time) AS maxtime  Return the most recent instance of each event in the results.
| stats count AS num_data_samples max(eval(if(_time >= relative_time(maxtime, "-1d@d"), count, null))) AS "count" avg(eval(if(_time<relative_time(maxtime, "-1d@d"), count,null))) AS avg stdev(eval(if(_time<relative_time(maxtime, "-1d@d"), count, null))) AS stdev BY "dest"  Calculate the mean, standard deviation, and most recent value. 

| eval upperBound=(avg + (stdev * 4)), isOutlier=if(((count > upperBound) AND (num_data_samples >= 20)),1,0)
 

Calculate an upper bound for your baseline by adding the standard deviation multiplied by 4 to the average. Then, create a new column called isOutlier. If the count of file writes is larger than the upper bound, return a value of 1 in the isOutlier column. Otherwise, return a value of 0.

Make sure your search time range is set appropriately or all new file writes might seem larger than the upper bound.

| search isOutlier=1 Return only results where the isOutlier value is 1, which indicates file writes larger than the upper bound.

Next steps

False positives from this search may occur if you install any new applications on your hosts or copy a large number of files because these actions cause a large increase of file modifications.

If you receive clear positive results from this search, start your incident response process for dealing with a ransomware infection. You should check for recent backups for the systems affected by the infection.

Finally, you might be interested in other processes associated with the Detecting a ransomware attack use case.