Windows 2008 кто удалил файл


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

Любой администратор Windows сталкивался с ситуацией, когда разъяренные пользователи хотят узнать, кто именно удалил мега важный файл с годовым отчетом в общей папке на файловом сервере. Эту информацию можно получить только при условии ведения аудита удаления файлов и папок на файловом сервере, иначе останется только восстановить удаленный файл из резервной копии (а вы их уже делаете?) и развести руками.

Но, даже при включенном аудите удаления файлов, найти что-то в логах бывает проблематично. Во-первых, найти нужную запись среди тысячи событий довольно сложно (в Windows отсутствуют вменяемые средства поиска интересующего события с возможностью гибкой фильтрации), а во-вторых, если файл был удален давно, это событие может просто отсутствовать в журнале, т.к. было перезатерто более новыми.

В этой статье мы покажем пример организации на встроенных средствах Windows системы аудита удаления файлов и папок в общем сетевом каталоге (файловом сервере) с записью событий в отдельную базу данных на MySQL.

Благодаря наличию БД с информацией обо всех удаленных файлах администратор сможет дать ответы на вопросы:

  • Кто и когда удалил файл
  • Из какого приложения удален файл
  • На какой момент времени нужно восстанавливать бэкап

В первую очередь на файловом сервере Windows нужно включить аудит событий, обеспечивающий запись информации об удалении файлов в журнал системы. Эту процедуру мы уже рассматривали в статье Аудит доступа к файлам и папкам в Windows .

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

Совет. Ведения аудита накладывает дополнительные расходы на ресурсы системы. Нужно с осторожностью применять его, особенно для высоконагруженных файловых серверов.

В свойствах общей сетевой папки (Security -> Advanced -> Auditing), удаление файлов в котором мы хотим отслеживать, для группы Everyone включим аудит событий удаления папок и файлов (Deletesubfoldersandfiles ).

Совет. Аудит удаления файлов в конкретной папке можно включить и через 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 @ | 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]@
$Connection.Open()
$sql = New-Object MySql.Data.MySqlClient.MySqlCommand
$sql.Connection = $Connection
$today = get-date -DisplayHint date -UFormat %Y-%m-%d
Get-WinEvent -FilterHashTable @ | 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]@
$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 и пр.

Итак, мы предложили идею и некий общий каркас системы аудита и хранения информации об удаленных файлах в сетевых шарах, при желании ее с лёгкостью можно будет модифицировать под ваши нужды.

  • Дисковые квоты пользователей на файловой системе NTFS
  • Блокируем сетевой доступ локальным учетным записям
  • SFTP (SSH FTP) на Windows Server 2012 R2
  • FTP over SSL (FTPS) в Windows Server 2012 R2
  • Запуск оснасток TSADMIN.msc и TSCONFIG.msc в Windows Server 2012 R2

Понравилась статья? Скажи спасибо и расскажи друзьям!

Подразумевал, что раз в сутки планировщик (допустим в 23:58) запускает powershell скрипт, который получает все события за прошедшие сутки и пишет из в базу.
Т.е. в создаем задание планировщика, которое запускет программу C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe с аргументом в виде имени файла со вторым скриптом C:\myscripts\WriteDelEventDB.PS1

«Скрипт сбора информации из журнала событий» — это просто пример работы с журналом событий, фильтрации и получения значений определенных полей. Он используется внутри следующего скрипта.

Alex Kornev | 04.05.2016

Что-то пошло не так. Или — что я сделал не так?
На первой же строке скрипта вылезает матершина:
(все делается под одним из Domain Admin аккаунтов)

Get-WinEvent. Could not retrieve information about the Security log. Error: Attempted to perform
an unauthorized operation..
At line:1 char:1
+ Get-WinEvent -FilterHashTable @
+


+ CategoryInfo. NotSpecified: (:) [Get-WinEvent], Exception
+ FullyQualifiedErrorId. LogInfoUnavailable,Microsoft.PowerShell.Commands.GetWinEventCommand

Get-WinEvent. There is not an event log on the localhost computer that matches «Security».
At line:1 char:1
+ Get-WinEvent -FilterHashTable @
+


+ CategoryInfo. ObjectNotFound: (Security:String) [Get-WinEvent], Exception
+ FullyQualifiedErrorId. NoMatchingLogsFound,Microsoft.PowerShell.Commands.GetWinEventCommand


