none
Powershell: Права на DCOM и WMI RRS feed

  • Вопрос

  • Добрый день!

    Помогите, пожалуйста, со скриптом для раздачи прав на объекты DCOM и WMI.

    Нужно на всех серверах и потенциально на рабочих станциях добавить для доменной группы безопасности следующие права:

    1) DCOM (dcomcnfg) -> "Components Services -> Computers -> My Computer -> Properties -> COM Security -> Launch and Activation Permissions -> Edit Limits": Remote Activation.
    2) WMI (wmimgmt.msc) -> "WMI Control (Local) -> Properties -> Security -> Root\CIMv2 -> Security": Remote Enable.

    Я находил примеры скриптов, например, для раздачи прав на конкретные приложения DCOM, но как раздать права на корневой объект (My Computer) не ясно.

    15 октября 2018 г. 14:03

Ответы

  • 1. https://unlockpowershell.wordpress.com/2009/11/20/script-remote-dcom-wmi-access-for-a-domain-user/

    Но проще через GPO добавить в локальную группу Distributed COM Users, у которой уже есть требуемые права или DCOM: Machine Access Restrictions in Security Descriptor Definition Language (SDDL) syntax

    2. WMI

    $Namespace = "root\cimv2"
    $systemSecurity = Get-CimInstance -Namespace $Namespace -ClassName __SystemSecurity   
    $oDacl = Invoke-CimMethod -InputObject $systemSecurity -MethodName GetSecurityDescriptor 
    
    $sd = $oDacl.Descriptor
    
    $domain = "Contoso"
    $user = "User1"
    
    $ntuser = New-Object System.Security.Principal.NTAccount($domain,$user) 
    
    $trustee = New-CimInstance -Namespace root/cimv2 -ClassName Win32_Trustee -ClientOnly -Property @{
    	Domain = $domain
    	Name = $user
    	SidString = $ntuser.Translate([Security.Principal.SecurityIdentifier]).Value
    } 
    
    # AceType Allow = 0 Deny = 1
    # AccessMask 35 = Execute Methods,Enable Account,Remote Enable
    
    $ace = New-CimInstance -Namespace root/cimv2 -ClassName Win32_Ace -ClientOnly -Property @{
    	AceType=[uint32]0
    	Trustee=$trustee
    	AccessMask=[uint32]35
    	AceFlags=[uint32]0
    } 
    
    [CIMInstance[]] $nDacl = $null 
    foreach ($iAce in $sd.DACL) { 
    	$nDacl += $iAce
    }
     
    $newDacl += $ace 
    $sd.DACL = $newDacl 
                    
    Invoke-CimMethod -InputObject $systemSecurity -MethodName SetSecurityDescriptor -Arguments @{ 
    	Descriptor = $sd 
    }

    • Помечено в качестве ответа Evgenii Alekseev 16 октября 2018 г. 9:40
    15 октября 2018 г. 15:30
    Отвечающий

