WMI privileges for a non-administrator user using Powershell

WMI privileges for a non-administrator user using Powershell

Administrators often find themselves working against time. In an environment where the time is of essence, certain day-to-day tasks like password resets, enabling remote access, etc., can be rationed off of technicians. However, technicians are non-admin users and hence will have to be delegated the necessary permissions to get the necessary work done.
 
The following script will help administrators grant WMI privileges to a non-admin user. Provide the username and the required permissions to be granted as parameters and run the script. 

Script
<#
.SYNOPSIS
This script can be used to provide WMI privileges to a non administrator user account.
.DESCRIPTION
This script can be used to provide WMI privileges to a non administrator user account.
.EXAMPLE
C:\PS>.\Set-WmiNamespaceSecurity.ps1 root add nonadmin@mslync10.com Enable,RemoteAccess,MethodExecute,ReadSecurity
Provides execute method, enable account, remote enable and read security for user ‘nonadmin’.
#>

Param ( [parameter(Mandatory=$true,Position=0)][string] $namespace,
[parameter(Mandatory=$true,Position=1)][string] $operation,
[parameter(Mandatory=$true,Position=2)][string] $account,
[parameter(Position=3)][string[]] $permissions = $null,
[bool] $allowInherit = $false,
[bool] $deny = $false,
[string] $computerName = “.”,
[System.Management.Automation.PSCredential] $credential = $null)Process
{
$ErrorActionPreference = “Stop”Function Get-AccessMaskFromPermission($permissions)
{
$WBEM_ENABLE = 1
$WBEM_METHOD_EXECUTE = 2
$WBEM_FULL_WRITE_REP = 4
$WBEM_PARTIAL_WRITE_REP = 8
$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
}
if ($PSBoundParameters.ContainsKey(“Credential”)) {
$remoteparams = @{ComputerName=$computer;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
$OBJECT_INHERIT_ACE_FLAG = 0x1
$CONTAINER_INHERIT_ACE_FLAG = 0x2
$computerName = (Get-WmiObject @remoteparams Win32_ComputerSystem).Name
if ($account.Contains(‘\’)) {
$domainaccount = $account.Split(‘\’)
$domain = $domainaccount[0]
if (($domain -eq “.”) -or ($domain -eq “BUILTIN”)) {
$domain = $computerName
}
$accountname = $domainaccount[1]
}
elseif ($account.Contains(‘@’)) {
$domainaccount = $account.Split(‘@’)
$domain = $domainaccount[1].Split(‘.’)[0]
$accountname = $domainaccount[0]
}
else {
$domain = $computerName
$accountname = $account
}
$getparams = @{Class=”Win32_Account”;Filter=”Domain=’$domain’ and Name=’$accountname'”}
$win32account = Get-WmiObject @getparams
if ($win32account -eq $null) {
throw “Account was not found: $account”
}
switch ($operation) {
“add” {
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) {
$ace.AceFlags = $OBJECT_INHERIT_ACE_FLAG + $CONTAINER_INHERIT_ACE_FLAG
}
else {
$ace.AceFlags = 0
}
$trustee = (New-Object System.Management.ManagementClass(“win32_Trustee”)).CreateInstance()
$trustee.SidString = $win32account.Sid
$ace.Trustee = $trustee$ACCESS_ALLOWED_ACE_TYPE = 0x0
$ACCESS_DENIED_ACE_TYPE = 0x1if ($deny) {
$ace.AceType = $ACCESS_DENIED_ACE_TYPE
}
else {
$ace.AceType = $ACCESS_ALLOWED_ACE_TYPE
}$acl.DACL += $ace.psobject.immediateBaseObject
}
“delete” {
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
}
default {
throw “Unknown operation: $operation`nAllowed operations: add delete”
}
}
$setparams = @{Name=”SetSecurityDescriptor”;ArgumentList=$acl.psobject.immediateBaseObject} + $invokeParams
$output = Invoke-WmiMethod @setparams
if ($output.ReturnValue -ne 0) {
throw “SetSecurityDescriptor failed: $($output.ReturnValue)”
}
}


















































































    • Related Articles

    • How to find unused Exchange Online mailboxes

      What are unused Exchange Online mailboxes and how to identify them? Unused Exchange Online mailboxes are user mailboxes which are currently not being used by their users. There are 3 ways in which we can identify if a mailbox is unused or not. They ...
    • Generate an Activity Report for Microsoft 365 Groups and Teams

      Introduction The activity reports available for Microsoft 365 groups and Teams can be beneficial for administrators in an organization. Microsoft 365 teams group activity reports provide insight into group activities, group workloads, group counts, ...
    • How to Get and Set properties of the Active Directory user using PowerShell

      In this article, we will discuss how to get and set properties of an Active Directory user using PowerShell. Here’s how to get User Properties To get user properties from Active Directory, Get-ADUser cmdlet can be used. Here is an example of how to ...
    • How to get memberships of the Active Directory user using PowerShell

      One of the essential parts of Active Directory administration is to manage user memberships in Active Directory. There may be times when the membership of a specific user need to be identified. In this article, we will explain how to use PowerShell ...
    • Automating Active Directory user creation

      Creating a single Active Directory (AD) account is a simple task. However, in an organization, the number of AD user accounts an administrator would have to create can rise drastically, making the simple task cumbersome. This is where the process of ...