What are the minimal permissions for WMI access to processes CommandLine?

I have been trying to get a remote listing of running windows processes including their CommandLine/ExecutablePath attribute through WMI as a non-administrator domain user for a monitoring tool. I have succeeded to get a process list using the answer below, but the CommandLine attribute was always empty.

[Which permissions/rights does a user need to have WMI access on remote machines?

Granting the 'debug programs' user right in the local security policy allows access to the CommandLine/ExecutablePath information. But then the monitoring user account could potentially invade processes, not just query information about them. Is there any lesser user right or other way to unlock the CommandLine information? I have used the wmic tool arguments shown below for testing.

wmic /node:"servername" /user:username /password:password PROCESS get name,commandline,executablepath

Thank you in advance for any insight you can give me.


Solution 1:

I have finally managed to work around this issue, by giving an AD group more permissions for the individual services. This way, the monitoring tool might be able to control the services to be monitored, but at least not be able to invade any process running on the target machines. I have used the Powershell script below to accomplish this. You would have to input your own AD group and modify the list of Windows services to cater to your needs. It is possible to run this kind of script through group policy and apply it to a group of servers.

function AddSDDL() {
    Param(
        [Parameter(Mandatory=$True)]
        [string]$Username,
        [Parameter(Mandatory=$True)]
        [string]$Service
    )
    $servicetest = Get-Service | where {$_.name -eq "$service"}
    if (!$servicetest -and $service -ne "scmanager") {
        Write-Host "Service $service does not exist. Please supply the name and not the display name"
        return $false;
    }
    $domain = ($username.split("\"))[0]
    $user = ($username.split("\"))[1]
    $ntaccount = New-Object System.Security.Principal.NTAccount($domain,$user)
    $sid = ($ntaccount.Translate([System.Security.Principal.SecurityIdentifier])).value
    if (!$sid) {
        Write-Host "User $username cannot be resolved to a SID. Does the account exist?"
        return $false;
    }
    $sddl = [string](cmd /c "sc.exe sdshow $service");
    if ($sddl -match $sid) {
        Write-Host "User $username already has some sort of access in the SDDL. Remediate manually"
        return $false;
    }
    if($sddl -match "S:\(") {
        $sddl = $sddl -replace "S:\(","(A;;CCLCLORPRC;;;$sid)S:("
    } elseif($sddl -match "D:" -and $sddl.LastIndexOf(":") -lt 3) {
        $sddl += "(A;;CCLCLORPRC;;;$sid)";
    } else {
        Write-Host "SDDL contains multiple description types like D: and A:, but not S:, remediate manually"
        return $false;
    }
    $sddlCommand = "sc.exe sdset $service $sddl";
    Write-Host($sddlCommand);
    $sddlset = cmd /c $sddlCommand
    if ($sddlset -notlike "*SUCCESS*") {
        Write-Host "Permissions did not set"
        Write-Host "Full error: $sddlset"
    }
    else {
        Write-Host "Permissions set successfully for $username on $service"
    }

    return $true;
}

clear;

# default 2012 R2 scmanager: D:(A;;CC;;;AU)(A;;CCLCRPRC;;;IU)(A;;CCLCRPRC;;;SU)(A;;CCLCRPWPRC;;;SY)(A;;KA;;;BA)(A;;CC;;;AC)S:(AU;FA;KA;;;WD)(AU;OIIOFA;GA;;;WD)
# default 2012 R2 w32time: D:(A;;CCLCSWRPWPDTLOCRRC;;;SY)(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;BA)(A;;CCLCSWLOCRRC;;;IU)(A;;CCLCSWLOCRRC;;;SU)(A;;CCLCSWRPLOCRRC;;;LS)(A;;CCSWWPLORC;;;LS)
# default 2008 R2 scmanager: D:(A;;CC;;;AU)(A;;CCLCRPRC;;;IU)(A;;CCLCRPRC;;;SU)(A;;CCLCRPWPRC;;;SY)(A;;KA;;;BA)S:(AU;FA;KA;;;WD)(AU;OIIOFA;GA;;;WD)
# default 2008 R2 w3svc: D:(A;;CCLCSWRPWPDTLOCRRC;;;SY)(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;BA)(A;;CCLCSWLOCRRC;;;IU)(A;;CCLCSWLOCRRC;;;SU)S:(AU;FA;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;WD)
# default 2008 R2 aspnet_state: D:(A;;CCLCSWRPWPDTLOCRRC;;;SY)(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;BA)(A;;CCLCSWLOCRRC;;;IU)(A;;CCLCSWLOCRRC;;;SU)S:(AU;FA;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;WD)
# with list content (LC), read all properties (RP) and read permissions (RC) for authenticated users: D:(A;;CCLC;;;AU)(A;;CCLCRPRC;;;IU)(A;;CCLCRPRC;;;SU)(A;;CCLCRPWPRC;;;SY)(A;;KA;;;BA)(A;;CC;;;AC)S:(AU;FA;KA;;;WD)(AU;OIIOFA;GA;;;WD)

$serviceNames = @("DHCPServer","TlntSvr","RpcSs","SamSs","DNS","Dnscache","LanmanWorkstation","Netlogon","Kdc","IsmServ","DFSR","W32Time","LanmanServer","WAS","aspnet_state","W3SVC","scmanager");
$serviceNames += Get-Service | Where-Object{$_.Name -like "*sql*"} | ForEach-Object{$_.Name};
$serviceNames += Get-Service | Where-Object{$_.Name -like "*ReportServer*"} | ForEach-Object{$_.Name};
foreach($serviceName in $serviceNames) {
    Write-Host("SDDL of $serviceName before update: ") -NoNewline;
    sc.exe sdshow $serviceName

    $wmiGroup = "YOUR_DOMAN\AD_GROUP_FOR_WMI_MONITORING"
    $modified = AddSDDL -Username $wmiGroup -Service $serviceName;

    if($modified) {
        Write-Host("SDDL of $serviceName after update: ") -NoNewline;
        sc.exe sdshow $serviceName
    }
}