You can use file system object access event auditing to identify a specific user who created, deleted, or modified a specific file. In this article, we’ll show you how to configure event auditing for files on a shared network folder on Windows Server 2016. After configuring auditing, you can use the information from the Event Viewer to find the user who deleted specific file on the file server.
How to Enable File and Folder Access Auditing Policy on Windows?
By default, File System Object Access audit is not enabled on Windows Server. You can enable and configure audit settings using Group Policy. If you need to enable audit policies on multiple servers or computers, you can use domain GPOs (configurable using the gpmc.msc
mmc console). If you only want to configure auditing on one server, you can use Local Group Policy Editor.
- Open the Local Group Policy Editor console –
gpedit.msc
; - Go to the GPO section with advanced audit policies: Windows Settings -> Security Settings -> Advanced Audit Policy Configuration -> Object Access;
- Open the Audit File System policy and specify that you want to log only successful access events to file system objects (Configure the following audit events -> Success);You can also enable auditing of local objects access using the Audit Object Access policy under Windows Settings -> Security Settings -> Local Policy -> Audit Policy. However, using the File System Audit policy is preferable because it only tracks NTFS access events.
- Save the changes and update your local Group Policy settings using the command:
gpupdate /force
.
Configuring File Deleted Audit Settings on a Shared Folder
Now you need to configure auditing in the properties of the share network folder you want to track access to. Run File Explorer and open the folder properties. Go to the Security tab. Click the Advanced button -> go to the Auditing tab.
If the message “You must be an administrator or have been given the appropriate privileges to view the audit properties of this object” appears, click the Continue button.
Then click the Add button to specify the user or group for which you want to capture audit events. If you want to track access events for all users, specify the Everyone group.
Then you need to specify which permissions used to access the object should be logged. To save only file deletion events in the Event Log, click the Show advanced permissions button. In the event list, leave auditing only for folder and file deletion events – Delete and Delete subfolders and files.
$Path = "E:\Public"
$AuditChangesRules = New-Object System.Security.AccessControl.FileSystemAuditRule('Everyone', 'Delete,DeleteSubdirectoriesAndFiles', 'none', 'none', 'Success')
$Acl = Get-Acl -Path $Path
$Acl.AddAuditRule($AuditChangesRules)
Set-Acl -Path $Path -AclObject $Acl
Now, if the user deletes any file or folder in the shared network folder, the File System -> Audit Success file delete event appears in the Security log with Event ID 4663 from the Microsoft Windows security auditing source.
Open the Event Viewer mmc console (eventvwr.msc
), expand the Windows Logs -> Security section. Enable event log filter by the EventID 4663.
Open any of the remaining events in the Event Viewer. As you can see, it contains information about the name of the deleted file, the account of the user who deleted the file and the process name.
An attempt was made to access an object. Subject:Security ID: CORP\jsmith Account Name: jsmith Account Domain: CORP Logon ID: 0x32B12627 Object:Object Server: Security Object Type: File Object Name: E:\Distr\Backup.rar Handle ID: 0x7bc4 Resource Attributes: S:AI Process Information: Process ID: 0x4 Process Name: Access Request Information: Accesses: DELETE Access Mask: 0x10000
After enabling file access auditing policy, you can find in the Security log :
- Who deleted the file from the shared network folder and when it happened;
- What application (process) was used to delete the file;
- What is the date of the backup to be restored.
How to Write File Deletion Events to SQL Database (MySQL/MSSQL)?
However, even if the audit of the deleted files is enabled, it can be troublesome to find something in the logs. Firstly, it is quite hard to find a specific entry among thousands of events (in Windows there are no convenient tool to search an event with a flexible filter). Secondly, if a file was deleted a long time ago, this event may be absent in the logs, since it was overwritten by new events.
You can save all file delete events to the SQL database. You can use Microsoft SQL Server, Elasticsearch, or MySQL/MariaDB databases to store your events.
In this example, we’ll show you how to log audit events to a separate database table on a MySQL. I will use the following table format:
- Server name;
- Name of the deleted file;
- Date and time;
- Name of the user who has deleted the file.
The MySQL query to create this table looks like that:
CREATE TABLE deleted_items (id INT NOT NULL AUTO_INCREMENT, server VARCHAR(100), file_name VARCHAR(255), dt_time DATETIME, user_name VARCHAR(100), PRIMARY KEY (ID));
If you want to use Microsoft SQL Server database, check out the article “How to run a MSSQL Server Query from PowerShell?”
To get events with EventID 4663 from the Security log for the current day, you can use the following PowerShell script:
$today = get-date -DisplayHint date -UFormat %Y-%m-%d
Get-WinEvent -FilterHashTable @{LogName="Security";starttime="$today";id=4663} | Foreach {
$event = [xml]$_.ToXml()
if($event)
{
$Time = Get-Date $_.TimeCreated -UFormat "%Y-%m-%d %H:%M:%S"
$File = $event.Event.EventData.Data[6]."#text"
$User = $event.Event.EventData.Data[1]."#text"
$Computer = $event.Event.System.computer
}
}
The next PowerShell script will write the data you get to the MySQL database on a remote server (with the IP address 10.1.1.13):
Add-Type –Path ‘C:\Program Files (x86)\MySQL\MySQL Connector Net 6.9.8\Assemblies\v4.5\MySql.Data.dll'
$Connection = [MySql.Data.MySqlClient.MySqlConnection]@{ConnectionString='server=10.1.1.13;uid=posh;pwd=P@ssw0rd;database=aduser'}
$Connection.Open()
$sql = New-Object MySql.Data.MySqlClient.MySqlCommand
$sql.Connection = $Connection
$today = get-date -DisplayHint date -UFormat %Y-%m-%d
Get-WinEvent -FilterHashTable @{LogName="Security";starttime="$today";id=4663} | Foreach {
$event = [xml]$_.ToXml()
if($event)
{
$Time = Get-Date $_.TimeCreated -UFormat "%Y-%m-%d %H:%M:%S"
$File = $event.Event.EventData.Data[6]."#text"
$File = $File.Replace(‘\’,’|’)
$User = $event.Event.EventData.Data[1]."#text"
$Computer = $event.Event.System.computer
$sql.CommandText = "INSERT INTO deleted_items (server,file_name,dt_time,user_name ) VALUES ('$Computer','$File','$Time','$User')"
$sql.ExecuteNonQuery()
}
}
$Reader.Close()
$Connection.Close()
Now, to find out who has deleted the file “AnnualReport.DOC“, it is enough to run the following script in the PowerShell console:
$DeletedFile = "%AnnualReport.DOC%"
Set-ExecutionPolicy RemoteSigned
Add-Type –Path ‘C:\Program Files (x86)\MySQL\MySQL Connector Net 6.9.8\Assemblies\v4.5\MySql.Data.dll'
$Connection = [MySql.Data.MySqlClient.MySqlConnection]@{ConnectionString='server=10.1.1.13;uid=posh;pwd=P@ssw0rd;database=aduser'}
$Connection.Open()
$MYSQLCommand = New-Object MySql.Data.MySqlClient.MySqlCommand
$MYSQLDataAdapter = New-Object MySql.Data.MySqlClient.MySqlDataAdapter
$MYSQLDataSet = New-Object System.Data.DataSet
$MYSQLCommand.Connection=$Connection
$MYSQLCommand.CommandText="SELECT user_name,dt_time from deleted_items where file_name LIKE '$DeletedFile'"
$MYSQLDataAdapter.SelectCommand=$MYSQLCommand
$NumberOfDataSets=$MYSQLDataAdapter.Fill($MYSQLDataSet, "data")
foreach($DataSet in $MYSQLDataSet.tables[0])
{
write-host "User:" $DataSet.user_name "at:" $DataSet.dt_time
}
$Connection.Close()
You can now see the username and the time the file was deleted in the PS console.
\
” is not written to the database, we have replaced it for “|
”. So if you have to display the full path to the file, you can perform a reverse replacement when selecting from the database:$DataSet.file_name.Replace(‘|’,’\’).
The script of writing the information from the Event log to the database can be run at the end of the day using Task Scheduler or attached to the file deletion EventID (On Event), which is more resource-consuming. It depends on the requirements to the system.
If necessary, you can create a simple PHP web page to get the information about the users who have deleted files in a more convenient form.
Logging File Delete Audit Events to a Text File
If you don’t want to use a separate database server, you can save file deletion audit events to a plain text log file. Use this PowerShell script to save you output to a text file:
$Outfile = "C:\Logs\Deleted-file-history-log.txt"
$today = get-date -DisplayHint date -UFormat %Y-%m-%d
Get-WinEvent -FilterHashTable @{LogName="Security";starttime="$today";id=4663} | Foreach {
$event = [xml]$_.ToXml()
if($event)
{
$Time = Get-Date $_.TimeCreated -UFormat "%Y-%m-%d %H:%M:%S"
$File = $event.Event.EventData.Data[6]."#text"
$User = $event.Event.EventData.Data[1]."#text"
$strLog = $Computer + " " + $File + " " + $Time + " " + $User
$strLog | out-file $Outfile –append
}
}
So, we have suggested an idea and the general model of the system to audit and store the information about the deleted files in the shared network folders. If needed, it can easily be modified to meet your requirements.
4 comments
Well summarized !
Thank you for sharing this interesting post.
Here is one more informative article which provides step-wise instructions to enable security auditing on important files and track every critical changes/access or file deletion into real time – https://community.spiceworks.com/how_to/123983-track-file-deletions-and-permission-changes-on-windows-file-server
Great stuff. Just what I was looking for. Thank you.
This produces a very, very large number of logs. For example, all temporarily created files that are deleted when a program is ended or when files are closed are also recorded. That may be correct in principle, but it goes far beyond my requirements.
The question that now arises is it possible to reduce the logging to the essentials in some way or does the effort involved in developing such a concept far outweigh the benefits?
Drag the logs into any data grave (Elastic Stack and the Log Ingestor are available for free), then it doesn’t really matter how many there are…