С помощью аудита событий доступа к объектам файловой системы можно определить конкретного пользователя, который создал, удалил или изменил определенный файл. В этой статье мы покажем, как настроить аудит событий удаления объектов в общей сетевой папке на файловом сервере Windows Server 2025/2022/2019. После настройки аудита, вы можете с помощью информации в журнале событий Event Viewer найти пользователя, который удалил файл или папку на файловом сервере.
Включаем политику аудита доступа к файлам и папкам в Windows
По умолчанию в Windows Server не включен аудит событий доступа к объектам на файловой системе. Если аудит не был включен на момент удаления файла, вы не сможете ретроспективно определить пользователя, удалившего файл.
Включить и настроить аудит событий доступа к файлам и папкам можно с помощью групповых политики. Настроить политику аудита можно с помощью доменной GPO (настраивается с помощью консоли управления gpmc.msc), или из локального редактора локальной политики (
gpedit.msc
) на конкретном хосте:
- Перейдите в раздел GPO с расширенными политиками аудита Windows Settings -> Security Settings -> Advanced Audit Policy Configuration -> Object Access;
- Включите политику Audit File System и укажите, что нужно логировать только успешные события доступа к объектам файловой системы (Configure the following audit events -> Success

- Сохраните изменения и обновите настройки групповых политик на компьютере с помощью команды
gpupdate /force.
Настройка аудита событий удаления файлов из конкретной папки
Теперь нужно настроить аудит в свойствах общей сетевой папки, доступ к которой вы хотите отслеживать. Запустите проводник и откройте свойства общей папки. Перейдите на вкладку Security. Нажмите кнопку Advanced -> вкладка Auditing.
Если появится сообщение You must be an administrator or have been given the appropriate privileges to view the audit properties of this object, нажмите кнопку Continue.

Нажмите кнопку Add и укажите имя пользователя или группы, для которых нужно записывать события аудита (если нужно отслеживать события для всех пользователей, укажите группу Everyone).
Чтобы в Event Viewer писались только события удаления файлов, нажмите кнопку Show advanced permissions. В списке событий оставьте аудит только для событий удаления папок и файлов — Delete и Delete subfolders and files.

$Path = "D:\Public"
$AuditChangesRules = New-Object System.Security.AccessControl.FileSystemAuditRule('Everyone', 'Delete,DeleteSubdirectoriesAndFiles', 'ContainerInherit,ObjectInherit', 'None', 'Success')
$Acl = Get-Acl -Path $Path
$Acl.AddAuditRule($AuditChangesRules)
Set-Acl -Path $Path -AclObject $Acl
Теперь, если пользователь удаляет файл в отслеживаемой сетевой папке, в журнале Event Viewer -> Security файлового сервера будут появляться события от источника Microsoft Windows security auditing.
Откройте mmc консоль Event Viewer (
eventvwr.msc
), разверните секцию Windows Logs -> Security. Включите фильтр событий по EventID 4663, 4659:
- 4663 – событие удаления из локальной папки
- 4659 – событие удаления из сетевой папки (по сети через UNC путь или через смонтированный сетевой диск) или локальное удаление мимо корзины (
SHIFT+DEL)
В описании события будет указан пользователь, удаливший файл (Subject: Account Name) и имя удаленного файла (Object Name). Access Mask 0x10000 и 0x10080 указывают, что файл был удален.

A handle to an object was requested with intent to delete.
Subject:
Security ID: WINITPRO\aaivanov2
Account Name: aaivanov2
Account Domain: WINITPRO
Logon ID: 0xD9F590
Object:
Object Server: Security
Object Type: File
Object Name: C:\Docs\report2025.pdf
Handle ID: 0x0
Process Information:
Process ID: 0x4
Access Request Information:
Transaction ID: {00000000-0000-0000-0000-000000000000}
Accesses: DELETE
ReadAttributes
Access Mask: 0x10080
Privileges Used for Access Check:
После настройки аудита, события в журнале Security позволят вам определить:
- Кто и когда удалил файл в сетевой папке;
- Из какого приложения удален файл;
- На какой момент времени нужно восстанавливать бэкап данного каталога.
Если после включения аудита удаления файлов в сетевой папке, вы видите в журнале много событий, найти что-то в логах бывает проблематично. Во-первых, найти нужную запись среди тысячи событий довольно сложно (в Windows отсутствуют вменяемые средства поиска интересующего события с возможностью гибкой фильтрации), а во-вторых, если файл был удален давно, это событие может просто отсутствовать в журнале, т.к. было перезатерто более новыми.
В этом случае вы можете записывать события удаления файлов во внешнее хранилище. Например:
- Оптимально отправлять события в специализированный лог коллектор, например GrayLog или Elasticsearch (в статье на сайте есть пример сбора событий Windows в GrayLog)
- Текстовый файл
- Базу данных
Запись информации о событиях удаления файлов в текстовый файл
В самом простом случае можно просто выгружать события удаления файлов в текстовый файл на сервере. Следующий PowerShell скрипт выберет все события с EventID 4663 и 4659 за сегодняшний день из журнала Security, извлечет из них имя удаленного файла/папки и имя пользователя, который удалили его, и сохранит результат в текстовый лог файл:
$outputFile = "C:\ps\delete-file-log.txt"
$auditfolder= "C:\Docs\*"
$eventIds = 4663, 4659
$computer = $env:COMPUTERNAME
$startTime = [datetime]::Today
Get-WinEvent -FilterHashtable @{LogName='Security'; ID=$eventIds; StartTime=$startTime} | ForEach-Object {
$xml = [xml]$_.ToXml()
$user = $xml.Event.EventData.Data | Where-Object { $_.Name -eq 'SubjectUserName' } | Select-Object -ExpandProperty '#text'
$file = $xml.Event.EventData.Data | Where-Object { $_.Name -eq 'ObjectName' } | Select-Object -ExpandProperty '#text'
if ($file -and $file -like $auditfolder) {
"$computer`t$($_.TimeCreated)`t$user`t$file" | Add-Content -Path $outputFile
}
}

Запись событий удаления файлов в SQL базу (MySQL/MSSQL)
Другой вариант – отправлять события удаления файлов из папки во внешнею SQL базу данных. Для хранения событий можно использовать Microsoft SQL Server, Elasticsearch, PostgreSQL, MySQL/MariaDB или любую другую БД.
В этом примере мы покажем, как записывать события аудита в отдельную таблицу БД на сервере MariaDB. Формат таблицы:
- Имя сервера;
- Имя удаленного файла
- Время удаления;
- Имя пользователя, удалившего файл.
SQL запрос на создание такой таблицы в MariDB будет выглядеть так:
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));
Выше рассмотрен пример PowerShell скрипта для получения событий удаления файлов (4663 и 4659) из журнала Security. Теперь вместо текстового файла будет отправлять данные в таблицу на MariaDB сервере.
Для подключения к базе данных будем использовать PowerShell модуль SimplySql. Его нужно установить из PowerShell галереи (или установить PowerShell модуль вручную),
Install-Module -Name SimplySql
Для подключения к базе данных MariaDB на удаленном сервере добавим следующий код:
import-module SimplySql
$dbhost="192.168.158.179"
$dbname="aduser"
$dbuser="posh"
$dbpass="P@ssw0rd"
$pwSecure = ConvertTo-SecureString $dbpass -AsPlainText -Force
$creds = New-Object System.Management.Automation.PSCredential($dbuser, $pwSecure)
$sqlConnect = Open-MySqlConnection -ConnectionName MyDBCon -Server $dbhost -Database $dbname -Credential $creds -Port 3306 -Verbose
Далее идет код выборки событий и записи данных в таблицу:
$auditfolder= "C:\Docs\*"
$eventIds = 4663, 4659
$computer = $env:COMPUTERNAME
$startTime = [datetime]::Today
Get-WinEvent -FilterHashtable @{LogName='Security'; ID=$eventIds; StartTime=$startTime} | ForEach-Object {
$xml = [xml]$_.ToXml()
$user = $xml.Event.EventData.Data | Where-Object { $_.Name -eq 'SubjectUserName' } | Select-Object -ExpandProperty '#text'
$file = $xml.Event.EventData.Data | Where-Object { $_.Name -eq 'ObjectName' } | Select-Object -ExpandProperty '#text'
if ($file -and $file -like $auditfolder) {
$time = $_.TimeCreated.ToString('yyyy-MM-dd HH:mm:ss')
$fileEscaped = $file -replace '\\', '\\\\'
$query = "INSERT INTO track_del (server, file_name, dt_time, user_name) VALUES ('$computer', '$fileEscaped', '$time', '$user');"
Invoke-SqlQuery -ConnectionName MyDBCon -Query $query
}
}
Close-SqlConnection -ConnectionName MyDBCon
Теперь, чтобы найти кто удалил конкретный файл, можно выполнять поиск по базе данных MySQL. В этом примере мы ищем любые удаленные файлы, содержащие в имени report2026.
$fileSearch = "%report2026%"
$pwSecure = ConvertTo-SecureString $dbpass -AsPlainText -Force
$creds = New-Object System.Management.Automation.PSCredential($dbuser, $pwSecure)
$sqlConnect = Open-MySqlConnection -ConnectionName MyDBCon -Server $dbhost -Database $dbname -Credential $creds -Port 3306 -Verbose
$fileSearchEscaped = $fileSearch -replace '\\', '\\\\'
$query = @"
SELECT server, REPLACE(file_name, '\\\\', '\\') AS file_name, dt_time, user_name FROM track_del
WHERE file_name LIKE '%$fileSearchEscaped%'
ORDER BY dt_time DESC;
"@
$data = Invoke-SqlQuery -ConnectionName MyDBCon -Query $query
$data | Format-Table -AutoSize
Close-SqlConnection -ConnectionName MyDBCon
В результате в консоли PS появится имя пользователя и время удаления файла.

