configure-sacl: cover per-user objects across all profiles + Default

Enumerate every user profile from ProfileList (plus C:\Users\Default so future
users inherit the SACL) and apply per-user SACLs:
- user_files: file SACL under each profile dir (Startup folder, Signal AppData).
- user_registry: registry SACL on each user hive - loaded hives via
  HKEY_USERS\<SID> directly, offline/Default hives by reg-load/unload of
  NTUSER.DAT (HKCU Run/RunOnce, User Shell Folders, StartupApproved, Load/Run,
  Command Processor AutoRun, Control Panel\Desktop screensaver, Environment
  logon script, LangBarAddin, Outlook Addins).
Handles are released ([gc]) before reg unload; objects/hives absent on the host
are skipped. Not covered: folder-redirected AppData on network shares, mandatory
profiles.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MVUmXZBkr5FnZ2hwFkDhx7
This commit is contained in:
Shirofune-SecurityandClaude Opus 4.8 committed 2026-09-17 22:03:24 +09:00
1 parent 6aef4c0f7b
commit 31aeeda768
2 files changed
+117 -2

No files matched your search

+99 -1
View File
@@ -1388,8 +1388,106 @@ function Set-AuditSacl {
} catch { Write-Host "[ERROR] $($t.path) : $_" -ForegroundColor Red }
}
Write-Host ""
# 4) Per-user objects: enumerate every profile (+ Default, for future users) and apply SACLs.
$hasUserTargets = ($targets.PSObject.Properties.Name -contains 'user_files' -and $targets.user_files) -or `
($targets.PSObject.Properties.Name -contains 'user_registry' -and $targets.user_registry)
if ($hasUserTargets) {
Write-Host "Enumerating user profiles for per-user SACLs..."
$profiles = Get-WelaUserProfiles
Write-Host "Found $($profiles.Count) profile(s) (incl. Default template)."
Write-Host ""
# 4a) Per-user FILE SACLs (each existing profile + Default)
if ($targets.user_files) {
foreach ($prof in $profiles) {
foreach ($t in $targets.user_files) {
$path = Join-Path $prof.Path $t.relpath
try {
if (-not (Test-Path -LiteralPath $path)) { continue } # not installed for this user
$isDir = (Get-Item -LiteralPath $path -Force).PSIsContainer
$rights = [System.Security.AccessControl.FileSystemRights]($t.rights -join ",")
$inh = if ($isDir -and $t.inherit) { [System.Security.AccessControl.InheritanceFlags]"ContainerInherit,ObjectInherit" } else { [System.Security.AccessControl.InheritanceFlags]"None" }
$acl = Get-Acl -LiteralPath $path -Audit
$already = $acl.Audit | Where-Object { $_.IdentityReference.Value -eq $everyone.Value -and (($_.FileSystemRights -band $rights) -eq $rights) -and ($_.AuditFlags -eq $auditFlags) }
if ($already) { continue }
if ($Auto -or $PSCmdlet.ShouldProcess("$path [$($prof.Sid)]", "add audit SACL")) {
$rule = New-Object System.Security.AccessControl.FileSystemAuditRule($everyone, $rights, $inh, "None", $auditFlags)
$acl.AddAuditRule($rule); Set-Acl -LiteralPath $path -AclObject $acl
Write-Host "[OK] $path ($($t.note))" -ForegroundColor Green
}
} catch { Write-Host "[ERROR] $path : $_" -ForegroundColor Red }
}
}
}
# 4b) Per-user REGISTRY SACLs. Loaded hives -> HKEY_USERS\<SID> directly;
# offline / Default hives -> reg load NTUSER.DAT, apply, reg unload.
if ($targets.user_registry) {
foreach ($prof in $profiles) {
$loadedHere = $false
if ($prof.Loaded) {
$base = "Microsoft.PowerShell.Core\Registry::HKEY_USERS\$($prof.Sid)"
} else {
$hive = Join-Path $prof.Path "NTUSER.DAT"
if (-not (Test-Path -LiteralPath $hive)) { continue }
$mount = "WELA_$($prof.Sid)"
$out = reg load "HKU\$mount" "$hive" 2>&1
if ($LASTEXITCODE -ne 0) { Write-Host "[SKIPPED] hive $($prof.Sid) : cannot load ($out)" -ForegroundColor DarkYellow; continue }
$loadedHere = $true
$base = "Microsoft.PowerShell.Core\Registry::HKEY_USERS\$mount"
}
try {
foreach ($t in $targets.user_registry) {
$key = "$base\$($t.key)"
try {
if (-not (Test-Path -LiteralPath $key)) { continue }
$rights = [System.Security.AccessControl.RegistryRights]($t.rights -join ",")
$inh = if ($t.inherit) { [System.Security.AccessControl.InheritanceFlags]"ContainerInherit" } else { [System.Security.AccessControl.InheritanceFlags]"None" }
$acl = Get-Acl -LiteralPath $key -Audit
$already = $acl.Audit | Where-Object { $_.IdentityReference.Value -eq $everyone.Value -and (($_.RegistryRights -band $rights) -eq $rights) -and ($_.AuditFlags -eq $auditFlags) }
if ($already) { continue }
if ($Auto -or $PSCmdlet.ShouldProcess("$($t.key) [$($prof.Sid)]", "add audit SACL")) {
$rule = New-Object System.Security.AccessControl.RegistryAuditRule($everyone, $rights, $inh, "None", $auditFlags)
$acl.AddAuditRule($rule); Set-Acl -LiteralPath $key -AclObject $acl
Write-Host "[OK] HKU\$($prof.Sid)\$($t.key) ($($t.note))" -ForegroundColor Green
}
} catch { Write-Host "[ERROR] $($t.key) [$($prof.Sid)] : $_" -ForegroundColor Red }
}
}
finally {
if ($loadedHere) {
# release handles before unloading, or 'reg unload' fails
[gc]::Collect(); [gc]::WaitForPendingFinalizers()
reg unload "HKU\$mount" 2>&1 | Out-Null
}
}
}
}
Write-Host ""
}
Write-Host "Done. Targeted object-access auditing is enabled without global file/registry auditing." -ForegroundColor Cyan
Write-Host "Note: per-user (HKCU / profile AppData) objects are out of scope for a machine-wide SACL policy." -ForegroundColor DarkCyan
Write-Host "Per-user objects were applied to existing profiles and the Default profile (future users)." -ForegroundColor DarkCyan
Write-Host "Not covered: folder-redirected AppData on network shares, and mandatory profiles." -ForegroundColor DarkCyan
}
function Get-WelaUserProfiles {
# Enumerate real user profiles from ProfileList (SID + path + whether the hive is loaded),
# plus the Default profile template so SACLs propagate to future users.
$result = @()
$pl = "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList"
foreach ($k in (Get-ChildItem -LiteralPath $pl -ErrorAction SilentlyContinue)) {
$sid = $k.PSChildName
if ($sid -notmatch '^S-1-5-21-') { continue } # skip system/service SIDs (S-1-5-18/19/20)
$p = (Get-ItemProperty -LiteralPath $k.PSPath -Name ProfileImagePath -ErrorAction SilentlyContinue).ProfileImagePath
if (-not $p -or -not (Test-Path -LiteralPath $p)) { continue }
$loaded = Test-Path -LiteralPath "Microsoft.PowerShell.Core\Registry::HKEY_USERS\$sid"
$result += [pscustomobject]@{ Sid = $sid; Path = $p; Loaded = $loaded }
}
$def = Join-Path $env:SystemDrive "Users\Default"
if (Test-Path -LiteralPath $def) { $result += [pscustomobject]@{ Sid = "DEFAULT"; Path = $def; Loaded = $false } }
return $result
}
$usage = @"
+18 -1
View File
@@ -1,5 +1,5 @@
{
"description": "Targeted System Access Control Lists (SACLs) that make Object Access File System (4663), Registry (4657) and Handle Manipulation (4656/4658) auditing produce the events the Hayabusa/Sigma Security-channel rules rely on - WITHOUT enabling global file/registry auditing (which would flood). Only the specific autostart/persistence registry keys (ASEPs) and sensitive files referenced by the ruleset are audited. Principal is 'Everyone'. Registry keys use ContainerInherit so subkeys are covered. Objects that are absent on a given host (e.g. Wow6432Node on 32-bit, NTDS on non-DCs) are skipped. Per-user objects (HKCU / user-profile AppData) cannot be set machine-wide here and are intentionally out of scope - apply those via logon script / GPP.",
"description": "Targeted System Access Control Lists (SACLs) that make Object Access File System (4663), Registry (4657) and Handle Manipulation (4656/4658) auditing produce the events the Hayabusa/Sigma Security-channel rules rely on - WITHOUT enabling global file/registry auditing (which would flood). Only the specific autostart/persistence registry keys (ASEPs) and sensitive files referenced by the ruleset are audited. Principal is 'Everyone'. Registry keys use ContainerInherit so subkeys are covered. Objects that are absent on a given host (e.g. Wow6432Node on 32-bit, NTDS on non-DCs) are skipped. Per-user objects are handled via 'user_registry' and 'user_files': WELA enumerates every profile from ProfileList (plus C:\\Users\\Default so future users inherit the SACL), sets file SACLs under each profile, and sets registry SACLs on each user hive (loaded hives directly via HKU:\\<SID>, offline/Default hives by reg-load/unload of NTUSER.DAT). 'user_registry' keys are relative to the user hive root; 'user_files' paths are relative to the profile directory. Remaining edge cases (folder-redirected AppData on network shares, mandatory profiles) are not covered.",
"registry": [
{"path": "HKLM:\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", "inherit": true, "rights": ["SetValue","CreateSubKey","Delete"], "note": "ASEP Run (T1547.001)"},
{"path": "HKLM:\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\RunOnce", "inherit": true, "rights": ["SetValue","CreateSubKey","Delete"], "note": "ASEP RunOnce"},
@@ -32,6 +32,23 @@
{"path": "HKLM:\\SOFTWARE\\Microsoft\\Windows Defender\\Exclusions", "inherit": true, "rights": ["SetValue","CreateSubKey"], "note": "Defender exclusion tampering (T1562.001)"},
{"path": "HKLM:\\SYSTEM\\CurrentControlSet\\Services", "inherit": false, "rights": ["CreateSubKey","Delete"], "note": "Service create/delete (T1543.003). Subkey add/remove only, to limit noise - service value edits are captured by 4697/7045."}
],
"user_registry": [
{"key": "Software\\Microsoft\\Windows\\CurrentVersion\\Run", "inherit": true, "rights": ["SetValue","CreateSubKey","Delete"], "note": "HKCU ASEP Run (T1547.001)"},
{"key": "Software\\Microsoft\\Windows\\CurrentVersion\\RunOnce", "inherit": true, "rights": ["SetValue","CreateSubKey","Delete"], "note": "HKCU ASEP RunOnce"},
{"key": "Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer\\Run", "inherit": true, "rights": ["SetValue","CreateSubKey","Delete"], "note": "HKCU Policies Explorer Run"},
{"key": "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders", "inherit": false, "rights": ["SetValue"], "note": "Startup folder redirection (T1547.001)"},
{"key": "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\StartupApproved\\Run", "inherit": false, "rights": ["SetValue","Delete"], "note": "StartupApproved (enable/disable autorun)"},
{"key": "Software\\Microsoft\\Windows NT\\CurrentVersion\\Windows", "inherit": false, "rights": ["SetValue"], "note": "HKCU Load/Run (T1546.010)"},
{"key": "Software\\Microsoft\\Command Processor", "inherit": false, "rights": ["SetValue"], "note": "HKCU cmd AutoRun (T1546.011)"},
{"key": "Control Panel\\Desktop", "inherit": false, "rights": ["SetValue"], "note": "Scrnsave.exe screensaver hijack (T1546.002)"},
{"key": "Environment", "inherit": false, "rights": ["SetValue"], "note": "UserInitMprLogonScript logon-script persistence (T1037.001)"},
{"key": "Software\\Microsoft\\Ctf\\LangBarAddin", "inherit": true, "rights": ["SetValue","CreateSubKey","Delete"], "note": "HKCU LangBarAddin"},
{"key": "Software\\Microsoft\\Office\\Outlook\\Addins", "inherit": true, "rights": ["CreateSubKey","Delete","SetValue"], "note": "Outlook add-in persistence (T1137.006)"}
],
"user_files": [
{"relpath": "AppData\\Roaming\\Microsoft\\Windows\\Start Menu\\Programs\\Startup", "inherit": true, "rights": ["WriteData","CreateFiles","Delete"], "note": "Startup folder persistence (T1547.001)"},
{"relpath": "AppData\\Roaming\\Signal", "inherit": true, "rights": ["ReadData"], "note": "Signal Desktop sensitive data access (T1005)"}
],
"files": [
{"path": "C:\\Windows\\NTDS", "inherit": true, "rights": ["ReadData","WriteData","Delete","ChangePermissions","TakeOwnership"], "note": "AD database dir - ntds.dit theft (T1003.003)"},
{"path": "C:\\Windows\\System32\\config\\SAM", "inherit": false, "rights": ["ReadData","WriteData","Delete","TakeOwnership"], "note": "SAM hive theft (T1003.002)"},