Все ответы

  • 1. https://unlockpowershell.wordpress.com/2009/11/20/script-remote-dcom-wmi-access-for-a-domain-user/

    Но проще через GPO добавить в локальную группу Distributed COM Users, у которой уже есть требуемые права или DCOM: Machine Access Restrictions in Security Descriptor Definition Language (SDDL) syntax

    2. WMI

    $Namespace = "root\cimv2"
    $systemSecurity = Get-CimInstance -Namespace $Namespace -ClassName __SystemSecurity   
    $oDacl = Invoke-CimMethod -InputObject $systemSecurity -MethodName GetSecurityDescriptor 
    
    $sd = $oDacl.Descriptor
    
    $domain = "Contoso"
    $user = "User1"
    
    $ntuser = New-Object System.Security.Principal.NTAccount($domain,$user) 
    
    $trustee = New-CimInstance -Namespace root/cimv2 -ClassName Win32_Trustee -ClientOnly -Property @{
    	Domain = $domain
    	Name = $user
    	SidString = $ntuser.Translate([Security.Principal.SecurityIdentifier]).Value
    } 
    
    # AceType Allow = 0 Deny = 1
    # AccessMask 35 = Execute Methods,Enable Account,Remote Enable
    
    $ace = New-CimInstance -Namespace root/cimv2 -ClassName Win32_Ace -ClientOnly -Property @{
    	AceType=[uint32]0
    	Trustee=$trustee
    	AccessMask=[uint32]35
    	AceFlags=[uint32]0
    } 
    
    [CIMInstance[]] $nDacl = $null 
    foreach ($iAce in $sd.DACL) { 
    	$nDacl += $iAce
    }
     
    $newDacl += $ace 
    $sd.DACL = $newDacl 
                    
    Invoke-CimMethod -InputObject $systemSecurity -MethodName SetSecurityDescriptor -Arguments @{ 
    	Descriptor = $sd 
    }

    • Помечено в качестве ответа Evgenii Alekseev 16 октября 2018 г. 9:40
    15 октября 2018 г. 15:30
    Отвечающий
  • Александр, спасибо.

    К сожалению, экспорт/импорт прав на DCOM не совсем подходит. - Некоторые приложения (антивирусы, DLP и т.д.) создают при установке группы/аккаунты для которых добавляют свои разрешения на DCOM.

    Группа "Distributed COM Users" - это слишком много лишних прав. 

    Хочется добавить к существующим правам лишь одну ACL-ку с минимально необходимыми полномочиями.

    Вроде бы и примеры скриптов в Интернете есть:

    https://rkeithhill.wordpress.com/2013/07/25/using-powershell-to-modify-dcom-launch-activation-settings/

    https://gallery.technet.microsoft.com/scriptcenter/Grant-Revoke-Get-DCOM-22da5b96#content

    Но все они заточены под раздачу прав на конкретное приложение (ApplicationID). Как их модифицировать, чтобы добавить разрешение на объект "My Computer" не понятно.

    16 октября 2018 г. 6:17
  • Насчет DCOM почти разобрался:

    Function Get-SID {
        Param ($DSIdentity)
        $ID = new-object System.Security.Principal.NTAccount($DSIdentity)
        Return $ID.Translate( [System.Security.Principal.SecurityIdentifier] ).toString()
    } 
    
    $SID = Get-SID "Domain\EventLogs-over-WMI"
    $DCOMSDDL = "A;;CCRP;;;$SID"
    
    $HKLM = 2147483650
    $Reg = [WMIClass]"\\.\root\default:StdRegProv"
    $DCOM = $Reg.GetBinaryValue($HKLM,"software\microsoft\ole","MachineLaunchRestriction").uValue
    $Converter = New-Object system.management.ManagementClass Win32_SecurityDescriptorHelper
    $outDCOMSDDL = $Converter.BinarySDToSDDL($DCOM)
    $newDCOMSDDL = $outDCOMSDDL.SDDL + "(" + $DCOMSDDL + ")"
    $DCOMbinarySD = $Converter.SDDLToBinarySD($newDCOMSDDL)
    $result = $Reg.SetBinaryValue($HKLM,"software\microsoft\ole","MachineLaunchRestriction", $DCOMbinarySD.binarySD)

    Но остается ещё один вопрос. - Как гарантировать, что в случае каких-нибудь ошибок выполнения скрипта на каких-нибудь серверах в реестр не импортнётся мусор (или данная ветка вообще не заменится пустым значением)?

    16 октября 2018 г. 7:51
  • Но остается ещё один вопрос. - Как гарантировать, что в случае каких-нибудь ошибок выполнения скрипта на каких-нибудь серверах в реестр не импортнётся мусор (или данная ветка вообще не заменится пустым значением)?

    Для этого есть тестевая среда, где можо проверить различные варианты. MachineLaunchRestriction - делать резервную копию параметра. И сделать проверку, что $newDCOMSDDL больше $outDCOMSDDL.SDDL .
    16 октября 2018 г. 8:06
    Отвечающий
  • Александр, ещё раз большое спасибо!

    Итоговый вариант скрипта получился следующим:

    Function Get-SID {
        Param ($DSIdentity)
        $ID = new-object System.Security.Principal.NTAccount($DSIdentity)
        Return $ID.Translate( [System.Security.Principal.SecurityIdentifier] ).toString()
    } 
    
    $SID = Get-SID "Domain\EventLogs-over-WMI"
    $DCOMSDDL = "A;;CCRP;;;$SID" # DCOM: Remote Activation
    $WMISDDL = "A;;WP;;;$SID" # WMI: Remote Enable
    
    $HKLM = 2147483650
    $Reg = [WMIClass]"\\.\root\default:StdRegProv"
    $DCOM = $Reg.GetBinaryValue($HKLM,"software\microsoft\ole","MachineLaunchRestriction").uValue
    $Converter = New-Object system.management.ManagementClass Win32_SecurityDescriptorHelper
    $outDCOMSDDL = $Converter.BinarySDToSDDL($DCOM)
    If ($outDCOMSDDL.SDDL) {
        $newDCOMSDDL = $outDCOMSDDL.SDDL + "(" + $DCOMSDDL + ")"
    }
    Else {
        Exit
    }
    If ($newDCOMSDDL -gt $outDCOMSDDL.SDDL) {
        $DCOMbinarySD = $Converter.SDDLToBinarySD($newDCOMSDDL)
        If ($DCOMbinarySD.BinarySD) { 
            $result = $Reg.SetBinaryValue($HKLM,"software\microsoft\ole","MachineLaunchRestriction", $DCOMbinarySD.BinarySD)
        } 
    }
    
    $WMISecurity = Get-WmiObject -Namespace root/cimv2 -Class __SystemSecurity
    $binWMISD = @($null)
    $result = $WMISecurity.PsBase.InvokeMethod("GetSD",$binWMISD)
    $outWMISDDL = $Converter.BinarySDToSDDL($binWMISD[0])
    If ($outWMISDDL.SDDL) {
        $newWMISDDL = $outWMISDDL.SDDL + "(" + $WMISDDL + ")"
    }
    Else {
        Exit
    }
    If ($newWMISDDL -gt $outWMISDDL.SDDL) {
        $WMIbinarySD = $Converter.SDDLToBinarySD($newWMISDDL)
        If ($WMIbinarySD.BinarySD) {
            $WMIConvertedPermissions = ,$WMIbinarySD.BinarySD # Приводим данные к типу Array
            $result = $WMISecurity.PsBase.InvokeMethod("SetSD", $WMIConvertedPermissions) 
        }
    }

    16 октября 2018 г. 9:40
  • Парни, а не подскажите как при таком способе убирать аккаунты?
    21 октября 2018 г. 15:49
  • Вопрос интересный.

    Если известны права аккаунта, то можно просто заменять строку вида ("A;;CCRP;;;$SID") на пустое значение.

    А вот как сделать, чтобы в SDDL-строке удалялись любые разрешения для указанного objectSID я не нашел.

    Опять вся надежда на Александра (Kazun).

    23 октября 2018 г. 8:08
  • Вроде убрать аккаунт получилось строкой вида:

    (($outDCOMSDDL.SDDL).Split("(") |?{$_ -notmatch "$SID"}) -join ("(")

    23 октября 2018 г. 9:10
  • $newsddl = $outsddl.sddl -replace "\([AD];;\w+;;;$sid\)"

    если наследование включено то "\([AD];\w+;\w+;;;$sid\)"


    ну я такой прихожу и мур, мур, мур!

    25 октября 2018 г. 3:56