fix: recognize auditpol RU Success+Failure as otказ not only sboy (2.0.17-SAC)

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
PTah
2026-06-03 15:08:20 +10:00
parent 0acd591c83
commit 6384a45395
4 changed files with 37 additions and 17 deletions
+34 -14
View File
@@ -89,7 +89,7 @@ $script:SkipLogDetailLimit = 15
# строки ниже, если правки «мелкие» и вы не хотите менять отображаемую версию в логах). # строки ниже, если правки «мелкие» и вы не хотите менять отображаемую версию в логах).
# Рекомендация: при значимых релизах меняйте и $ScriptVersion, и version.txt одинаково; при только # Рекомендация: при значимых релизах меняйте и $ScriptVersion, и version.txt одинаково; при только
# исправлениях на шаре — достаточно поднять patch в version.txt (например 1.3.0.1). # исправлениях на шаре — достаточно поднять patch в version.txt (например 1.3.0.1).
$ScriptVersion = "2.0.16-SAC" $ScriptVersion = "2.0.17-SAC"
# Логи (все под InstallRoot) # Логи (все под InstallRoot)
$LogFile = Join-Path $script:InstallRoot "Logs\login_monitor.log" $LogFile = Join-Path $script:InstallRoot "Logs\login_monitor.log"
@@ -1139,13 +1139,18 @@ function Enable-SecurityAudit {
function Test-SuccessAndFailureText { function Test-SuccessAndFailureText {
param([string]$Line) param([string]$Line)
if ([string]::IsNullOrWhiteSpace($Line)) { return $false } if ([string]::IsNullOrWhiteSpace($Line)) { return $false }
$w1 = Uc @(0x0443,0x0441,0x043F,0x0435,0x0445) $wSuccess = Uc @(0x0443,0x0441,0x043F,0x0435,0x0445)
$w2 = Uc @(0x0438) $wAnd = Uc @(0x0438)
$w3 = Uc @(0x0441,0x0431,0x043E,0x0439) # RU auditpol: "Успех и сбой" (older builds) or "Успех и отказ" (common on Server 2016+ RU).
$p1 = '(?i)' + [regex]::Escape($w1) + '\s+' + [regex]::Escape($w2) + '\s+' + [regex]::Escape($w3) $failureWords = @(
$p2 = '(?i)' + [regex]::Escape($w1) + '\s*' + [regex]::Escape($w2) + '\s*' + [regex]::Escape($w3) (Uc @(0x0441,0x0431,0x043E,0x0439)),
if ($Line -match $p1) { return $true } (Uc @(0x043E,0x0442,0x043A,0x0430,0x0437))
if ($Line -match $p2) { return $true } )
foreach ($wFail in $failureWords) {
$p1 = '(?i)' + [regex]::Escape($wSuccess) + '\s+' + [regex]::Escape($wAnd) + '\s+' + [regex]::Escape($wFail)
$p2 = '(?i)' + [regex]::Escape($wSuccess) + '\s*' + [regex]::Escape($wAnd) + '\s*' + [regex]::Escape($wFail)
if ($Line -match $p1 -or $Line -match $p2) { return $true }
}
if (($Line -match '(?i)Success') -and ($Line -match '(?i)Failure')) { return $true } if (($Line -match '(?i)Success') -and ($Line -match '(?i)Failure')) { return $true }
return $false return $false
} }
@@ -1243,6 +1248,23 @@ function Enable-SecurityAudit {
return $true return $true
} }
# Locale-neutral subcategory GUIDs (Logon / Logoff).
function Ensure-LogonLogoffSubcategoriesByGuid {
$targets = @(
'0CCE9226-69AE-11D9-BED3-505054503030',
'0CCE9227-69AE-11D9-BED3-505054503030'
)
foreach ($guid in $targets) {
$setArgs = ('/set /subcategory:{{{0}}} /success:enable /failure:enable' -f $guid)
$set = Invoke-AuditPol -Arguments $setArgs
if ($set.ExitCode -ne 0) {
Write-Log ("auditpol GUID SET FAIL (code {0}): {1}`n{2}" -f $set.ExitCode, $setArgs, $set.Text)
return $false
}
}
return $true
}
$preferRu = Test-RussianUiPreferred $preferRu = Test-RussianUiPreferred
if ($preferRu) { if ($preferRu) {
@@ -1258,12 +1280,10 @@ function Enable-SecurityAudit {
return return
} }
# Logon/Logoff category GUID (not a user id). Write-Log "Trying Logon/Logoff subcategories via known GUIDs (locale-neutral fallback)..."
Write-Log "Trying Logon/Logoff category set via known GUID (fallback)..." if (Ensure-LogonLogoffSubcategoriesByGuid) {
$logonLogoffCategoryGuid = "69979849-797A-11D9-BED3-505054503030" Write-Log "Audit policy (GUID): OK for Logon/Logoff subcategories."
$guidSet = Invoke-AuditPol -Arguments ("/set /category:`"$logonLogoffCategoryGuid`" /success:enable /failure:enable") return
if ($guidSet.ExitCode -ne 0) {
Write-Log ("auditpol GUID SET FAIL (code {0}):`n{1}" -f $guidSet.ExitCode, $guidSet.Text)
} }
Write-Log "WARNING: could not configure logon/logoff auditing via auditpol automatically. The script will continue; check audit policy in local/domain GPO." Write-Log "WARNING: could not configure logon/logoff auditing via auditpol automatically. The script will continue; check audit policy in local/domain GPO."
+1 -1
View File
@@ -41,7 +41,7 @@ Get-Content "C:\ProgramData\RDP-login-monitor\Logs\login_monitor.log" -Tail 60
- **Локальные настройки RDP-монитора** вынесены в **`login_monitor.settings.ps1`** (образец **`login_monitor.settings.example.ps1`**). При автообновлении **`Login_Monitor.ps1`** с шары секреты и параметры КД **не слетают**. Deploy при отсутствии settings создаёт файл один раз из example на шаре. - **Локальные настройки RDP-монитора** вынесены в **`login_monitor.settings.ps1`** (образец **`login_monitor.settings.example.ps1`**). При автообновлении **`Login_Monitor.ps1`** с шары секреты и параметры КД **не слетают**. Deploy при отсутствии settings создаёт файл один раз из example на шаре.
- **Кодировка `.ps1`**: в репозитории добавлены `.editorconfig` и `.gitattributes`, чтобы `*.ps1` по умолчанию сохранялись как **UTF-8 with BOM** и с **CRLF** (это сильно снижает “кракозябры” и ошибки парсинга PowerShell). - **Кодировка `.ps1`**: в репозитории добавлены `.editorconfig` и `.gitattributes`, чтобы `*.ps1` по умолчанию сохранялись как **UTF-8 with BOM** и с **CRLF** (это сильно снижает “кракозябры” и ошибки парсинга PowerShell).
- **Кодировка логов**: `login_monitor.log` / `watchdog.log` пишутся как **UTF-8 с BOM** (и при необходимости BOM добавляется к уже существующему файлу), чтобы в **FAR/старых просмотрщиках** не было ситуации “в консоли нормально, а в файле РЈРІРµ…” из‑за неверной авто-кодировки. - **Кодировка логов**: `login_monitor.log` / `watchdog.log` пишутся как **UTF-8 с BOM** (и при необходимости BOM добавляется к уже существующему файлу), чтобы в **FAR/старых просмотрщиках** не было ситуации “в консоли нормально, а в файле РЈРІРµ…” из‑за неверной авто-кодировки.
- **`auditpol` на русской Windows**: настройка/проверка аудита опирается на категорию **`Вход/выход`** и подкатегории **`Вход в систему` / `Выход из системы`** (ожидается строка **`Успех и сбой`**). Это устраняет ошибки вида `0x00000057` из‑за несуществующего на RU ОС имени `Logon`. - **`auditpol` на русской Windows**: настройка/проверка аудита опирается на категорию **`Вход/выход`** и подкатегории **`Вход в систему` / `Выход из системы`** (ожидается **`Успех и сбой`** или **`Успех и отказ`** — формулировка зависит от сборки ОС). Это устраняет ошибки вида `0x00000057` из‑за несуществующего на RU ОС имени `Logon`.
- **Стабильность**: `auditpol` вызывается по полному пути `%SystemRoot%\System32\auditpol.exe` (без зависимости от PATH), stdout+stderr объединяются через `ProcessStartInfo`. - **Стабильность**: `auditpol` вызывается по полному пути `%SystemRoot%\System32\auditpol.exe` (без зависимости от PATH), stdout+stderr объединяются через `ProcessStartInfo`.
- **Агрегация 4625 (брутфорс)**: при включённом `$FailedLogonRateLimitEnabled` — уровень 1: **5** неудачных попыток за **60** с с одного источника для **одной** учётной записи (IP+user); уровень 2: **12** попыток за **60** с с одного IP (несколько логинов). Пока порог не достигнут — поштучные 4625; при всплеске — сводные алерты, одиночные подавляются. Параметры в начале `Login_Monitor.ps1`. Автоблокировка IP не выполняется. - **Агрегация 4625 (брутфорс)**: при включённом `$FailedLogonRateLimitEnabled` — уровень 1: **5** неудачных попыток за **60** с с одного источника для **одной** учётной записи (IP+user); уровень 2: **12** попыток за **60** с с одного IP (несколько логинов). Пока порог не достигнут — поштучные 4625; при всплеске — сводные алерты, одиночные подавляются. Параметры в начале `Login_Monitor.ps1`. Автоблокировка IP не выполняется.
- **Exchange Mail Security** (`Exchange-MailSecurity.ps1`): на **сервере Exchange** — очереди, пересылка на внешние адреса, watchdog. Руководство: **[Docs/exchange-mail-security.md](Docs/exchange-mail-security.md)**. GPO **`Deploy-LoginMonitor.ps1`** на MailServer ставит тот же RDP-монитор и дописывает WinRM/4624 noise в **`login_monitor.settings.ps1`**; **`Deploy-DomainMonitors.ps1 -Target Exchange`** — отдельно. - **Exchange Mail Security** (`Exchange-MailSecurity.ps1`): на **сервере Exchange** — очереди, пересылка на внешние адреса, watchdog. Руководство: **[Docs/exchange-mail-security.md](Docs/exchange-mail-security.md)**. GPO **`Deploy-LoginMonitor.ps1`** на MailServer ставит тот же RDP-монитор и дописывает WinRM/4624 noise в **`login_monitor.settings.ps1`**; **`Deploy-DomainMonitors.ps1 -Target Exchange`** — отдельно.
+1 -1
View File
@@ -18,7 +18,7 @@ PowerShell toolkit for monitoring Windows logons with Telegram and/or Email (SMT
- **`.ps1` encoding**: `.editorconfig` and `.gitattributes` encourage **`*.ps1`** as **UTF-8 with BOM** and **CRLF**, reducing mojibake and PowerShell parse issues. - **`.ps1` encoding**: `.editorconfig` and `.gitattributes` encourage **`*.ps1`** as **UTF-8 with BOM** and **CRLF**, reducing mojibake and PowerShell parse issues.
- **Log encoding**: `login_monitor.log` / `watchdog.log` are written as **UTF-8 with BOM** (BOM is applied to existing files if missing) so viewers like **FAR Manager** do not mis-detect encoding. - **Log encoding**: `login_monitor.log` / `watchdog.log` are written as **UTF-8 with BOM** (BOM is applied to existing files if missing) so viewers like **FAR Manager** do not mis-detect encoding.
- **`auditpol` on Russian Windows**: auditing checks use the **`Вход/выход`** category and **`Вход в систему` / `Выход из системы`** subcategories (expect **`Успех и сбой`**), avoiding errors such as `0x00000057` when English names like `Logon` are absent on a localized OS. - **`auditpol` on Russian Windows**: auditing checks use the **`Вход/выход`** category and **`Вход в систему` / `Выход из системы`** subcategories (expect **`Успех и сбой`** or **`Успех и отказ`**, depending on OS build), avoiding errors such as `0x00000057` when English names like `Logon` are absent on a localized OS.
- **Stability**: `auditpol` is invoked via full path `%SystemRoot%\System32\auditpol.exe` (no PATH dependency); stdout and stderr are merged via `ProcessStartInfo`. - **Stability**: `auditpol` is invoked via full path `%SystemRoot%\System32\auditpol.exe` (no PATH dependency); stdout and stderr are merged via `ProcessStartInfo`.
- **`4625` burst alerts**: when `$FailedLogonRateLimitEnabled` is true — tier 1: **5** failures in **60** s per **IP+user**; tier 2: **12** in **60** s per **IP** (spray). Below thresholds, individual `4625` alerts are sent; during a burst, aggregated alerts replace per-event noise. No automatic IP blocking. Tune at the top of `Login_Monitor.ps1`. - **`4625` burst alerts**: when `$FailedLogonRateLimitEnabled` is true — tier 1: **5** failures in **60** s per **IP+user**; tier 2: **12** in **60** s per **IP** (spray). Below thresholds, individual `4625` alerts are sent; during a burst, aggregated alerts replace per-event noise. No automatic IP blocking. Tune at the top of `Login_Monitor.ps1`.
- **Exchange Mail Security** (`Exchange-MailSecurity.ps1`): Exchange server only — queues, external forwarding, watchdog. See **[Docs/exchange-mail-security.md](Docs/exchange-mail-security.md)**. - **Exchange Mail Security** (`Exchange-MailSecurity.ps1`): Exchange server only — queues, external forwarding, watchdog. See **[Docs/exchange-mail-security.md](Docs/exchange-mail-security.md)**.
+1 -1
View File
@@ -1 +1 @@
2.0.16-SAC 2.0.17-SAC