+ CategoryInfo. NotSpecified: (:) [Get-WinEvent], EventLogException
+ FullyQualifiedErrorId. System.Diagnostics.Eventing.Reader.EventLogException,Microsoft.Power
Shell.Commands.GetWinEventCommand

Alex Kornev | 04.05.2016

Пардону просим
Run As Administrator забыл сделать Ж-)

Здравствуйте, отличная статья. Решал подобную задачу для сбора статистики с KMS сервера, но использовал связку PS и MSSQL Express. Через год работы наткнулся на проблему, что превысил лимит базы данных в 10Гб, в итоге сделал ротацию данных в БД Наверное в вашем случае тоже было бы неплохо предусмотреть удаление старых данных?

Могу поделиться наработками, если интересно.

Приветствую,
Насчет удаления старых данных пока не думал. Сложно оценить насколько будет большой база и за какой период нужна информация. Здесь больше идея рассматривается, какие-то выводы и усовершенствования можно делать только после опыта более продолжительного использования.

А инфой конечно, делитесь! Можно оформить отдельной статьей, думаю тема сбора и хранения статистики использования KMS сервера будет многим интересна.
Мой емайл есть на странице _http://winitpro.ru/index.php/o-bloge/

Alex Kornev | 05.05.2016

Странно как-то себя MySQL повел ….
Поставил, для удобства, Navicat Premium Enterprise 11.2.4
(http://nnm.me/blogs/MANS0RY/premiumsoft-navicat-premium-11-2-4-enterprise/ )
и получается как-то странно
если делать, этим Navicat, Export всей таблицы из базы, то в поле file_name попадает имя файла целиком (правда отделенное пробелом почему-то от всего остального)

«id» «server» «file_name» «dt_time» «user_name»
«1440» «AUDITTEST» «DeviceHarddiskVolume2TEST 0000.txt» «5.5.2016 12:12:24″ «name»

а когда делаешь select … то имя файла обрезается до полного пути до него
SELECT track_del.file_name,track_del.dt_time,track_del.user_name FROM track_del
а на выходе
file_name dt_time user_name
DeviceHarddiskVolume2TEST 2016-05-05 12:12:24 name

Если присмотреться, то в поле file_name попадается пробел. И, походу, по нему и режется. А пока оно так себя ведет, дальше ничего не работает. То есть невозможно сделать LIKE по значению, которое не показывается

Alex Kornev | 05.05.2016

Починил.
В скрипте, который заполняет таблицу в БД, вставил строку, которая меняет в имени файла, получаемого из Security Even Log’a все ‘\’ на ‘|’ Вот здесь:

$File = $event.Event.EventData.Data[6].»#text»
$File = $File.Replace(‘\’,’|’)

После этого имя файла перестало «теряться» и попадает в БД как надо

И потом, слегка «доработал» скрипт, который выдает результат. Мне плказалось так и красивее, и правильнее. Добавлен вывод имени файла с полным путем. с обратной заменой ‘|’ на ‘\’

foreach($DataSet in $MYSQLDataSet.tables[0])
<
write-host «File:» $DataSet.file_name.Replace(‘|’,’\’) — «User:» DataSet.user_name «at:» $DataSet.dt_time
>

Alex Kornev | 06.05.2016

А ведь это был _очень_неприятный баг MySQL, на самом деле

Файл, на котором я «тренировался», я назвал 00000.txt (5 нулей) и, в итоге, в базу из Event Log’a попадало вот что
DeviceHarddiskVolume2TEST 0000.txt
То есть при выполнении INSERT MySQL «выгрызал» все символы ‘\’ и, более того делал из подстроки 0000.txt такое вот "[SPACE]0000.txt" типа пытался «интерпретировать по своему»?
А после того как я, предварительно, заменял все ‘\’ на ‘|’ — все проходило как надо

Дмитрий, думаю не лишним будет или упомянуть об этой «особенности» или поправить скрипт, который заносит имя файла в таблицу БД.

Видимо проблема в сочетании "\"+"0". которое как-то интерпретируется mysql, то ли пустая строка, то ли что-то в этом роде.
Согласен, в скрипте лучше всего заменить ‘\’ на ‘|’, а при выборке делать обратную замену.
Сейчас внесу изменения в статью. Спасибо!



windows 2008 кто удалил файл:Организуем систему ведения базы данных с информацией о том, кто и когда удалил файлы в общей папке на файловом сервере Windows

windows 2008 кто удалил файл