Set WMI Namespace Sec-Win2003-2008-Remotely Many servers

This topic contains 4 replies, has 3 voices, and was last updated by Profile photo of Richard Siddaway Richard Siddaway 3 years, 7 months ago.

  • Author
    Posts
  • #11410
    Profile photo of Jake Sully
    Jake Sully
    Participant

    Howdy – I posted a question here last week and found out that what I was trying to use for a script that I found MS posted was not valid for Windows 2003 because the Security Descriptor is not available. Instead of wasting anyone's time I thought a new request for help would be better.

    I wanted to ask anyone if they could help me with a new script that would do what I need to set WMI Namespace permissions for a service account on root\cimv2 and if possible do this on 2003, 2008, 2008r2, and even 2012 if that's possible?

    I have tried doing things found in several articles and haven't had any luck at all. The best thing I found was the script below which states it works on 2003 but I haven't tested it because I want to remove the items it sets for DCOM permissions but I'm not sure what they are? Then if I remove them I'm sure I'll break the WMI portion which I need. Can someone help me possibly set this so it only sets the permissions required on root\cimv2 for servers, I have the systems in a list, obviously I can use csv or txt, but I was thinking it would be great to run this against the domain and do a search for 2003, 2008, 2008r2, and then based on the results run the proper commands to set the permissions using the right commands. The service account is for a monitoring application and it states that the WMI access required is:
    Enable Account
    Remote Enable

    For the groups it has to be a member of dist com users, perf log users, and per mon users, but I'm using a gpo for that part. For standalone servers I wanted to have this script either determine the domain or even a separate script that would create a regular "user" account on the system, set the pwd, set it to never expire, set it to "user cant change pwd", and then add it to the groups. What's the best way to handle these systems?

    function get-sid
    {
    Param (
    $DSIdentity
    )
    $ID = new-object System.Security.Principal.NTAccount($DSIdentity)
    return $ID.Translate( [System.Security.Principal.SecurityIdentifier] ).toString()
    }
    $sid = get-sid "local\maxsmart"
    $SDDL = "A;;CCWP;;;$sid"
    $DCOMSDDL = "A;;CCDCRP;;;$sid"
    $computers = Get-Content "computers.txt"
    foreach ($strcomputer in $computers)
    {
    $Reg = [WMIClass]"\\$strcomputer\root\default:StdRegProv"
    $DCOM = $Reg.GetBinaryValue(2147483650,"software\microsoft\ole","MachineLaunchRestriction").uValue
    $security = Get-WmiObject -ComputerName $strcomputer -Namespace root/cimv2 -Class __SystemSecurity
    $converter = new-object system.management.ManagementClass Win32_SecurityDescriptorHelper
    $binarySD = @($null)
    $result = $security.PsBase.InvokeMethod("GetSD",$binarySD)
    $outsddl = $converter.BinarySDToSDDL($binarySD[0])
    $outDCOMSDDL = $converter.BinarySDToSDDL($DCOM)
    $newSDDL = $outsddl.SDDL += "(" + $SDDL + ")"
    $newDCOMSDDL = $outDCOMSDDL.SDDL += "(" + $DCOMSDDL + ")"
    $WMIbinarySD = $converter.SDDLToBinarySD($newSDDL)
    $WMIconvertedPermissions = ,$WMIbinarySD.BinarySD
    $DCOMbinarySD = $converter.SDDLToBinarySD($newDCOMSDDL)
    $DCOMconvertedPermissions = ,$DCOMbinarySD.BinarySD
    $result = $security.PsBase.InvokeMethod("SetSD",$WMIconvertedPermissions)
    $result = $Reg.SetBinaryValue(2147483650,"software\microsoft\ole","MachineLaunchRestriction", $DCOMbinarySD.binarySD)
    }

  • #11435
    Profile photo of Don Jones
    Don Jones
    Keymaster

    So.. I'm sorry, I don't think I'm following what the question is.

    How do I ________?

    Fill in the blank?

  • #11464
    Profile photo of Jake Sully
    Jake Sully
    Participant

    Don –
    Your response is much appreciated

    "How do I modify the script above to remove the parts that set the "DCOM" permissions?

    "How do I set the WMI namespace permissions on root\cimv2 for the required 2 permissions, Remote Enable, Enable Account"?

    How can I search the AD domain for the OS version and run this on 2003 servers and then what will work to set the same permissions on 2008/2008r/, and 2012? What I would like to do is have 1 script that could be run against either a list of servers or modified to search AD for server OS types, detect the version and then set the permissions. As I mentioned, I don't want to modify the DCOM access when I'm adding the account to the DCOM users group as that's redundant, and a gpo is a better method to centralize the permissions.

    I did find a script I posed in the 1st post which works on 2008/2008r2 but not on 2003, and I could not find anyway to get it to work on 2003, not combine that with this script which should work on 2003. I have no idea what in this script is setting DCOM access, I've read through it and understand quite a bit, but I can't narrow down the WMI vs DCOM settings being applied in terms of what is needed to set WMI access.

    By the way, I just joined CBT and your new videos are great!! I've gotten many scripts written, although basic, they work and when I share them they are apparently done right and commented well, so I'm learning!

  • #11469
    Profile photo of Don Jones
    Don Jones
    Keymaster

    So, the one thing I can probably help with is getting the OS version. AD obviously keeps that in an attribute, and if you're using Get-ADComputer, you can specify a -Filter or -LdapFilter that limits the results to just those computers of a particular OS. Or, you can use -Property to make sure that attribute comes down in the results, and then filter it in a Where clause, or build a Switch construct to take a different action for each OS.

    The other two, dunno – but I've asked our resident WMI expert to have a look at this topic.

    And thanks for joining CBT ;). They're great to work with from my end, and a big chunk of your fee really helps us trainers pay the mortgage, so it's very much appreciated.

  • #11498
    Profile photo of Richard Siddaway
    Richard Siddaway
    Moderator

    I think the best way to approach this is to try and step through the code determining what each line, or group of lines, does.


    function get-sid {
    Param ( $DSIdentity )
    $ID = new-object System.Security.Principal.NTAccount($DSIdentity)
    return $ID.Translate( [System.Security.Principal.SecurityIdentifier] ).toString()
    }
    $sid = get-sid "local\maxsmart"

    This defines a function to get the SID of an account which looks something like this
    S-1-5-21-2408039147-2416000835-5500772448-1009

    $SDDL = "A;;CCWP;;;$sid"
    $DCOMSDDL = "A;;CCDCRP;;;$sid"

    Are Security Dexcriptor Definition Language ACE definitions where
    A = allow
    CC = create child
    WP = write property
    DC = delete child
    RP = read property

    More info can be found here http://msdn.microsoft.com/en-us/library/aa374928(v=vs.85).aspx

    $computers = Get-Content "computers.txt"
    foreach ($strcomputer in $computers) {

    reads a list of computers and loops through them

    $Reg = [WMIClass]"\\$strcomputer\root\default:StdRegProv"
    $DCOM = $Reg.GetBinaryValue(2147483650,"software\microsoft\ole","MachineLaunchRestriction").uValue

    "creates" an instance of the StdRegprov class to read the registry and reads the given key
    this part appears to be for DCOM

    $security = Get-WmiObject -ComputerName $strcomputer -Namespace root/cimv2 -Class __SystemSecurity

    gets the __SystemSecurity class which is used for setting permissions on a namespace see:
    http://msdn.microsoft.com/en-us/library/aa394677(v=vs.85).aspx

    $converter = new-object system.management.ManagementClass Win32_SecurityDescriptorHelper

    creates an instance of the Win32_SecurityDescriptorHelper helper class – could probably have used [wmiclass] here as well

    $binarySD = @($null)
    creates an empty array – using $null doesn't add anything – could just use @()

    $result = $security.PsBase.InvokeMethod("GetSD",$binarySD)
    Use the GetSD method of __SystemSecurity class to populate the array with the security descriptor data. A much neater way to do this is:
    Invoke-WmiMethod -Class __SystemSecurity -Name GetSD | select -ExpandProperty SD

    $outsddl = $converter.BinarySDToSDDL($binarySD[0])
    $outDCOMSDDL = $converter.BinarySDToSDDL($DCOM)
    $newSDDL = $outsddl.SDDL += "(" + $SDDL + ")"
    $newDCOMSDDL = $outDCOMSDDL.SDDL += "(" + $DCOMSDDL + ")"

    convert the SD to SSDL and add the extra permissions

    $WMIbinarySD = $converter.SDDLToBinarySD($newSDDL)
    $WMIconvertedPermissions = ,$WMIbinarySD.BinarySD
    $DCOMbinarySD = $converter.SDDLToBinarySD($newDCOMSDDL)
    $DCOMconvertedPermissions = ,$DCOMbinarySD.BinarySD

    convert the permissions back

    $result = $security.PsBase.InvokeMethod("SetSD",$WMIconvertedPermissions)
    $result = $Reg.SetBinaryValue(2147483650,"software\microsoft\ole","MachineLaunchRestriction", $DCOMbinarySD.binarySD)

    set the permissions

    If you read through the code you will see that there are two strands to the processing – one modifies the registry for the DCOM setting and the other works on the name space

    If I've understood your need correctly you want to just modify the setting on the namespace. I've commented out the lines in your code that for the DCOM modification.

    PLEASE TEST THIS VERY, VERY, VERY CAREFULLY

    function get-sid {
    Param ( $DSIdentity )
    $ID = new-object System.Security.Principal.NTAccount($DSIdentity)
    return $ID.Translate( [System.Security.Principal.SecurityIdentifier] ).toString()
    }
    $sid = get-sid "local\maxsmart"
    $SDDL = "A;;CCWP;;;$sid"
    #$DCOMSDDL = "A;;CCDCRP;;;$sid"

    $computers = Get-Content "computers.txt"
    foreach ($strcomputer in $computers) {
    #$Reg = [WMIClass]"\\$strcomputer\root\default:StdRegProv"
    #$DCOM = $Reg.GetBinaryValue(2147483650,"software\microsoft\ole","MachineLaunchRestriction").uValue
    $security = Get-WmiObject -ComputerName $strcomputer -Namespace root/cimv2 -Class __SystemSecurity
    $converter = new-object system.management.ManagementClass Win32_SecurityDescriptorHelper
    $binarySD = @($null)
    $result = $security.PsBase.InvokeMethod("GetSD",$binarySD)
    $outsddl = $converter.BinarySDToSDDL($binarySD[0])
    #$outDCOMSDDL = $converter.BinarySDToSDDL($DCOM)
    $newSDDL = $outsddl.SDDL += "(" + $SDDL + ")"
    #$newDCOMSDDL = $outDCOMSDDL.SDDL += "(" + $DCOMSDDL + ")"
    $WMIbinarySD = $converter.SDDLToBinarySD($newSDDL)
    $WMIconvertedPermissions = ,$WMIbinarySD.BinarySD
    #$DCOMbinarySD = $converter.SDDLToBinarySD($newDCOMSDDL)
    #$DCOMconvertedPermissions = ,$DCOMbinarySD.BinarySD
    $result = $security.PsBase.InvokeMethod("SetSD",$WMIconvertedPermissions)
    #$result = $Reg.SetBinaryValue(2147483650,"software\microsoft\ole","MachineLaunchRestriction", $DCOMbinarySD.binarySD)
    }

    PLEASE TEST THIS VERY, VERY, VERY CAREFULLY
    DISCLAIMER
    This isn't something that I normally modify so I'm making a number of assumptions. Modifying permissions on WMI namespaces can have an adverse effect on your machine. The code is supplied as is with no warranty

You must be logged in to reply to this topic.