mirror of
https://github.com/Yamato-Security/WELA.git
synced 2026-10-23 22:53:00 +02:00
Restrict native WMI writes to SACL and verify privilege cleanup
This commit is contained in:
1 parent
45ab6bcc8c
commit
d7f710c9ad
9 files changed
+115
-11
No files matched your search
@@ -60,7 +60,9 @@ namespace Wela {
|
||||
try {
|
||||
if (changed) {
|
||||
TokenPrivileges ignored; uint required;
|
||||
if (!AdjustTokenPrivileges(token, false, ref previous, (uint)Marshal.SizeOf(typeof(TokenPrivileges)), out ignored, out required)) throw new Win32Exception(Marshal.GetLastWin32Error());
|
||||
bool ok = AdjustTokenPrivileges(token, false, ref previous, (uint)Marshal.SizeOf(typeof(TokenPrivileges)), out ignored, out required);
|
||||
int error = Marshal.GetLastWin32Error();
|
||||
if (!ok || error != 0) throw new Win32Exception(error, "Restoring SeSecurityPrivilege failed; the previous token state could not be verified.");
|
||||
}
|
||||
} finally { CloseHandle(token); token=IntPtr.Zero; }
|
||||
}
|
||||
@@ -155,7 +157,10 @@ function Get-WelaWmiNamespaceSnapshot {
|
||||
# Strings prevent JSON journal depth truncation of nested, unfamiliar ACEs.
|
||||
[pscustomobject]@{ Namespace = $Namespace; DescriptorJson = ConvertTo-WelaWmiJson $data
|
||||
DescriptorMof = $descriptor.GetText([System.Management.TextFormat]::Mof); SaclReadPrivilege = 'SeSecurityPrivilege enabled' }
|
||||
} finally { if ($connection) { $connection.Dispose() }; $privilege.Dispose() }
|
||||
} finally {
|
||||
try { if ($connection) { $connection.Dispose() } }
|
||||
finally { $privilege.Dispose() }
|
||||
}
|
||||
}
|
||||
|
||||
function Set-WelaWmiNamespaceDescriptor {
|
||||
@@ -188,14 +193,21 @@ function Set-WelaWmiNamespaceDescriptor {
|
||||
} finally { $aceClass.Dispose(); $trusteeClass.Dispose() }
|
||||
}
|
||||
$updated.SACL = [System.Management.ManagementBaseObject[]]$aces
|
||||
# Only SE_SACL_PRESENT is added when absent. Every other control bit stays.
|
||||
$updated.ControlFlags = [uint32]$descriptor.ControlFlags -bor [uint32]16
|
||||
# SetSecurityDescriptor treats SE_DACL_PRESENT and non-null Owner/Group
|
||||
# as requests to rewrite access permissions. Omit those fields explicitly
|
||||
# so the provider preserves them, even if another writer races this call.
|
||||
# Complete original fields remain in the journal and read-back comparison.
|
||||
$updated.DACL = $null; $updated.Owner = $null; $updated.Group = $null
|
||||
$updated.ControlFlags = ([uint32]$descriptor.ControlFlags -band [uint32]4294967291) -bor [uint32]16
|
||||
$parameters = $connection.GetMethodParameters('SetSecurityDescriptor')
|
||||
$parameters.Descriptor = $updated
|
||||
$response = $connection.InvokeMethod('SetSecurityDescriptor', $parameters, $null)
|
||||
Assert-WelaWmiReturnCode $response 'SetSecurityDescriptor'
|
||||
'SACL update accepted; full descriptor preservation and audit entries require read-back verification. Event generation is unverified.'
|
||||
} finally { if ($connection) { $connection.Dispose() }; $privilege.Dispose() }
|
||||
} finally {
|
||||
try { if ($connection) { $connection.Dispose() } }
|
||||
finally { $privilege.Dispose() }
|
||||
}
|
||||
}
|
||||
|
||||
function Test-WelaWmiDescriptorPreserved {
|
||||
|
||||
Reference in new issue
Block a user