I'm writing a monitoring service that uses WMI to get information from remote machines. Having local admin rights on all these machines is not possible for political reasons.
Is this possible? What permissions/rights does my user require for this?
I'm writing a monitoring service that uses WMI to get information from remote machines. Having local admin rights on all these machines is not possible for political reasons.
Is this possible? What permissions/rights does my user require for this?
The following works on Window 2003 R2 SP 2, Windows Server 2012 R2
wmimgmt.msc
). In the Security tab, highlight Root/CIMV2
, click Security; add Performance Monitor Users and enable the options : Enable Account
and Remote Enable
dcomcnfg
. At Component Services > Computers > My Computer, in the COM security tab of the Properties dialog click "Edit Limits" for both Access Permissions
and Launch and Activation Permissions
. Add Performance Monitor Users and allow remote access, remote launch, and remote activation.Remote Launch
and Remote Activation
privileges to Performance Monitor Users Group.Notes:
Root
level, and recurse the permissions to the sub-namespaces via the Advanced
window in Security
All I did on Windows 8 was added user to group "Remote Management Users", and remote WQL requests worked.
By default, only the local Administrators group has remote permissions to WMI. You will have to customise the WMI "Remote Enable" permissions.
You may also have to grant "DCOM remote access permissions" and/or "DCOM remote launch and activation permissions" depending on what exactly you are trying to do. This MSDN article gives the step-by-step procedures.
The following worked for me in a 2012 r2 domain environment although I only managed to do it per server and not the entire domain:
1) Add user to Performance Log Users Group. 2) Run wmimgmt.msc, right click "WMI Control (LOCAL), goto Security tab and grant the appropriate user "Enable Account" and "Remote Enable" on the desired namespace (usualy CIMV2).
If I manage to get it done for the entire domain I'll come back and update.
Based on the chosen answer, I modified the script from Microsoft to set the WMI security. My test user was a non-administrative domain user who was a member of the "Remote Management Users" on the local system for reasons not related to this issue. After granting my user the EnableAccount, RemoteEnable, and ExecuteMethods permissions on the target namespace, I was able to access WMI.
So, I did not add my user to the Performance Monitor Users or Distributed COM Users local groups.
A couple of notes regarding the script:
$OBJECT_INHERIT_ACE_FLAG
The script is below. I named it Set-WMINamespaceSsecurity.ps1
Param ([Parameter(Mandatory=$true,Position=0)] [string]$Namespace,
[Parameter(Mandatory=$true,Position=1)] [ValidateSet("Add","Remove")] [string]$Operation,
[Parameter(Mandatory=$true,Position=2)] [string] $Account,
[Parameter(Mandatory=$false,Position=3)] [ValidateSet("EnableAccount","ExecuteMethods","FullWrite","PartialWrite","ProviderWrite","RemoteEnable","ReadSecurity","WriteSecurity")] [string[]] $Permissions=$null,
[Parameter(Mandatory=$false)] [switch]$AllowInherit,
[Parameter(Mandatory=$false)] [switch]$Deny,
[Parameter(Mandatory=$false)] [string]$ComputerName=".",
[Parameter(Mandatory=$false)] [System.Management.Automation.PSCredential]$Credential=$null)
$OBJECT_INHERIT_ACE_FLAG = 0x1
$CONTAINER_INHERIT_ACE_FLAG = 0x2
$ACCESS_ALLOWED_ACE_TYPE = 0x0
$ACCESS_DENIED_ACE_TYPE = 0x1
$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_S_SUBJECT_TO_SDS = 0x43003
$ErrorActionPreference = "Stop"
$InvokeParams=@{Namespace=$Namespace;Path="__systemsecurity=@";ComputerName=$ComputerName}
if ($PSBoundParameters.ContainsKey("Credential")) { $InvokeParams+= @{Credential=$Credential}}
$output = Invoke-WmiMethod @InvokeParams -Name "GetSecurityDescriptor"
if ($output.ReturnValue -ne 0) { throw "GetSecurityDescriptor failed: $($output.ReturnValue)" }
$ACL = $output.Descriptor
if ($Account.Contains('\')) {
$Domain=$Account.Split('\')[0]
if (($Domain -eq ".") -or ($Domain -eq "BUILTIN")) { $Domain = $ComputerName }
$AccountName=$Account.Split('\')[1]
}
elseif ($Account.Contains('@')) {
$Somain=$Account.Split('@')[1].Split('.')[0]
$AccountName=$Account.Split('@')[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" }
# Add Operation
if ($Operation -eq "Add") {
if ($Permissions -eq $null) { throw "Permissions must be specified for an add operation" }
# Construct AccessMask
$AccessMask=0
$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="EnableAccount","ExecuteMethods","FullWrite","PartialWrite","ProviderWrite","RemoteEnable","ReadSecurity","WriteSecurity"
$PermissionTable=@{}
for ($i=0; $i -lt $WBEM_RIGHTS_FLAGS.Count; $i++) { $PermissionTable.Add($WBEM_RIGHTS_STRINGS[$i].ToLower(), $WBEM_RIGHTS_FLAGS[$i]) }
foreach ($Permission in $Permissions) { $AccessMask+=$PermissionTable[$Permission.ToLower()] }
$ACE=(New-Object System.Management.ManagementClass("Win32_Ace")).CreateInstance()
$ACE.AccessMask=$AccessMask
# Do not use $OBJECT_INHERIT_ACE_FLAG. There are no leaf objects here.
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
}
#Remove Operation
else {
if ($Permissions -ne $null) { Write-Warning "Permissions are ignored for a remove operation" }
[System.Management.ManagementBaseObject[]]$newDACL = @()
foreach ($ACE in $ACL.DACL) {
if ($ACE.Trustee.SidString -ne $Win32Account.SID) { $newDACL+=$ACE }
}
$ACL.DACL = $newDACL
}
$SetParams=@{Name="SetSecurityDescriptor"; ArgumentList=$ACL}+$InvokeParams
$output = Invoke-WmiMethod @SetParams
if ($output.ReturnValue -ne 0) { throw "SetSecurityDescriptor failed: $($output.ReturnValue)" }
Nothing here worked for me. I found a YT vid in conjunction with an arbitrary comment that solved it for me (& hopefully for you, too), but only when using invoke-command
(ex. invoke-command -ComputerName MyRemoteComputer -ScriptBlock {Get-Process -Name explorer}
).
On the PC you want to remotely access (on same domain):
Run
> lusrmgr.msc
(on Domain Controllers: dsa.msc
)Groups
folder] (on Domain Controllers: Builtin
folder)Distributed COM Users
] > Add to [a] group...
> Add...
Check Names
(to confirm it's the right group/user) > OK
Why does adding the user/group to the Distributed COM Users
group help? Well, that group has privileges to launch applications & objects remotely under COM Security
settings. You can view these privileges with: [Right-click Start] > Run
> DCOMcnfg
> Component Services
> Computers
> [Right-click My Computer
] > Properties
> COM Security
> Edit Limits...
Set-PSSessionConfiguration -ShowSecurityDescriptorUI -Name Microsoft.PowerShell
Add...
> [Search the user/group you want to grant WMI access to] > Check Names
(to confirm it's the right group/user) > OK
Allow
column under Permissions for MyUser
, I only selected the Read(Get,Enumerate,Subscribe)
and Execute(Invoke)
options (since I was granting these privileges to all Domain Users
).Apply
> OK
Run
> services.msc
Restart
both Windows Management Instrumentation
and Windows Remote Management (WS-Management)
.Startup type
s to Automatic
--if not already--in [Right-click] > Properties
.)Windows Defender Firewall with Advanced Security
and [Right-click] > Enable
each Windows Management Instrumentation
Inbound Rule
.If you are trying to access WMI there are two protocols available: DCOM and WinRM. Which protocol you are using will depend on the tools or API used. For example, when you are using PowerShell, the 'older' Get-WmiObject cmdlet uses DCOM, whereas the 'newer' Get-CimInstance cmdlet uses WinRM.
To access WMI as a non-administrator using DCOM you need the following groups / permissions
To access WMI as a non-administrator using WinRM you need the following groups / permissions
Hopefully it goes without saying that to do this remotely you need the 'Windows Management Instrumentation' rules enabled in Windows Defender Firewall.
(You can also use the 'Performance Log Users' group to assign DCOM and WMI performance metric permissions in place of 'Distributed COM Users' and 'Performance Monitor Users', but this group has additional privileges that may not be appropriate for it to grant, or set up the DCOM Remote Launch and Activation Permissions manually as suggested in other answers, but that seems an overly complicated process.)
We did this for PRTG: We created a new domain user: Created a GPO Dit to put his user in the group "Performnce Log Users" and used a powershell script to add this user to WMI Control. thanks to: