<# This script will modify the defaultSecurityDescriptor attribute on the Group-Policy-Container schema class object, which ensures that a specific set of permissions are applied by default to new Group Policy Objects (GPOs). It's been setup to add groups with either/or: - Modify Permissions - Read Permissions This script was specifically written to overcome the Group Policy security change Microsoft made in security update MS16-072 (KB3163622) by ensuring that Domain Computers is set with default Read permissions. This is the defaultSecurityDescriptor of the Group-Policy-Container class object: D:P(A;CI;RPWPCCDCLCLOLORCWOWDSDDTSW;;;DA)(A;CI;RPWPCCDCLCLOLORCWOWDSDDTSW;;;EA) (A;CI;RPWPCCDCLCLOLORCWOWDSDDTSW;;;CO)(A;CI;RPWPCCDCLCLORCWOWDSDDTSW;;;SY) (A;CI;RPLCLORC;;;AU)(OA;CI;CR;edacfd8f-ffb3-11d1-b41d-00a0c968f939;;AU)(A;CI;LCRPLORC;;;ED) Where... - (A;CI;RPWPCCDCLCLOLORCWOWDSDDTSW;;;DA) = Domain Admins - (A;CI;RPWPCCDCLCLOLORCWOWDSDDTSW;;;EA) = Enterprise Admins - (A;CI;RPWPCCDCLCLOLORCWOWDSDDTSW;;;CO) = Creator Owner - (A;CI;RPWPCCDCLCLORCWOWDSDDTSW;;;SY) = System - (A;CI;RPLCLORC;;;AU) = Authenticated Users - (OA;CI;CR;edacfd8f-ffb3-11d1-b41d-00a0c968f939;;AU) = Authenticated Users - (A;CI;LCRPLORC;;;ED) = Enterprise Domain Controllers This translates to the following: ACE Type: - A = ACCESS ALLOWED - OA = OBJECT ACCESS ALLOWED: ONLY APPLIES TO A SUBSET OF THE OBJECT(S). ACE Flags: - CI = CONTAINER INHERIT: Child objects that are containers, such as directories, inherit the ACE as an explicit ACE. Permissions: - RC = Read Permissions - SD = Delete - WD = Modify Permissions - WO = Modify Owner - RP = Read All Properties - WP = Write All Properties - CC = Create All Child Objects - DC = Delete All Child Objects - LC = List Contents - SW = All Validated Writes - LO = List Object - DT = Delete Subtree - CR = All Extended Rights Trustee: - DA = Domain Admins - EA = Enterprise Admins - CO = Creator Owner - SY = System - AU = Authenticated Users - ED = Enterprise Domain Controllers So we simply need to append these: - (A;CI;RPWPCCDCLCLOLORCWOWDSDDTSW;;;) - (A;CI;LCRPLORC;;;) Some good references to help you understand this further: - http://www.sdmsoftware.com/general-stuff/group-policy-delegation/ - http://support.microsoft.com/kb/321476 - http://clintboessen.blogspot.com/2011/08/ad-delegation-how-to-set-default.html - https://blogs.technet.microsoft.com/askds/2008/04/18/the-security-descriptor-definition-language-of-love-part-1/ - https://blogs.technet.microsoft.com/askds/2008/05/07/the-security-descriptor-definition-language-of-love-part-2/ This script is based on: - A script I originally wrote on 11th November 2011 using the Quest ActiveRoles Snapin Module for a delegated administrative model for a large University. - A script published by Peter Hinchley 10th Oct 2015: Set Default Permissions for New Group Policy Objects http://hinchley.net/2015/10/10/set-default-permissions-for-new-group-policy-objects/ Syntax examples: - To execute the script in report only mode: Modify-GroupPolicyContainer.ps1 - To execute the script and take action: Modify-GroupPolicyContainer.ps1 -Action Script name: Modify-GroupPolicyContainer.ps1 Release 1.2 Written by Jeremy Saunders (jeremy@jhouseconsulting.com) 11th November 2011 Modified by Jeremy Saunders (jeremy@jhouseconsulting.com) 28th June 2016 #> #------------------------------------------------------------- param( [switch]$Action ) # Set Powershell Compatibility Mode Set-StrictMode -Version 2.0 #------------------------------------------------------------- # Set the Read Permissions Group Name. $ReadOnlyGroup = "Domain Computers" # Set the Modify Permissions Group Name. $ModifyGroup = "" # Set this to True to reset the base security descriptor to default settings. $ResetDefault = $False $defaultSecurityDescriptor = @" D:P(A;CI;RPWPCCDCLCLOLORCWOWDSDDTSW;;;DA)(A;CI;RPWPCCDCLCLOLORCWOWDSDDTSW;;;EA)(A;CI;RPWPCCDCLCLOLORCWOWDSDDTSW;;;CO)(A;CI;RPWPCCDCLCLORCWOWDSDDTSW;;;SY)(A;CI;RPLCLORC;;;AU)(OA;CI;CR;edacfd8f-ffb3-11d1-b41d-00a0c968f939;;AU)(A;CI;LCRPLORC;;;ED) "@ #------------------------------------------------------------- # You must be a member of the Schema Admins group to perform this task. # Get Group Membership of current user try { $groups = (([System.Security.Principal.WindowsIdentity]::GetCurrent()).Groups | %{ $_.Translate([System.Security.Principal.NTAccount]) } | Sort) -join "`r`n" } catch { "Groups could not be retrieved." } # Check if current user is a member of Schema Admins $IsMemberOfSchemaAdmins = $False ForEach ($group in $groups) { If ($group -like "*\Schema Admins*") { $IsMemberOfSchemaAdmins = $True } } If ($IsMemberOfSchemaAdmins) { write-verbose "The current user is a member of the Schema Admins group." -verbose # Import the Active Directory Module Import-Module ActiveDirectory -WarningAction SilentlyContinue # Get Domain information. $domain = Get-ADDomain # Get Schema Master FSMO role holder. $SchemaMaster = (Get-ADForest -Server $domain.Forest).SchemaMaster write-verbose "The Schema Master is: $SchemaMaster" -verbose # Get the Naming Context (NC) for the Schema $schemaNamingContext = (Get-ADRootDSE).schemaNamingContext # Get existing security descriptor for group policy container from schema partition in Active Directory. $descriptor = ($container = Get-ADObject -Server $SchemaMaster "CN=Group-Policy-Container,$schemaNamingContext" -Properties defaultSecurityDescriptor).defaultSecurityDescriptor write-verbose "The existing security descriptor is:" -verbose $descriptor If ($ResetDefault) { $descriptor = $defaultSecurityDescriptor write-verbose "Resetting the security descriptor to default:" -verbose $descriptor } If ($ReadOnlyGroup -ne "") { write-verbose "Adding the read only group to the security descriptor." -verbose switch ($ReadOnlyGroup) { "Domain Computers" { # Use the commonly used acronym of DC for the well-known SID $reader = "DC"; Break } "Authenticated Users" { # Use the commonly used acronym of AU for the well-known SID $reader = "AU"; Break } default { # Get SID of ReadOnlyGroup. $reader = New-Object System.Security.Principal.NTAccount($domain.NetBIOSName, "$ReadOnlyGroup") $reader = $reader.Translate([System.Security.Principal.SecurityIdentifier]).value } } # Set the access control entry for the Read Only group. $descriptor = $descriptor + "(A;CI;LCRPLORC;;;$reader)" } If ($ModifyGroup -ne "") { write-verbose "Adding the modify group to the security descriptor." -verbose # Get SID of ModifyGroup. $modifier = New-Object System.Security.Principal.NTAccount($domain.NetBIOSName, "$ModifyGroup") $modifier = $modifier.Translate([System.Security.Principal.SecurityIdentifier]).value # Set the access control entry for the Modify group. $descriptor = $descriptor + "(A;CI;RPWPCCDCLCLORCWOWDSDDTSW;;;$modifier)" } If ($Action) { # Concatenate the access control entries with the existing security descriptor. $container | Set-ADObject -Replace @{defaultSecurityDescriptor = "$descriptor";} -Server $SchemaMaster write-verbose "The new security descriptor after the change is:" -verbose (Get-ADObject -Server $SchemaMaster "CN=Group-Policy-Container,$schemaNamingContext" -Properties defaultSecurityDescriptor).defaultSecurityDescriptor } Else { write-verbose "The new security descriptor to be applied is:" -verbose $descriptor } } Else { write-warning "The current user is NOT a member of the Schema Admins group." -verbose write-warning "This is a requirement to run this script." -verbose }