- Скрипт сохранения данных из журнала событий в БД можно выполнять один раз в конце дня по планировщику или повесить триггер на событие удаления (On Event), что более ресурсоемко. Все зависит от требования к системе.
- Убедитесь, что на файловом сервере задан достаточно большой максимальный размер для журнала безопасности, чтобы в него помещались все события за день. Иначе придется запускать задания сброса данных из журнала в базу чаще, чем 1 раз в день, или вообще по триггеру.
- После сохранения событий во внешнюю базу данных, если вам не нужны другие логи, этот журнал Event Viewer можно очистить.
Можно создать простую веб страницу на php для получения информации о событиях удаления файлов в более удобном виде.
Итак, мы предложили идею и некий общий каркас системы аудита и хранения информации об удаленных файлах в сетевых папках. Вы можете ее с лёгкостью модифицировать под ваши нужды.


Предполагается, видимо, что MySQL уже установлен и настроен?
100 лет уже не имел дела с «мускулом»…
Да, конечно. Причем он даже под Windows ставится несколькими кликами.
В общем-то код и всю технику можно легко адаптировать и под MSSql, но с точки зрения зрения легкости, отдаю предпочтению мусклу.
Прошелся по любимому сайту и нашел 🙂
https://winitpro.ru/index.php/2014/09/10/ustanovka-mysql-na-windows-server-2012-windows-8/
Извини если туплю, но из статьи НЕ очевтдно
куда засунуть и как запустить скрипт
«Скрипт сбора информации из журнала событий. Мы фильтруем журнал по событию с ID 4663 за текущий день»
а за ним все остальные
Подразумевал, что раз в сутки планировщик (допустим в 23:58) запускает powershell скрипт, который получает все события за прошедшие сутки и пишет из в базу.
Т.е. в создаем задание планировщика, которое запускет программу C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe с аргументом в виде имени файла со вторым скриптом C:\myscripts\WriteDelEventDB.PS1
«Скрипт сбора информации из журнала событий» — это просто пример работы с журналом событий, фильтрации и получения значений определенных полей. Он используется внутри следующего скрипта.
Что-то пошло не так. Или — что я сделал не так?
На первой же строке скрипта вылезает матершина:
(все делается под одним из Domain Admin аккаунтов)
PS C:\Users\admin> Get-WinEvent -FilterHashTable @{LogName=»Security»;starttime=»$today»;id=4663}
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 @{LogName=»Security»;starttime=»$today»;id=4663}
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ 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 @{LogName=»Security»;starttime=»$today»;id=4663}
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (Security:String) [Get-WinEvent], Exception
+ FullyQualifiedErrorId : NoMatchingLogsFound,Microsoft.PowerShell.Commands.GetWinEventCommand
Get-WinEvent : The parameter is incorrect
At line:1 char:1
+ Get-WinEvent -FilterHashTable @{LogName=»Security»;starttime=»$today»;id=4663}
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Get-WinEvent], EventLogException
+ FullyQualifiedErrorId : System.Diagnostics.Eventing.Reader.EventLogException,Microsoft.Power
Shell.Commands.GetWinEventCommand
Пардону просим
Run As Administrator забыл сделать Ж-)
Здравствуйте, отличная статья. Решал подобную задачу для сбора статистики с KMS сервера, но использовал связку PS и MSSQL Express. Через год работы наткнулся на проблему, что превысил лимит базы данных в 10Гб, в итоге сделал ротацию данных в БД Наверное в вашем случае тоже было бы неплохо предусмотреть удаление старых данных? Могу поделиться наработками, если интересно. 🙂
Приветствую,
Насчет удаления старых данных пока не думал. Сложно оценить насколько будет большой база и за какой период нужна информация. Здесь больше идея рассматривается, какие-то выводы и усовершенствования можно делать только после опыта более продолжительного использования.
А инфой конечно, делитесь! Можно оформить отдельной статьей, думаю тема сбора и хранения статистики использования KMS сервера будет многим интересна.
Мой емайл есть на странице https://winitpro.ru/index.php/o-bloge/
Странно как-то себя MySQL повел ….
Поставил, для удобства, Navicat Premium Enterprise 11.2.4
)
и получается как-то странно
если делать, этим 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 по значению, которое не показывается
Починил.
В скрипте, который заполняет таблицу в БД, вставил строку, которая меняет в имени файла, получаемого из 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
}
А ведь это был _очень_неприятный баг MySQL, на самом деле
Файл, на котором я «тренировался», я назвал
00000.txt(5 нулей) и, в итоге, в базу из Event Log’a попадало вот чтоDeviceHarddiskVolume2TEST 0000.txtТо есть при выполнении INSERT MySQL «выгрызал» все символы ‘\’ и, более того делал из подстроки
0000.txtтакое вот"[SPACE]0000.txt"типа пытался «интерпретироватьпо своему»?А после того как я, предварительно, заменял все ‘\’ на ‘|’ — все проходило как надо
Дмитрий, думаю не лишним будет или упомянуть об этой «особенности» или поправить скрипт, который заносит имя файла в таблицу БД.
Видимо проблема в сочетании
"\"+"0", которое как-то интерпретируется mysql, то ли пустая строка, то ли что-то в этом роде.Согласен, в скрипте лучше всего заменить ‘\’ на ‘|’, а при выборке делать обратную замену.
Сейчас внесу изменения в статью. Спасибо!
А что скажете про [regex]::Escape(‘c:\’) ?
Я подобную штуку сейчас проворачиваю, но отправляю пошиком не напрямую в базу, а через пхп, так вот эскейп работает как надо. Мне интересно как будут обстоять дела, если пошиком напрямую в базу лить, но сам пробовать не хочу ))
Коллеги кто нибуть настраивал данную возможность с помощью SCOM?
Есть ли информация по данному вопросу,может быть кто то уже имел опыт,заранее спасибо за ответ.
Для настройки мониторинга данного EventID нужно в SCOM создать новое правило (Rule).
Правило создаём тут: Authoring -> Management Pack Objects -> Rules.
При создании указываем Type: Alert Generating Rules -> Event Based -> NT Event Log (Alert); Rule target: Windows Domain controller, Log Name: Security, Event ID eq 4663. Затем нужно привязаться к новому правилу действие в Subscription.
Странная команда в скрите
«Следующий скрипт запишет полученные данные в БД MySQL на удаленном сервере:»
вот эта
$Reader.Close()PowerShell ругается на нее. Наверное и правильно. Ведь закрывается то, что не открывалось.
А для Win2k как сделать подобное?
В нем аудит естьт, политика безопасности — есть, а события 4663 не выдается (((
Может кто сталкивался?
ID события скорее всего другие, да и не факт что PowerShell вообще заведется на W2k..
ЗЫ. Закапывайте мамонта
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));
результат.
Msg 102, Level 15, State 1, Line 1
Incorrect syntax near ‘AUTO_INCREMENT’.
Понял my SQL
Здраствуйте. Никогда раньше ни делал ничего подобного. Со второго раза вроде получилось. У меня вопрос в событии у меня есть строка » 192.168.201.153″ как добавть дополнительный столбец в таблицу и как в него записывать Ip адресс?
добрый день.
собран кластер на WS2016.
Есть CSV. Эту шару я и хочу логировать. Делаю все по инструкции, но когда что-либо оттуда удаляю, нет записи в логах Security.
Был ли опыт проведения аудита на кластерной шаре?
Спасибо. Хорошая статья.
Под рукой такой конфигурации нет. Могу посоветовать
1) проверить, что политики аудита применяются для обычных шар (записи в логе появляются).
2) в случае CSV возможно стоит проверять все логи на всех нодах кластера
1) работает, идеально.
2) проверяю на всех, к сожалению нет.
Запускай на каждой ноде. В Скрипте проверяй кто владеет нодой:
$ClusterRoleOwner = (Get-ClusterGroup | Where-Object {($_.Name -eq «ИМЯ ТВОЕЙ РОЛИ»)}).OwnerNode
если тот кто надо, то читаешь логи:
if ($ClusterRoleOwner -eq $env:computername)
Отличный каркас для работы с логами. После лёгкой косметической допилки всё полетело на MSSQL Express 2014 ADV (ставить на сервер вторую СУБД смысла нет). Бага с чир-символом в этой версии MSSQL нет. Всё загружается и выгружается чётко. 🙂
Спасибо автору))
Спасибо! Очень полезная вещь!
Пожалуйста подскажите, как быть с кириллицей в имени каталогов и файлов? В таблице вместо кириллицы знаки вопроса «…??????|?????.docx».
Что делать с русской кодировкой в именах файлах, к сожалению, не знаю. Как вариант — экспортировать журналы в csv файлы. А потом при загружать их через Get-Content -Encoding UTF8. Но это на уровне идеи…
Для правильного сохранения кириллицы добавьте в конец строки «charset=utf8»
Должно получится так
$Connection = [MySql.Data.MySqlClient.MySqlConnection]@{ConnectionString='server=10.7.7.13;uid=posh;pwd=P@ssw0rd;database=aduser;charset=utf8'}Отлично! Спасибо за полезную инфу!
Доброго времени суток. Попробовал, все равно «??????|?????.pdf» 🙁
Спасибо огромное. Разобрался. Нужно было сменить кодировку в самой БД на utf8_unicode_ci.
Для работы с любыми логами использую graylog community edition можно купить enterprise edition , и там делаю с логами что угодно
А что для визуализации данных и логов используете (графические дашборды, отчеты)?
С Elasticsearch обычно используют Kibana. А что у graylog как аналог?
PS C:\WINDOWS\system32> $event = [xml]$_.ToXml()
Невозможно вызвать метод для выражения со значением NULL.
строка:1 знак:1
+ $event = [xml]$_.ToXml()
+ ~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
Как поправить?
Какая ОС и версия PowerShell?
Windows Server 2012 R2 6.3.9600.18969 64-разрядная
Version PS : 5.1.14409.1018
Странно у меня в такой же конфигурации все работает. Windows Server случайно не русская? Я такую принципиально не пользую, только eng.
Нет. Проверил в 10-ке (правда «русской») — тоже такая же «петрушка»
Ну вот у меня код работает даже в русской Windows….
Запускаете в PowerShell ISE под админом?
Да, под админом
Не работает
А если удалять файлы с помощью Shift+DEL, то регистрируется только событие с id 4659. По крайней мере у меня на Windows Server 2012 так.
Здравствуйте, у нас стоят 2 сервера с Windows 2019, и на них установлен DFS с авторепликацией на оба сервера.
В результате у нас нет нормального аудита: в списках по событию 4663 (мы используем дополнительно фильтр по маске 0х10000, что предположительно соответствует операции DELETE) есть файлы с названиями типа
D:\System Volume Information\DFSR\Private\{ABC…}-{DEF…}\Installing\Teil-of-name-{123..}-v123456.doc
(это после удаления всех файлов типа .log, .tmp и \~$ ). Причём в качестве пользователя стоит имя сервера.
Ещё есть удаления целых каталогов (?!), тоже с именем сервера. В поле ProzessName стоит C:\Windows\System32\dfsrs.exe
Есть и удаления от конкретных пользователей, но от них идут несколько удалений одних и тех же файлов — это вероятно результаты неоднократных редактирований того же файла… При этом поле ProzessName вообще пустое!
Вопрос: каким образом можно обнаружить удаления при использовании DFS ?
Колеги а как очистить журнал после того, как витянул данные с журнала?
Я же буду на постой дозаписывать то, что уже есть.
Очистка журналов событий в Windows: https://winitpro.ru/index.php/2017/07/31/ochistka-zhurnalov-sobytij-windows-s-pomoshhyu-powershell-i-wevtutil/
Нужно искать пару : id 4663 а потом 4660 с аналогичным кодом дескриптора в двух событиях. Тогда это будет реальное удаление.
https://docs.microsoft.com/en-us/windows/security/threat-protection/auditing/event-4660
Доброго времени, уважаемые коллеги!
У меня сервер 2008. Сделал всё как тут написано, получилось на ура. Но хотелось бы задать вопрос. В событиях по коду 4663 регистрируется только пользователь и действия с файлом, которые он инициировал. Но хотелось бы в событиях поиметь или имя компа или его айпишник. Думал, на 2008 серваке такого нет, а есть в более поздних серверных версиях, но нет. На работе посмотрел, также без айпишников логи ведутся.
Есть ли возможность добавить в событие 4663 IP или имя компа? Хочу вычислить, откуда вирусня прёт, а то в этой организации многие сидят под одним логином. Я говорю, давайте каждому учётку заведём. Нет, говорят. Нам так удобнее. Ну что с такими делать?
Имеено это событие вы никак не расширите. Тут нужно скорре всего нужно дополнительно анализировать события логона компьютера на ваш сервере из журнала Security. Скорее всего они будут связаны по logonID или handleID. И уже из события логона вытягивать имя компьютера.
Сначала попробуйте вручную разобраться с ID события и их связью с 4663 . Пришлите инфу сюда, может помогу в чем.
—
4663
1
0
12800
0
0x8020000000000000
1013357
Security
pismo
—
S-1-5-21-2924944393-1657555545-3026754319-501
Гость
PISMO
0xc4bc6
Security
File
D:\pismo1\!Tinchlik\Бизнес кредитларни ундириш шўъбаси\ФАЙЛ
0xc68
%%1537
0x10000
0x4
S:AI
здесь вошел в систему как гость, и все пользователи входят в систему под этим именем. Как я могу определить IP-адрес, чтобы найти человека или компьютер, который удалил файл?
Выполнена попытка получения доступа к объекту.
Субъект:
ИД безопасности: PISMO\Гость
Имя учетной записи: Гость
Домен учетной записи: PISMO
ИД входа: 0xC4BC6
Объект:
Сервер объекта: Security
Тип объекта: File
Имя объекта: D:\pismo1\!Tinchlik\Бизнес кредитларни ундириш шўъбаси\ФАЙЛ
Код дескриптора: 0xc68
Атрибуты ресурса: S:AI
Сведения о процессе:
ИД процесса: 0x4
Имя процесса:
Сведения о запросе на доступ:
Операции доступа: DELETE
Маска доступа: 0x10000
Спасибо за статью. Пришлось исправить, т.к. у меня Server 2008 R2 (соответственно там старая версия Powershell), данные выгружаются в MySQL 5.0.95, который находится на другом старом Linux сервере:
1) В базе выполнил SQL-запрос:
SET SESSION old_passwords=0;
SET PASSWORD FOR db_user_name=PASSWORD(‘db_user_password’);
2) Скрипт выглядит так:
Set-ExecutionPolicy RemoteSigned
Add-Type –Path ‘C:\Program Files (x86)\MySQL\MySQL Connector Net 6.9.8\Assemblies\v2.0\MySql.Data.dll’
$connectionString = «server=server_IP;uid=db_user_name;pwd=db_user_password;database=db_name;»
$connection = New-Object MySql.Data.MySqlClient.MySqlConnection
$connection.ConnectionString = $connectionString
$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()
}
}
$Connection.Close()
3) Создал задание в планировщике с такими параметрами:
Вкладка Общие:
-выполнять вне зависимости от регистрации пользователя
-выполнять с наивысшими правами
-выполнять от учетки админа домена
Вкладка Триггеры:
-начать задачу при событии
-Параметры: Простое, Журнал — Безопасность, Источник — Microsoft Windows security auditing, Код события — 4663
-внизу галочка — Включено
Вкладка Действия:
-Действие — Запуск программы
-Программа или сценарий: C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe
-Добавить аргументы: E:\scripts\file_del_to_db.ps1 (путь к скрипту)
Вкладка Параметры:
-Разрешать выполнение задачи по требованию
-Останавливать задачу, выполняемую дольше: 3 дн.
-Принудительная остановка задачи, если она не прекращается по запросу
-Если задача уже выполняется, то применять правило: Не запускать новый экземпляр.
Ну и при сохранении задачи естественно нужно будет ввести пароль пользователя, от имени которого она будет выполняться (у меня учетка админа домена).
Теперь особенность. За 1,5 дня у меня в базе 8000 записей. Как бы много, и не очень удобно в случае чего искать нужные.
Просьба к автору статьи, не могли бы Вы изменить скрипт так, чтобы данные в базу писались каждый день в отдельные таблицы или как-то по-другому их отделить, а также сделать исключение файлов, например, по расширению (а то пользователи напрямую открывают по сети файлы Microsoft Office и в базу потом пишутся записи об удалённых файлах *.tmp). Спасибо))).
За инфу спасибо.
1) Писать в разные таблицы? а зачем, не проще фильтровать записи по дате.
2) Чтобы писать инфу только по нужным расширениям файлам, просто сделайте дополнительную проверку содержимого $File на соответствие нужным расширениям файлов перед запись в базу:
$allowedext = @('.doc','.docx','.xlsx','.xls')$fileext=[System.IO.Path]::GetExtension($file)
if ($allowedext -match $fileext')
{
write to db
}
Спасибо за ответ. Не могу точно знать какие типы файлов там есть, т.к. структура папок огромная, всего примерно 2 млн. файлов))) Конечно и ненужные есть, но рыться там у меня нет желания, у каждого отдела своя папка… короче там чёрт ногу сломит))). Поэтому вышел из положения так:
1) Перенес базу на новый Linux сервер, там 10.3.28-MariaDB. В ней есть уже планировщик заданий.
2) В phpmyadmin создал задачу, которая каждый день в 00:00 удаляет из базы записи о файлах *.tmp.
Параметры задачи такие:
Название события: file_del_tmp_every_day
Состояние: ENABLED
Тип события: RECURRING
Выполнять каждые: 1 DAY
Начало: 2021-05-14 00:00:00
Конец: (Пусто)
Определение: delete from `db_name`.`track_del` where file_name like ‘%.tmp’
Сохранить при окончании: (Поставил галочку)
Определитель: root@localhost
Также нужно не забыть:
Статус планировщика событий: Включить
Пока пусть будет так. Правда с 14 мая 2021 до сегодня (21 мая 2021) размер базы 114 МБ и количество строк примерно 530000))). Жесть конечно, пока не знаю что с этим делать))).
Из личных наблюдений. События 4660 и 4663 появляются при локальном удалении из локальной или сетевой папки, т.е. пользователь совершил локальный вход на сервер и удаляет файл с диска или из папки в общем доступе. Событие 4659 — при сетевом удалении из сетевой папки. Так что как применять статью не понятно.
В новых версиях Windows при удалении минуя корзину ещё записываются события с кодом 4659. Достаточно добавить код этого события в скрипт. Например, для записи списка удаленных файлов в текстовый файл изменить строку примерно так:
…
Get-WinEvent -FilterHashTable @{LogName=»Security»;starttime=»$today»;id=4663,4459} | Foreach {
…
Скрипт записи в текстовый файл дополненный выборкой только по удаленным файлам:
$Outfile = «C:\ps\delete-file-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.Event.EventData[9].’#text’ -eq ‘0x10000’)
{
$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
}
}
Корректировка) пропустил Data[9]
$event.Event.EventData.Data[9]
Статья нужная, но нам нужно было на создание файлов в обмене и отправлялся отчет. Добавили в планировщик задачу с выполнением скрипта. Если кому нужно сам скрипт:
$Outfile = "D:\audit.txt" #$(Get-Date -UFormat "%d-%m-%Y_%H_%M_%S").txt" - у меня сохраняет в единый файл, но кому надо будет создавать ежедневный отчет.
$today = [datetime]::Today.AddDays(-5) #Get-Date -DisplayHint date -UFormat %d-%m-%Y Указал за последние 5 дней сбор данных
$strLog = @()
Get-WinEvent -FilterHashTable @{ LogName = "Security"; starttime = $today; id = 4663} | Foreach {
$event = [xml]$_.ToXml()
if($event) {
$Time = Get-Date $_.TimeCreated -UFormat "%d-%m-%Y %H:%M:%S"
$File = $event.Event.EventData.Data[6]."#text"
$User = $event.Event.EventData.Data[1]."#text"
If ($User -notmatch "SERVER\$|LOCAL SERVICE" -and $File -match "F:\\obmen") { # исключаем наименование сервера SERVER\$|LOCAL SERVICE (у вас будет имя иначе) и включать только записи с расположением папки obmen
$strLog += $Time + " " + $User + " " + $Computer + " " + $File
}
}
}
$strLog | out-file $Outfile
#Отправляем письмо с отчетом о проведении аудита
$ToAddress = "IBadm@pochta.ru"
$CcAddress = "IBadm1@pochta.ru"
$FromAddress = "obmen@pochta.ru"
$SmtpServer = "mail.pochta.ru"
$sabj = "Аудит обмена"
$text = "text"
$mailparam = @{
To = $ToAddress
Cc = $CcAddress
From = $FromAddress
Subject = $sabj
Body = $text
SmtpServer = $SmtpServer
Attachments = "d:\audit.txt"
}
Send-MailMessage @mailparam -Encoding UTF8
Пользуйтесь.
А можно пример скрипта который в текстовой файл записывает удаленные и редактируемые объекты
(вывод в формате расположение файла-время-пользователь-действие)
Отличная статья, спасибо!
Правда у меня не всё получилось. На некоторых подпапках отключено наследование прав по аудиту и устанавливая аудит на родительскую папку, внутри на часть папок аудит так и не доезжает. Пробовал рекурсией пройтись по всем каталогам, но в таком случае права аудит выставляются на каждый каталог в отдельности.
Может есть идеи, как найти все подпапки с отключённым наследованием прав аудита и включить наследование на них?
Можно вывести папки (включая вложенные), для которых не включено наследование с помощью PowerShell:
DIR "C:\Folder" -directory -recurse | GET-ACL | where {$_.Access.IsInherited -eq $false}
Нужно что бы когда пользователь удаляет файл/папку приходило уведомления об этом на почту админа. С этим все ок. Через task shedule настроено на конкретный eventid запуск powershell скрипта, уведомления приходит но проблема в том что когда пользователь удаляет файл/папку приходит несколько писем одновременно (доступ на файл, удаления и др.). А мне нужно только удаления. Фильтировать с помощью 4660 не получилось так как разные действия (доступ,удаления и т.д.) приходят под одну категорию. Нащел решения переходить на ID 4656, там тоже получаем несколько уведомлений при одном удаление, но фильтровать чистое удаления можно с помощью категории (выбрав «Файловая система»), но никак не могу заставить работать фильтр под категорию (например: Where-Object {$_.Category -match 12800}).
Буду благодарен за идею.
$EventId = 4660$A = Get-WinEvent -MaxEvents 1 -FilterHashTable @{Logname = "Security" ; ID = $EventId}
$Message = $A.Message
$EventID = $A.Id
$MachineName = $A.MachineName
$Source = $A.ProviderName
$Password = Get-Content "C:\fy.txt" | ConvertTo-SecureString
$EmailFrom = "testmail@mail.com"
$EmailTo = "2testmail@mail.com"
$Subject ="Alert From $MachineName"
$Body = "EventID: $EventID`nSource: $Source`nMachineName: $MachineName `nMessage: $Message"
$SMTPServer = "smtp.office365.com"
$SMTPClient = New-Object Net.Mail.SmtpClient($SmtpServer, 587)
$SMTPClient.EnableSsl = $true
$SMTPClient.Credentials = New-Object System.Net.NetworkCredential("testmail@mail.com", $Password);
$SMTPClient.Send($EmailFrom, $EmailTo, $Subject, $Body)
Добрый день! Сделал все по инструкции , но возникла проблема. Когда удаляю папку , в логах записывается, но когда удаляю файл , в логах ничего не пишется
Посмотрите в настройках аудита папки, что выбран режим This folder, subfolder and files.
Подскажите, а если вместо имени папки в привычном виде отображается что-то типа:
Имя объекта: C:\Windows\WinSxS\FileMaps\$$_system32_21f9a9c4a2f8b514.cdf-ms
Как это исправить?
Чтобы в файл из журнала записывались события только по нужной папке, можно сделать так (выше приведены уже были скрипты в комментариях):
If ($File -match «ПУТЬ К НЕОБХОДИМОЙ ПАПКЕ АУДИТА»)
{
$strLog = $Computer + » » + $File + » » + $Time + » » + $User
$strLog | out-file $Outfile -append
}