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:
+34
-14
@@ -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."
|
||||||
|
|||||||
@@ -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
@@ -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
@@ -1 +1 @@
|
|||||||
2.0.16-SAC
|
2.0.17-SAC
|
||||||
|
|||||||
Reference in New Issue
Block a user