Проста система аудиту видалення файлів і папок для Windows Server

Будь-адміністратор Windows стикався з ситуацією, коли розлючені користувачі хочуть дізнатися, хто саме вилучив мега важливий файл з річним звітом в загальнодоступному місці на файловому сервері. Цю інформацію можна отримати тільки за умови ведення аудиту видалення файлів і папок на файловому сервері, інакше залишиться тільки відновити віддалений файл з резервної копії (а ви їх вже робите?) І розвести руками.

Але, навіть при включеному аудиті видалення файлів, знайти щось в логах буває проблематично. По-перше, знайти потрібний запис серед тисячі подій досить складно (в Windows відсутні осудні кошти пошуку цікавить події з можливістю гнучкої фільтрації), а по-друге, якщо файл був видалений давно, ця подія може просто бути відсутнім в журналі, тому що було перезатерто новішими.

У цій статті ми покажемо приклад організації на вбудованих засобах Windows системи аудиту видалення файлів і папок в загальному мережевому каталозі (Файловому сервері) із записом подій в окрему базу даних на MySQL.

Завдяки наявності БД з інформацією про всі віддалених файлах адміністратор зможе дати відповіді на питання:

  • Хто і коли видалив файл
  • З якого додатка видалений файл
  • На який момент часу потрібно відновлювати бекап

В першу чергу на файловому сервері Windows потрібно включити аудит подій, що забезпечує запис інформації про видалення файлів в журнал системи. Цю процедуру ми вже розглядали в статті Аудит доступу до файлів і папок в Windows.

Аудит може бути включений через загальну політику Audit Object Access в розділі політик Security Settings -> Local Policy -> Audit Policy

Або (переважно) через розширені політики аудиту в GPO: Security Settings -> Advanced Audit Policy Configuration -> Object Access -> Audit File System.

Порада. Ведення аудиту накладає додаткові витрати на ресурси системи. Потрібно з обережністю застосовувати його, особливо для високонавантажених файлових серверів.

У властивостях загальної мережевої папки (Security -> Advanced -> Auditing), видалення файлів в якому ми хочемо відстежувати, для групи Everyone включимо аудит подій видалення папок і файлів (Delete subfolders and files).

Порада. Аудит видалення файлів в конкретній папці можна включити і через PowerShell:

$ Path = "D: \ 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

При успішному видаленні файлу в журналі безпеки системи з'являється подія Event ID 4663 від джерела Microsoft Windows security auditing. В описі події є інформація про ім'я віддаленого файлу, облікового запису з-під якої було виконано видалення і імені процесу.

Отже, що цікавлять нас події пишуться в журнал, настала пора створити на сервері MySQL таблицю, що складається з наступних полів:

  • ім'я сервера
  • Ім'я віддаленого файлу
  • час видалення
  • Ім'я користувача, вилучив файл

MySQL запит на створення такої таблиці буде виглядати так:

CREATE TABLE track_del (id INT NOT NULL AUTO_INCREMENT, server VARCHAR (100), file_name VARCHAR (255), dt_time DATETIME, user_name VARCHAR (100), PRIMARY KEY (ID));

Примітка. Особливості роботи з MySQL базою ми докладно розглядали в статті Працюємо з базою даних MySQL з PowerShell

Скрипт збору інформації з журналу подій. Ми фільтруємо журнал за подією з ID 4663 за поточний день

$ 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

Наступний скрипт запише отримані дані в БД MySQL на віддаленому сервері:

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.7.7.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 track_del (server, file_name, dt_time, user_name) VALUES ( '$ Computer', '$ File', '$ Time', '$ User')"
$ Sql.ExecuteNonQuery ()


$ Reader.Close ()
$ Connection.Close ()

Тепер, щоб дізнатися, хто видалив файл "document1 - Copy.DOC", Досить в консолі PowerShell виконати наступний скрипт.

$ DeletedFile = "% document1 - Copy.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.7.7.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 track_del 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 ()

В консолі отримуємо ім'я користувача і час видалення файлу.

Примітка. Оскільки була виявлена ​​проблема, чир символ «\" не записується в БД, ми замінили його на «|». Відповідно якщо потрібно вказати вивести повний шлях до файлу, при вибірці з бази можна виконати зворотну заміну $ DataSet.file_name.Replace ( '|', '\'). Спасибі Alex Kornev за зауваження!

Скрипт скидання даних з журналу в БД можна виконувати один раз в кінці дня за планувальником або повісити на подію видалення (On Event), що більш ресурсоємних. Все залежить від вимоги до системи.

Порада. Потрібно переконатися, що журнал безпеки має достатній розмір, щоб в нього містилися всі події за день. Інакше доведеться запускати завдання скидання даних з журналу в базу частіше, ніж 1 раз в день, або взагалі по триггеру. Для робочих станція Maximum Log Size як правило варто задати не менше 64 Мб, на северах - 262 Мб. Опцію перезапису залишаємо включеної (Overwrite events as needed).

При бажанні за аналогією можна реагувати просту веб сторінку на php для отримання інформації про винуватців видалення файлів в більш зручному вигляді. Завдання вирішується силами будь-якого php програміста за 1-2 години.

важлива рада. При наявності в журналі інформації про видалення файлу користувачем не поспішайте однозначно інтерпретувати його як навмисне або навіть зловмисне. Багато програм (особливо цим грішать програми пакета MS Office), при збереженні даних спочатку створюють тимчасовий файл, зберігають документ в нього, а стару версію файлу видаляють. У цьому випадку має сенс додаткової записи в БД імені процесу, яким було виконано видалення файлу (поле ProcessName події), і вести аналіз видалення файлів з урахуванням цього факту. Або зовсім радикально відсівати події від таких сміттєвих процесів, наприклад, winword.exe, excel.exe тощо.

Отже, ми запропонували ідею і якийсь загальний каркас системи аудиту і зберігання інформації про віддалених файлах в мережевих кулях, при бажанні її з легкістю можна буде модифікувати під ваші потреби.