diff --git a/Examples/Example-00-GPOPermissionTypes.ps1 b/Examples/Example-00-GPOPermissionTypes.ps1 new file mode 100644 index 0000000..0672e6e --- /dev/null +++ b/Examples/Example-00-GPOPermissionTypes.ps1 @@ -0,0 +1,24 @@ +$GPPermissions = [ordered] @{ + GpoApply = 'The trustee can apply the GPO; corresponds to the READ and APPLY Group Policy access rights being set to "Allow" for a user.' + GpoCustom = 'The trustee has custom permissions for the GPO.' + GpoEdit = 'The trustee can read and edit the policy settings for the GPO; corresponds to the READ, WRITE, CREATE CHILD OBJECT, and DELETE CHILD OBJECT Group Policy access rights set to "Allow" for a user.' + GpoEditDeleteModifySecurity = 'The trustee can read, edit and delete the permissions for the GPO; corresponds to the Group Policy access rights specified by GpoEdit plus the DELETE, MODIFY PERMISSIONS, and MODIFY OWNER access rights set to "Allow" for a user.' + GpoRead = 'The trustee can read the GPO; corresponds to the READ Group Policy access right set to "Allow" for a user.' + None = 'This value is reserved for internal use by the Group Policy Windows PowerShell cmdlets.' + SomCreateGpo = 'The trustee can create GPOs in the domain. Applies to domains only.' + SomCreateStarterGpo = 'The trustee can create Starter GPOs in the domain. Applies to domains only.' + SomCreateWmiFilter = 'The trustee can create WMI filters in the domain. Applies to domains only.' + SomLink = 'The trustee can link GPOs to the SOM. Applies to sites, domains and OUs.' + SomLogging = 'The trustee can generate RSoP logging data for the SOM. Applies to domains and OUs.' + SomPlanning = 'The trustee can generate RSoP planning data for the SOM. Applies to domains and OUs.' + SomWmiFilterFullControl = 'The trustee has full control over all WMI filters in the domain. Applies to domains only.' + StarterGpoCustom = 'The trustee has custom permissions for the Starter GPO.' + StarterGpoEdit = 'The trustee can read and edit the administrative template policy settings for the Starter GPO; corresponds to the READ, WRITE, CREATE CHILD OBJECT, and DELETE CHILD OBJECT Group Policy access rights set to "Allow" for a user.' + StarterGpoFullControl = 'The trustee has full control for the Starter GPO. Applies to domains only.' + StarterGpoRead = 'The trustee can read the Starter GPO; corresponds to the READ Group Policy access right set to "Allow" for a user.' + WmiFilterCustom = 'The trustee has custom permissions for the WMI filter.' + WmiFilterEdit = 'The trustee can edit the WMI filter.' + WmiFilterFullControl = 'The trustee has full control over the WMI filter.' +} + +$GPPermissions | Format-Table \ No newline at end of file diff --git a/Examples/Example-08-ListingPermissions.ps1 b/Examples/Example-08-ListingPermissions.ps1 index 3e7d22d..38c8148 100644 --- a/Examples/Example-08-ListingPermissions.ps1 +++ b/Examples/Example-08-ListingPermissions.ps1 @@ -1,17 +1,5 @@ Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force -#$GPOS = Get-GPOZaurr -#$GPOS | Format-Table -AutoSize - -#$GPOS[0] | Format-List - -#$GPOs[0].ACL | Format-Table -AutoSize - -#Get-GPOZaurrPermissions | Format-Table -AutoSize -$T = Get-GPOZaurrPermission #| Out-HtmlView -#$T[0] | Format-List * +$T = Get-GPOZaurrPermission #-SkipWellKnown #-SkipAdministrative # -ExcludePermissionType GpoRead,GpoApply #| Out-HtmlView $T | Format-Table -AutoSize * -#$T[0].Trustee -#$T[0].Permission -#$T[0] -$T | Out-HtmlView -ScrollX -Filtering -Online -DisablePaging \ No newline at end of file +#$T | Out-HtmlView -ScrollX -Filtering -Online -DisablePaging \ No newline at end of file diff --git a/Examples/Example-09-RemovingGPOPermission.ps1 b/Examples/Example-09-RemovingGPOPermissionUnknown.ps1 similarity index 50% rename from Examples/Example-09-RemovingGPOPermission.ps1 rename to Examples/Example-09-RemovingGPOPermissionUnknown.ps1 index 9627b20..0d976e6 100644 --- a/Examples/Example-09-RemovingGPOPermission.ps1 +++ b/Examples/Example-09-RemovingGPOPermissionUnknown.ps1 @@ -1,3 +1,3 @@ Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force -Remove-GPOZaurrPermission -Verbose \ No newline at end of file +Remove-GPOZaurrPermission -Verbose -Type Unknown -WhatIf \ No newline at end of file diff --git a/Examples/Example-09-RemovingGPOpermissionNamed.ps1 b/Examples/Example-09-RemovingGPOpermissionNamed.ps1 new file mode 100644 index 0000000..a4d49d4 --- /dev/null +++ b/Examples/Example-09-RemovingGPOpermissionNamed.ps1 @@ -0,0 +1,13 @@ +Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force + +$Named = @( + 'S-1-5-21-853615985-2870445339-3163598659-1105' +) + +# Using exclude permission types (it may not be good idea to delete GPORead/GPOApply) +#Remove-GPOZaurrPermission -Verbose -Type Named -WhatIf -LimitProcessing 2 -NamedObjects $Named -ExcludePermissionType GpoRead,GpoApply + +# But +#Remove-GPOZaurrPermission -Type Named -NamedObjects $Named -IncludePermissionType GpoEditDeleteModifySecurity -SkipWellKnown -SkipAdministrative -Verbose -WhatIf + +Remove-GPOZaurrPermission -Type Named -NamedObjects $Named -SkipWellKnown -SkipAdministrative -Verbose #-WhatIf \ No newline at end of file diff --git a/GPOZaurr.psd1 b/GPOZaurr.psd1 index 47f5b3d..cd3b816 100644 --- a/GPOZaurr.psd1 +++ b/GPOZaurr.psd1 @@ -7,7 +7,7 @@ Description = 'Group Policy Eater' FunctionsToExport = 'Backup-GPOZaurr', 'Get-GPOZaurr', 'Get-GPOZaurrBackupInformation', 'Get-GPOZaurrPassword', 'Get-GPOZaurrPermission', 'Get-GPOZaurrWMI', 'New-GPOZaurrWMI', 'Remove-GPOZaurr', 'Remove-GPOZaurrPermission', 'Remove-GPOZaurrWMI', 'Restore-GPOZaurr', 'Save-GPOZaurrFiles', 'Set-GPOZaurrOwner', 'Set-GPOZaurrWMI' GUID = 'f7d4c9e4-0298-4f51-ad77-e8e3febebbde' - ModuleVersion = '0.0.9' + ModuleVersion = '0.0.10' PowerShellVersion = '5.1' PrivateData = @{ PSData = @{ diff --git a/Private/Get-ADAdministrativeGroups.ps1 b/Private/Get-ADAdministrativeGroups.ps1 index 6337bd5..beb71b4 100644 --- a/Private/Get-ADAdministrativeGroups.ps1 +++ b/Private/Get-ADAdministrativeGroups.ps1 @@ -45,6 +45,7 @@ function Get-ADADministrativeGroups { ) $ADDictionary = [ordered] @{ } $ADDictionary['ByNetBIOS'] = [ordered] @{ } + $ADDictionary['BySID'] = [ordered] @{ } $ForestInformation = Get-WinADForestDetails -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -ExtendedForestInformation $ExtendedForestInformation foreach ($Domain in $ForestInformation.Domains) { @@ -56,12 +57,14 @@ function Get-ADADministrativeGroups { Get-ADGroup -Filter "SID -eq '$($DomainInformation.DomainSID)-512'" -Server $QueryServer -ErrorAction SilentlyContinue | ForEach-Object { $ADDictionary['ByNetBIOS']["$($DomainInformation.NetBIOSName)\$($_.Name)"] = $_ $ADDictionary[$Domain]['DomainAdmins'] = "$($DomainInformation.NetBIOSName)\$($_.Name)" + $ADDictionary['BySID'][$_.SID.Value] = $_ } } if ($Type -contains 'EnterpriseAdmins') { Get-ADGroup -Filter "SID -eq '$($DomainInformation.DomainSID)-519'" -Server $QueryServer -ErrorAction SilentlyContinue | ForEach-Object { $ADDictionary['ByNetBIOS']["$($DomainInformation.NetBIOSName)\$($_.Name)"] = $_ $ADDictionary[$Domain]['EnterpriseAdmins'] = "$($DomainInformation.NetBIOSName)\$($_.Name)" + $ADDictionary['BySID'][$_.SID.Value] = $_ #"$($DomainInformation.NetBIOSName)\$($_.Name)" } } } diff --git a/Public/Get-GPOZaurrPermission.ps1 b/Public/Get-GPOZaurrPermission.ps1 index 84bdafd..308d6c4 100644 --- a/Public/Get-GPOZaurrPermission.ps1 +++ b/Public/Get-GPOZaurrPermission.ps1 @@ -1,16 +1,25 @@ function Get-GPOZaurrPermission { [cmdletBinding()] param( - [switch] $SkipWellKnownGroup, + [string[]]$NamedObjects, + [switch] $SkipWellKnown, + [switch] $SkipAdministrative, + [alias('ForestName')][string] $Forest, [string[]] $ExcludeDomains, [alias('Domain', 'Domains')][string[]] $IncludeDomains, - [System.Collections.IDictionary] $ExtendedForestInformation + [System.Collections.IDictionary] $ExtendedForestInformation, + + [alias('Unknown', 'All')][string[]] $Type = 'All', + [switch] $IncludeOwner, + [Microsoft.GroupPolicy.GPPermissionType[]] $IncludePermissionType, + [Microsoft.GroupPolicy.GPPermissionType[]] $ExcludePermissionType, + [switch] $IncludeGPOObject ) Begin { - if ($Type -contains 'NonAdministrative') { + # if ($Type -contains 'NonAdministrative') { $ADAdministrativeGroups = Get-ADADministrativeGroups -Type DomainAdmins, EnterpriseAdmins -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -ExtendedForestInformation $ExtendedForestInformation - } + #} #$Count = 0 } Process { @@ -20,9 +29,31 @@ Get-GPO -All -Domain $Domain -Server $QueryServer | ForEach-Object -Process { $GPO = $_ Write-Verbose "Get-GPOZaurrPermission - Processing $($GPO.DisplayName) from $($GPO.DomainName)" - Get-GPPermissions -Guid $GPO.ID -DomainName $GPO.DomainName -All -Server $QueryServer | ForEach-Object -Process { + $SecurityRights = $GPO.GetSecurityInfo() + $SecurityRights | ForEach-Object -Process { + #Get-GPPermissions -Guid $GPO.ID -DomainName $GPO.DomainName -All -Server $QueryServer | ForEach-Object -Process { $GPOPermission = $_ - [PSCustomObject] @{ + if ($ExcludePermissionType -contains $GPOPermission.Permission) { + return + } + if ($IncludePermissionType) { + if ($IncludePermissionType -notcontains $GPOPermission.Permission) { + return + } + } + if ($SkipWellKnown.IsPresent) { + if ($GPOPermission.Trustee.SidType -eq 'WellKnownGroup') { + return + } + } + if ($SkipAdministrative.IsPresent) { + $IsAdministrative = $ADAdministrativeGroups['BySID'][$GPOPermission.Trustee.Sid.Value] + if ($IsAdministrative) { + return + } + } + + $ReturnObject = [ordered] @{ DisplayName = $GPO.DisplayName # : ALL | Enable RDP GUID = $GPO.ID DomainName = $GPO.DomainName # : ad.evotec.xyz @@ -35,41 +66,57 @@ Domain = $GPOPermission.Trustee.Domain #: EVOTEC DistinguishedName = $GPOPermission.Trustee.DSPath #: CN = Domain Admins, CN = Users, DC = ad, DC = evotec, DC = xyz Name = $GPOPermission.Trustee.Name #: Domain Admins - Sid = $GPOPermission.Trustee.Sid #: S - 1 - 5 - 21 - 853615985 - 2870445339 - 3163598659 - 512 + Sid = $GPOPermission.Trustee.Sid.Value #: S - 1 - 5 - 21 - 853615985 - 2870445339 - 3163598659 - 512 SidType = $GPOPermission.Trustee.SidType #: Group + } + if ($IncludeGPOObject) { + $ReturnObject.GPOObject = $GPO + $ReturnObject.GPOSecurity = $SecurityRights + } + [PSCustomObject] $ReturnObject } - if ($GPO.Owner) { - $SplittedOwner = $GPO.Owner.Split('\') - $DomainOwner = $SplittedOwner[0] #: EVOTEC - $DomainUserName = $SplittedOwner[1] #: Domain Admins - $SID = $ADAdministrativeGroups['ByNetBIOS']["$($GPO.Owner)"].Sid - if ($SID) { - $SIDType = 'Group' + if ($IncludeOwner.IsPresent) { + if ($GPO.Owner) { + $SplittedOwner = $GPO.Owner.Split('\') + $DomainOwner = $SplittedOwner[0] #: EVOTEC + $DomainUserName = $SplittedOwner[1] #: Domain Admins + $SID = $ADAdministrativeGroups['ByNetBIOS']["$($GPO.Owner)"].Sid.Value + if ($SID) { + $SIDType = 'Group' + $DistinguishedName = $ADAdministrativeGroups['ByNetBIOS']["$($GPO.Owner)"].DistinguishedName + } else { + $SIDType = '' + $DistinguishedName = '' + } } else { + $DomainOwner = $GPO.Owner + $DomainUserName = '' + $SID = '' $SIDType = '' + $DistinguishedName = '' } - } else { - $DomainOwner = $GPO.Owner - $DomainUserName = '' - $SID = '' - $SIDType = '' - } - [PSCustomObject] @{ - DisplayName = $GPO.DisplayName # : ALL | Enable RDP - GUID = $GPO.GUID - DomainName = $GPO.DomainName # : ad.evotec.xyz - Enabled = $GPO.GpoStatus - Description = $GPO.Description - CreationDate = $GPO.CreationTime - ModificationTime = $GPO.ModificationTime - Permission = 'GpoOwner' # : GpoEditDeleteModifySecurity - Inherited = $false # : False - Domain = $DomainOwner - DistinguishedName = '' #: CN = Domain Admins, CN = Users, DC = ad, DC = evotec, DC = xyz - Name = $DomainUserName - Sid = $SID #: S - 1 - 5 - 21 - 853615985 - 2870445339 - 3163598659 - 512 - SidType = $SIDType # #: Group + $ReturnObject = [ordered] @{ + DisplayName = $GPO.DisplayName # : ALL | Enable RDP + GUID = $GPO.GUID + DomainName = $GPO.DomainName # : ad.evotec.xyz + Enabled = $GPO.GpoStatus + Description = $GPO.Description + CreationDate = $GPO.CreationTime + ModificationTime = $GPO.ModificationTime + Permission = 'GpoOwner' # : GpoEditDeleteModifySecurity + Inherited = $false # : False + Domain = $DomainOwner + DistinguishedName = $DistinguishedName #: CN = Domain Admins, CN = Users, DC = ad, DC = evotec, DC = xyz + Name = $DomainUserName + Sid = $SID #: S - 1 - 5 - 21 - 853615985 - 2870445339 - 3163598659 - 512 + SidType = $SIDType # #: Group + } + if ($IncludeGPOObject) { + $ReturnObject.GPOObject = $GPO + $ReturnObject.GPOSecurity = $SecurityRights + } + [PSCustomObject] $ReturnObject } } } diff --git a/Public/Remove-GPOZaurrPermission.ps1 b/Public/Remove-GPOZaurrPermission.ps1 index b3e6d46..e196eb9 100644 --- a/Public/Remove-GPOZaurrPermission.ps1 +++ b/Public/Remove-GPOZaurrPermission.ps1 @@ -1,13 +1,72 @@ function Remove-GPOZaurrPermission { - [cmdletBinding()] + [cmdletBinding(SupportsShouldProcess)] param( - [string] $Type, + [alias('Unknown', 'Named')][string[]] $Type, + [Microsoft.GroupPolicy.GPPermissionType[]] $IncludePermissionType, + [Microsoft.GroupPolicy.GPPermissionType[]] $ExcludePermissionType, + [switch] $SkipWellKnown, + [switch] $SkipAdministrative, + + [string[]]$NamedObjects, + [alias('ForestName')][string] $Forest, [string[]] $ExcludeDomains, [alias('Domain', 'Domains')][string[]] $IncludeDomains, - [System.Collections.IDictionary] $ExtendedForestInformation + [System.Collections.IDictionary] $ExtendedForestInformation, + + [int] $LimitProcessing ) - Get-GPOZaurrPermission -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -ExtendedForestInformation $ExtendedForestInformation | ForEach-Object -Process { - Write-Verbose "Remove-GPOZaurrPermission - Test" + Begin { + $Count = 0 + } + Process { + if ($Type -contains 'Named' -and $NamedObjects.Count -eq 0) { + Write-Warning "Remove-GPOZaurrPermission - When using type Named you need to provide names to remove. Terminating." + return + } + Get-GPOZaurrPermission -IncludeGPOObject -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -ExtendedForestInformation $ExtendedForestInformation -ExcludePermissionType $ExcludePermissionType -IncludePermissionType $IncludePermissionType -SkipWellKnown:$SkipWellKnown.IsPresent -SkipAdministrative:$SkipAdministrative.IsPresent | ForEach-Object -Process { + $GPOPermission = $_ + if ($Type -contains 'Unknown') { + if ($GPOPermission.SidType -eq 'Unknown') { + #Write-Verbose "Remove-GPOZaurrPermission - Removing $($GPOPermission.Sid) from $($GPOPermission.DisplayName) at $($GPOPermission.DomainName)" + if ($PSCmdlet.ShouldProcess($GPOPermission.DisplayName, "Removing $($GPOPermission.Sid) from $($GPOPermission.DisplayName) at $($GPOPermission.DomainName)")) { + $GPOPermission.GPOSecurity.RemoveTrustee($GPOPermission.Sid) + $GPOPermission.GPOObject.SetSecurityInfo($GPOPermission.GPOSecurity) + # Set-GPPPermission doesn't work on Unknown Accounts + $Count++ + if ($Count -eq $LimitProcessing) { + # skipping skips per removed permission not per gpo. + break + } + } + } + } + if ($Type -contains 'Named') { + + if ($Named -contains $GPOPermission.Sid) { + #Write-Verbose "Remove-GPOZaurrPermission - Removing $($GPOPermission.Sid) from $($GPOPermission.DisplayName) at $($GPOPermission.DomainName)" + if ($PSCmdlet.ShouldProcess($GPOPermission.DisplayName, "Removing $($GPOPermission.Sid) from $($GPOPermission.DisplayName) at $($GPOPermission.DomainName)")) { + $GPOPermission.GPOSecurity.RemoveTrustee($GPOPermission.Sid) + $GPOPermission.GPOObject.SetSecurityInfo($GPOPermission.GPOSecurity) + # Set-GPPPermission doesn't work on Unknown Accounts + $Count++ + if ($Count -eq $LimitProcessing) { + # skipping skips per removed permission not per gpo. + break + } + } + + } + + + + } + #Set-GPPermission -PermissionLevel None -TargetName $GPOPermission.Sid -Verbose -DomainName $GPOPermission.DomainName -Guid $GPOPermission.GUID #-WhatIf + #Set-GPPermission -PermissionLevel GpoRead -TargetName 'Authenticated Users' -TargetType Group -Verbose -DomainName $Domain -Guid $_.GUID -WhatIf + + } + } + End { + } } \ No newline at end of file