<#
.Synopsis
A Script for modifying the current security descriptor of a WMI namespace.
.DESCRIPTION
A Script for modifying the current security descriptor of a WMI namespace.
.EXAMPLE
Set-WMINamespaceSecurity.ps1 -namespace root/cimv2 -Account "contoso\AD - Remote WMI Access" -operation Add -permissions Enable
.EXAMPLE
Set-WmiNamespaceSecurity.ps1 root/cimv2 add steve Enable,RemoteAccess
.NOTES
Blog links:
https://blogs.msdn.microsoft.com/wmi/2009/07/20/scripting-wmi-namespace-security-part-1-of-3/
https://blogs.msdn.microsoft.com/wmi/2009/07/23/scripting-wmi-namespace-security-part-2-of-3/
https://blogs.msdn.microsoft.com/wmi/2009/07/27/scripting-wmi-namespace-security-part-3-of-3/
Original Content by Steve Lee
Modified by Graeme Bray
Modified a lot by Jason Eberhardt
#>
Param ([Parameter (Mandatory=$true,ParameterSetName="ADD")]
[Parameter (Mandatory=$true,ParameterSetName="DEL")] [string]$Namespace,
[Parameter (Mandatory=$true,ParameterSetName="ADD")] [switch]$Add,
[Parameter (Mandatory=$true,ParameterSetName="DEL")] [switch]$Delete,
[Parameter (Mandatory=$true,ParameterSetName="ADD")]
[Parameter (Mandatory=$true,ParameterSetName="DEL")] [string]$Account,
[Parameter (Mandatory=$true,ParameterSetName="ADD")] [ValidateSet("PartialWrite","Enable","ProviderWrite","ReadSecurity","WritesSecurity","MethodExecute","RemoteAccess","FullWrite")] [string[]]$Permissions,
[Parameter (Mandatory=$false,ParameterSetName="ADD")] [switch]$AllowInherit,
[Parameter (Mandatory=$false,ParameterSetName="ADD")] [switch]$Deny,
[Parameter (Mandatory=$false,ParameterSetName="ADD")]
[Parameter (Mandatory=$false,ParameterSetName="DEL")] [string]$ComputerName=".",
[Parameter (Mandatory=$false,ParameterSetName="ADD")]
[Parameter (Mandatory=$false,ParameterSetName="DEL")] [System.Management.Automation.PSCredential]$Credential=$null)
Begin {
$ACCESS_ALLOWED_ACE_TYPE=0x0
$ACCESS_DENIED_ACE_TYPE=0x1
$OBJECT_INHERIT_ACE_FLAG=0x1
$CONTAINER_INHERIT_ACE_FLAG=0x2
}
Process {
Function Get-AccessMaskFromPermission($Permissions) {
$WBEM_ENABLE = 0x01
$WBEM_METHOD_EXECUTE = 0x02
$WBEM_FULL_WRITE_REP = 0x04
$WBEM_PARTIAL_WRITE_REP = 0x08
$WBEM_WRITE_PROVIDER = 0x10
$WBEM_REMOTE_ACCESS = 0x20
$WBEM_RIGHT_SUBSCRIBE = 0x40
$WBEM_RIGHT_PUBLISH = 0x80
$READ_CONTROL = 0x20000
$WRITE_DAC = 0x40000
$WBEM_RIGHTS_FLAGS=$WBEM_ENABLE,$WBEM_METHOD_EXECUTE,$WBEM_FULL_WRITE_REP,$WBEM_PARTIAL_WRITE_REP,$WBEM_WRITE_PROVIDER,$WBEM_REMOTE_ACCESS,$READ_CONTROL,$WRITE_DAC
$WBEM_RIGHTS_STRINGS="Enable","MethodExecute","FullWrite","PartialWrite","ProviderWrite","RemoteAccess","ReadSecurity","WriteSecurity"
$PermissionTable=@{}
for ($i=0; $i -lt $WBEM_RIGHTS_FLAGS.Length; $i++) {
$PermissionTable.Add($WBEM_RIGHTS_STRINGS[$i].ToLower(), $WBEM_RIGHTS_FLAGS[$i])
}
$AccessMask=0
foreach ($Permission in $Permissions) {
if (-not $PermissionTable.ContainsKey($Permission.ToLower())) {
throw "Unknown permission: $Permission`nValid permissions: $($PermissionTable.Keys)"
}
$AccessMask+=$PermissionTable[$Permission.ToLower()]
}
$AccessMask
} #Get-AccessMaskFromPermission
if ($PSBoundParameters.ContainsKey("Credential")) {
$RemoteParams=@{ComputerName=$ComputerName;Credential=$Credential}
}
else {$RemoteParams=@{ComputerName=$ComputerName}}
$InvokeParams=@{Namespace=$Namespace;Path="__systemsecurity=@"}+$RemoteParams
$Output=Invoke-WmiMethod @InvokeParams -Name "GetSecurityDescriptor"
if ($Output.ReturnValue -ne 0) {throw "GetSecurityDescriptor failed: $($Output.ReturnValue)" }
$ACL=$Output.Descriptor
if ($ComputerName -eq ".") { $ComputerName=$env:COMPUTERNAME }
Local or NT-style accounts
if ($Account.Contains('')) {
$DomainAccount=$Account.Split('')
$Domain=$DomainAccount[0]
if (($Domain -eq ".") -or ($Domain -eq "BUILTIN")) { $Domain=$ComputerName }
$AccountName=$DomainAccount[1]
}
Modern style accounts
elseif ($Account.Contains('@')) {
$DomainAccount=$Account.Split('@')
$Domain=(Get-ADDomain -Server $DomainAccount[1]).NetBIOSName
$AccountName=$DomainAccount[0]
}
Local accounts only
else {
$Domain=$ComputerName
$AccountName=$Account
}
$SetParams=@{Class="Win32_Account";Filter="Domain='$Domain' and Name='$AccountName'"}+$RemoteParams
$Win32Account=Get-WmiObject @SetParams
if ($Win32Account -eq $null) { throw "Account was not found: $Account" }
if ($Add.IsPresent) {
if ($Permissions -eq $null) { throw "-Permissions must be specified for an add operation" }
$AccessMask=Get-AccessMaskFromPermission($Permissions)
$ACE=(New-Object System.Management.ManagementClass("win32_Ace")).CreateInstance()
$ACE.AccessMask=$AccessMask
if ($AllowInherit.IsPresent) { $ACE.AceFlags=$CONTAINER_INHERIT_ACE_FLAG }
else { $ACE.AceFlags=0 }
$Trustee=(New-Object System.Management.ManagementClass("win32_Trustee")).CreateInstance()
$Trustee.SidString=$Win32Account.Sid
$ACE.Trustee=$Trustee
if ($Deny.IsPresent) { $ACE.AceType=$ACCESS_DENIED_ACE_TYPE }
else { $ACE.AceType=$ACCESS_ALLOWED_ACE_TYPE }
$ACL.DACL += $ace.psobject.immediateBaseObject
}
else {
if ($Permissions -ne $null) { throw "Permissions cannot be specified for a delete operation" }
[System.Management.ManagementBaseObject[]]$newDACL=@()
foreach ($ACE in $ACL.DACL) {
if ($ACE.Trustee.SIDString -ne $Win32Account.SID) { $NewDACL+=$ACE.PSObject.ImmediateBaseObject }
}
$ACL.DACL=$NewDACL.PSObject.ImmediateBaseObject
}
$SetParams=@{Name="SetSecurityDescriptor";ArgumentList=$ACL.PSObject.ImmediateBaseObject}+$InvokeParams
$Output=Invoke-WmiMethod @SetParams
if ($output.ReturnValue -ne 0) { throw "SetSecurityDescriptor failed: $($Output.ReturnValue)" }
}