{"id":1668,"date":"2016-06-29T22:44:01","date_gmt":"2016-06-29T14:44:01","guid":{"rendered":"http:\/\/www.jhouseconsulting.com\/?p=1668"},"modified":"2021-07-07T19:33:39","modified_gmt":"2021-07-07T11:33:39","slug":"script-to-modify-the-defaultsecuritydescriptor-attribute-on-the-group-policy-container-schema-class-object","status":"publish","type":"post","link":"https:\/\/www.jhouseconsulting.com\/jhouseconsulting\/2016\/06\/29\/script-to-modify-the-defaultsecuritydescriptor-attribute-on-the-group-policy-container-schema-class-object-1668","title":{"rendered":"Script to modify the defaultSecurityDescriptor attribute on the Group-Policy-Container schema class object"},"content":{"rendered":"<p>Last week I published an article about the changes in the behavior of Group Policy processing after the deployment of security update MS16-072 under KB3163622. It included a script to&nbsp;assist with the&nbsp;remediation of Group Policy permissions: <a href=\"http:\/\/www.jhouseconsulting.com\/2016\/06\/22\/script-to-report-on-and-remediate-the-group-policy-security-change-in-ms16-072-1627\" target=\"_blank\">Script to report on and remediate the Group Policy security change in MS16-072<\/a>.<\/p>\n<p>Of course that&#8217;s not where it ends. What about new Group Policies? Do you create a procedure that requires you to add &#8220;Domain Computers&#8221; with Read permission every time you create a new Group Policy Object (GPO)? No&#8230;of course not!<\/p>\n<p>What we need to do now is change the defaultSecurityDescriptor&nbsp;attribute on the Group-Policy-Container schema class object so that new GPOs are created with Domain Computers having Read permissions by default. Microsoft didn&#8217;t released an official script or method to do this, so here&#8217;s the next best thing.<!--more--><\/p>\n<p>I will note that <a href=\"https:\/\/sdmsoftware.com\/\" target=\"_blank\">Darren Mar-Elia<\/a>&nbsp;created a <a href=\"https:\/\/sdmsoftware.com\/group-policy-blog\/tips-tricks\/modifying-default-gpo-permissions-creation-time\/\" target=\"_blank\">blog post<\/a>&nbsp;to show you how to manually do this.&nbsp;<a href=\"http:\/\/www.gpanswers.com\/\" target=\"_blank\">Jeremy Moskowitz<\/a> also&nbsp;included these steps&nbsp;in <a href=\"http:\/\/www.gpanswers.com\/never-a-dull-moment-with-group-policy-or-what-to-do-about-ms16-072\/\" target=\"_blank\">his article<\/a>.<\/p>\n<p>I&#8217;m a big fan of scripting, and already had a script to this that I wrote back in 2011 using the&nbsp;Quest ActiveRoles Snapin Module. I wrote it&nbsp;for a delegated administrative model I implemented for a large University. I also recently found a great script from <a href=\"http:\/\/hinchley.net\/\" target=\"_blank\">Peter Hinchley<\/a>:&nbsp;<a href=\"http:\/\/hinchley.net\/2015\/10\/10\/set-default-permissions-for-new-group-policy-objects\/\" target=\"_blank\">Set Default Permissions for New Group Policy Objects<\/a>. So I took both scripts and merged the ideas, basing a new script on Peter&#8217;s. The outcome was a very simple and repeatable way to modify the defaultSecurityDescriptor on the Group-Policy-Container schema class object without the need to go through the steps that Darren and Jeremy laid out.<\/p>\n<p>Before running the script you (or the account you&#8217;re running the script as) must be a member of the Schema Admins group.<\/p>\n<p>Run the script with no parameters (in report only mode) and it will report on the existing&nbsp;Security Descriptor, and what the new one will look like. So it&#8217;s basically showing you the projected outcome. The following screen shot shows that DC (the&nbsp;acronym for the well-known SID of Domain Computers) is added with Read permissions.<\/p>\n<p><a href=\"http:\/\/www.jhouseconsulting.com\/gpc-securitydescriptor-before-change\"><img fetchpriority=\"high\" decoding=\"async\" class=\"aligncenter size-full wp-image-1673\" src=\"https:\/\/www.jhouseconsulting.com\/jhouseconsulting\/wp-content\/uploads\/2016\/06\/GPC-SecurityDescriptor-Before-Change.png\" alt=\"Group-Policy-Container DefaultSecurityDescriptor - Before Change\" width=\"693\" height=\"157\" srcset=\"https:\/\/www.jhouseconsulting.com\/jhouseconsulting\/wp-content\/uploads\/2016\/06\/GPC-SecurityDescriptor-Before-Change.png 693w, https:\/\/www.jhouseconsulting.com\/jhouseconsulting\/wp-content\/uploads\/2016\/06\/GPC-SecurityDescriptor-Before-Change-300x68.png 300w\" sizes=\"(max-width: 693px) 100vw, 693px\" \/><\/a><\/p>\n<p>So how do we know that we&#8217;re applying Read permissions? Well I guess you need to understand a little bit about the&nbsp;Security Descriptor Definition Language (SDDL). Without going too deeply into SDDL in this article, the specific permission we are adding here is made up of the following 6&nbsp;fields:<\/p>\n<p>ACE Type:<\/p>\n<ul>\n<li>A =&nbsp;Access Allowed<\/li>\n<\/ul>\n<p>ACE Flags:<\/p>\n<ul>\n<li>CI = Container Inherit<\/li>\n<\/ul>\n<p>Permissions:<\/p>\n<ul>\n<li>LC = List Contents<\/li>\n<li>RP = Read All Properties<\/li>\n<li>LO = List Object<\/li>\n<li>RC = Read Permissions<\/li>\n<\/ul>\n<p>ObjectType:<\/p>\n<ul>\n<li>(nothing added here, hence why the field is blank)<\/li>\n<\/ul>\n<p>Inherited Object Type:<\/p>\n<ul>\n<li>(nothing added here, hence why the field is blank)<\/li>\n<\/ul>\n<p>Trustee:<\/p>\n<ul>\n<li>DC = Domain&nbsp;Computers<\/li>\n<\/ul>\n<p>Running the script again with the -Action parameter applies the change as demonstrated in the following screen shot.<\/p>\n<p><a href=\"http:\/\/www.jhouseconsulting.com\/gpc-securitydescriptor-after-change\"><img decoding=\"async\" class=\"aligncenter size-full wp-image-1674\" src=\"https:\/\/www.jhouseconsulting.com\/jhouseconsulting\/wp-content\/uploads\/2016\/06\/GPC-SecurityDescriptor-After-Change.png\" alt=\"Group-Policy-Container DefaultSecurityDescriptor - After Change\" width=\"693\" height=\"155\" srcset=\"https:\/\/www.jhouseconsulting.com\/jhouseconsulting\/wp-content\/uploads\/2016\/06\/GPC-SecurityDescriptor-After-Change.png 693w, https:\/\/www.jhouseconsulting.com\/jhouseconsulting\/wp-content\/uploads\/2016\/06\/GPC-SecurityDescriptor-After-Change-300x67.png 300w\" sizes=\"(max-width: 693px) 100vw, 693px\" \/><\/a><\/p>\n<p>So now when you create a new Group Policy Object (GPO), Domain Computers will have Read permissions by default!<\/p>\n<p><a href=\"http:\/\/www.jhouseconsulting.com\/new-gpo-permission-test\"><img decoding=\"async\" class=\"aligncenter size-full wp-image-1675\" src=\"https:\/\/www.jhouseconsulting.com\/jhouseconsulting\/wp-content\/uploads\/2016\/06\/New-GPO-Permission-Test.png\" alt=\"New GPO Permission Test\" width=\"539\" height=\"213\" srcset=\"https:\/\/www.jhouseconsulting.com\/jhouseconsulting\/wp-content\/uploads\/2016\/06\/New-GPO-Permission-Test.png 539w, https:\/\/www.jhouseconsulting.com\/jhouseconsulting\/wp-content\/uploads\/2016\/06\/New-GPO-Permission-Test-300x119.png 300w\" sizes=\"(max-width: 539px) 100vw, 539px\" \/><\/a><\/p>\n<p>How easy&nbsp;is that?<\/p>\n<p>Here&#8217;s an improved version written by Stu (kewalaka@gmail.com) and posted to his <a href=\"https:\/\/github.com\/kewalaka\/TechnetGallery\/blob\/main\/Set-GPOContainerPermissions\/Set-GPOContainerPermissions.ps1\" target=\"_blank\">Github repository<\/a>.<\/p>\n<p>I&#8217;ve made&nbsp;this script as generic as possible so that it can be used for other purposes too.<\/p>\n<p>Here is the <a  data-e-Disable-Page-Transition=\"true\" class=\"download-link\" title=\"\" href=\"https:\/\/www.jhouseconsulting.com\/jhouseconsulting\/download\/1676\/?tmstv=1776914800\" rel=\"nofollow\" id=\"download-link-1676\" data-redirect=\"false\" >\n\tModify-GroupPolicyContainer.ps1\t(1699 downloads\t)\n<\/a>\n&nbsp;script:<\/p>\n<pre class=\"brush: powershell; auto-links: false; title: ; toolbar: false; notranslate\" title=\"\">\r\n&lt;#\r\n  This script will modify the defaultSecurityDescriptor attribute on the Group-Policy-Container\r\n  schema class object, which ensures that a specific set of permissions are applied by default\r\n  to new Group Policy Objects (GPOs).\r\n\r\n  It's been setup to add groups with either\/or:\r\n  - Modify Permissions\r\n  - Read Permissions\r\n\r\n  This script was specifically written to overcome the Group Policy security change Microsoft\r\n  made in security update MS16-072 (KB3163622) by ensuring that Domain Computers is set with\r\n  default Read permissions.\r\n\r\n  This is the defaultSecurityDescriptor of the Group-Policy-Container class object:\r\n    D:P(A;CI;RPWPCCDCLCLOLORCWOWDSDDTSW;;;DA)(A;CI;RPWPCCDCLCLOLORCWOWDSDDTSW;;;EA)\r\n    (A;CI;RPWPCCDCLCLOLORCWOWDSDDTSW;;;CO)(A;CI;RPWPCCDCLCLORCWOWDSDDTSW;;;SY)\r\n    (A;CI;RPLCLORC;;;AU)(OA;CI;CR;edacfd8f-ffb3-11d1-b41d-00a0c968f939;;AU)(A;CI;LCRPLORC;;;ED)\r\n\r\n  Where...\r\n  - (A;CI;RPWPCCDCLCLOLORCWOWDSDDTSW;;;DA) = Domain Admins\r\n  - (A;CI;RPWPCCDCLCLOLORCWOWDSDDTSW;;;EA) = Enterprise Admins\r\n  - (A;CI;RPWPCCDCLCLOLORCWOWDSDDTSW;;;CO) = Creator Owner\r\n  - (A;CI;RPWPCCDCLCLORCWOWDSDDTSW;;;SY) = System\r\n  - (A;CI;RPLCLORC;;;AU) = Authenticated Users\r\n  - (OA;CI;CR;edacfd8f-ffb3-11d1-b41d-00a0c968f939;;AU) = Authenticated Users\r\n  - (A;CI;LCRPLORC;;;ED) = Enterprise Domain Controllers\r\n\r\n  This translates to the following:\r\n\r\n  ACE Type:\r\n  - A = ACCESS ALLOWED\r\n  - OA = OBJECT ACCESS ALLOWED: ONLY APPLIES TO A SUBSET OF THE OBJECT(S).\r\n \r\n  ACE Flags:\r\n  - CI = CONTAINER INHERIT: Child objects that are containers, such as directories, inherit the ACE as an explicit ACE.\r\n\r\n  Permissions:\r\n  - RC = Read Permissions\r\n  - SD = Delete\r\n  - WD = Modify Permissions\r\n  - WO = Modify Owner\r\n  - RP = Read All Properties\r\n  - WP = Write All Properties\r\n  - CC = Create All Child Objects\r\n  - DC = Delete All Child Objects\r\n  - LC = List Contents\r\n  - SW = All Validated Writes\r\n  - LO = List Object\r\n  - DT = Delete Subtree\r\n  - CR = All Extended Rights\r\n\r\n  Trustee:\r\n  - DA = Domain Admins\r\n  - EA = Enterprise Admins\r\n  - CO = Creator Owner\r\n  - SY = System\r\n  - AU = Authenticated Users\r\n  - ED = Enterprise Domain Controllers\r\n\r\n  So we simply need to append these:\r\n  - (A;CI;RPWPCCDCLCLOLORCWOWDSDDTSW;;;&lt;Creator Owners Group Sid&gt;)\r\n  - (A;CI;LCRPLORC;;;&lt;Read Only Group Sid&gt;)\r\n\r\n  Some good references to help you understand this further:\r\n  - http:\/\/www.sdmsoftware.com\/general-stuff\/group-policy-delegation\/\r\n  - http:\/\/support.microsoft.com\/kb\/321476\r\n  - http:\/\/clintboessen.blogspot.com\/2011\/08\/ad-delegation-how-to-set-default.html\r\n  - https:\/\/blogs.technet.microsoft.com\/askds\/2008\/04\/18\/the-security-descriptor-definition-language-of-love-part-1\/\r\n  - https:\/\/blogs.technet.microsoft.com\/askds\/2008\/05\/07\/the-security-descriptor-definition-language-of-love-part-2\/\r\n\r\n  This script is based on:\r\n  - A script I originally wrote on 11th November 2011 using the Quest ActiveRoles Snapin Module\r\n    for a delegated administrative model for a large University.\r\n  - A script published by Peter Hinchley 10th Oct 2015: Set Default Permissions for New Group Policy Objects\r\n    http:\/\/hinchley.net\/2015\/10\/10\/set-default-permissions-for-new-group-policy-objects\/\r\n\r\n  Syntax examples:\r\n\r\n  - To execute the script in report only mode:\r\n      Modify-GroupPolicyContainer.ps1\r\n\r\n  - To execute the script and take action:\r\n      Modify-GroupPolicyContainer.ps1 -Action\r\n\r\n  Script name: Modify-GroupPolicyContainer.ps1\r\n  Release 1.2\r\n  Written by Jeremy Saunders (jeremy@jhouseconsulting.com) 11th November 2011\r\n  Modified by Jeremy Saunders (jeremy@jhouseconsulting.com) 28th June 2016\r\n\r\n#&gt;\r\n\r\n#-------------------------------------------------------------\r\nparam(\r\n      &#x5B;switch]$Action\r\n     )\r\n\r\n# Set Powershell Compatibility Mode\r\nSet-StrictMode -Version 2.0\r\n\r\n#-------------------------------------------------------------\r\n\r\n# Set the Read Permissions Group Name.\r\n$ReadOnlyGroup = &quot;Domain Computers&quot;\r\n\r\n# Set the Modify Permissions Group Name.\r\n$ModifyGroup = &quot;&quot;\r\n\r\n# Set this to True to reset the base security descriptor to default settings.\r\n$ResetDefault = $False\r\n$defaultSecurityDescriptor = @&quot;\r\nD: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)\r\n&quot;@\r\n\r\n#-------------------------------------------------------------\r\n\r\n# You must be a member of the Schema Admins group to perform this task.\r\n\r\n# Get Group Membership of current user\r\ntry {  \r\n  $groups = ((&#x5B;System.Security.Principal.WindowsIdentity]::GetCurrent()).Groups | %{\r\n    $_.Translate(&#x5B;System.Security.Principal.NTAccount])\r\n  } | Sort) -join &quot;`r`n&quot;\r\n} catch { &quot;Groups could not be retrieved.&quot; }\r\n\r\n# Check if current user is a member of Schema Admins\r\n$IsMemberOfSchemaAdmins = $False\r\nForEach ($group in $groups) {\r\n  If ($group -like &quot;*\\Schema Admins*&quot;) {\r\n    $IsMemberOfSchemaAdmins = $True\r\n  }\r\n}\r\n\r\nIf ($IsMemberOfSchemaAdmins) {\r\n  write-verbose &quot;The current user is a member of the Schema Admins group.&quot; -verbose\r\n\r\n  # Import the Active Directory Module\r\n  Import-Module ActiveDirectory -WarningAction SilentlyContinue\r\n\r\n  # Get Domain information.\r\n  $domain = Get-ADDomain\r\n\r\n  # Get Schema Master FSMO role holder.\r\n  $SchemaMaster = (Get-ADForest -Server $domain.Forest).SchemaMaster\r\n  write-verbose &quot;The Schema Master is: $SchemaMaster&quot; -verbose\r\n\r\n  # Get the Naming Context (NC) for the Schema\r\n  $schemaNamingContext = (Get-ADRootDSE).schemaNamingContext\r\n\r\n  # Get existing security descriptor for group policy container from schema partition in Active Directory.\r\n  $descriptor = ($container = Get-ADObject -Server $SchemaMaster &quot;CN=Group-Policy-Container,$schemaNamingContext&quot; -Properties defaultSecurityDescriptor).defaultSecurityDescriptor\r\n  write-verbose &quot;The existing security descriptor is:&quot; -verbose\r\n  $descriptor\r\n\r\n  If ($ResetDefault) {\r\n    $descriptor = $defaultSecurityDescriptor\r\n    write-verbose &quot;Resetting the security descriptor to default:&quot; -verbose\r\n    $descriptor\r\n  }\r\n\r\n  If ($ReadOnlyGroup -ne &quot;&quot;) {\r\n    write-verbose &quot;Adding the read only group to the security descriptor.&quot; -verbose\r\n\r\n    switch ($ReadOnlyGroup)\r\n    {\r\n      &quot;Domain Computers&quot;    { # Use the commonly used acronym of DC for the well-known SID\r\n                              $reader = &quot;DC&quot;;\r\n                              Break\r\n                            }\r\n      &quot;Authenticated Users&quot; { # Use the commonly used acronym of AU for the well-known SID\r\n                              $reader = &quot;AU&quot;;\r\n                              Break\r\n                            }\r\n      default               { # Get SID of ReadOnlyGroup.\r\n                              $reader = New-Object System.Security.Principal.NTAccount($domain.NetBIOSName, &quot;$ReadOnlyGroup&quot;) \r\n                              $reader = $reader.Translate(&#x5B;System.Security.Principal.SecurityIdentifier]).value\r\n                            }\r\n    }\r\n\r\n    # Set the access control entry for the Read Only group.\r\n    $descriptor = $descriptor + &quot;(A;CI;LCRPLORC;;;$reader)&quot;\r\n  }\r\n\r\n  If ($ModifyGroup -ne &quot;&quot;) {\r\n    write-verbose &quot;Adding the modify group to the security descriptor.&quot; -verbose\r\n    # Get SID of ModifyGroup.\r\n    $modifier = New-Object System.Security.Principal.NTAccount($domain.NetBIOSName, &quot;$ModifyGroup&quot;) \r\n    $modifier = $modifier.Translate(&#x5B;System.Security.Principal.SecurityIdentifier]).value\r\n    # Set the access control entry for the Modify group.\r\n    $descriptor = $descriptor + &quot;(A;CI;RPWPCCDCLCLORCWOWDSDDTSW;;;$modifier)&quot;\r\n  }\r\n\r\n  If ($Action) {\r\n    # Concatenate the access control entries with the existing security descriptor.\r\n    $container | Set-ADObject -Replace @{defaultSecurityDescriptor = &quot;$descriptor&quot;;} -Server $SchemaMaster\r\n\r\n    write-verbose &quot;The new security descriptor after the change is:&quot; -verbose\r\n    (Get-ADObject -Server $SchemaMaster &quot;CN=Group-Policy-Container,$schemaNamingContext&quot; -Properties defaultSecurityDescriptor).defaultSecurityDescriptor\r\n  } Else {\r\n    write-verbose &quot;The new security descriptor to be applied is:&quot; -verbose\r\n    $descriptor\r\n  }\r\n\r\n} Else {\r\n  write-warning &quot;The current user is NOT a member of the Schema Admins group.&quot; -verbose\r\n  write-warning &quot;This is a requirement to run this script.&quot; -verbose\r\n}\r\n<\/pre>\n<p>Enjoy!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Last week I published an article about the changes in the behavior of Group Policy processing after the deployment of security update MS16-072 under KB3163622. It included a script to&nbsp;assist with the&nbsp;remediation of Group Policy permissions: Script to report on and remediate the Group Policy security change in MS16-072. Of course that&#8217;s not where it &#8230; <a title=\"Script to modify the defaultSecurityDescriptor attribute on the Group-Policy-Container schema class object\" class=\"read-more\" href=\"https:\/\/www.jhouseconsulting.com\/jhouseconsulting\/2016\/06\/29\/script-to-modify-the-defaultsecuritydescriptor-attribute-on-the-group-policy-container-schema-class-object-1668\" aria-label=\"Read more about Script to modify the defaultSecurityDescriptor attribute on the Group-Policy-Container schema class object\">Read more<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"ngg_post_thumbnail":0,"footnotes":""},"categories":[202,60,5],"tags":[120,447,441,214,419,217,215,443,442,341,340,444,7],"class_list":["post-1668","post","type-post","status-publish","format-standard","hentry","category-active-directory","category-group-policy","category-scripting","tag-authenticated-users","tag-defaultsecuritydescriptor","tag-domain-computers","tag-gpo","tag-group-policy","tag-group-policy-container","tag-group-policy-object","tag-kb3163622","tag-ms16-072","tag-posh","tag-powershell","tag-read-permission","tag-script"],"aioseo_notices":[],"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/www.jhouseconsulting.com\/jhouseconsulting\/wp-json\/wp\/v2\/posts\/1668","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.jhouseconsulting.com\/jhouseconsulting\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.jhouseconsulting.com\/jhouseconsulting\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.jhouseconsulting.com\/jhouseconsulting\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.jhouseconsulting.com\/jhouseconsulting\/wp-json\/wp\/v2\/comments?post=1668"}],"version-history":[{"count":5,"href":"https:\/\/www.jhouseconsulting.com\/jhouseconsulting\/wp-json\/wp\/v2\/posts\/1668\/revisions"}],"predecessor-version":[{"id":2269,"href":"https:\/\/www.jhouseconsulting.com\/jhouseconsulting\/wp-json\/wp\/v2\/posts\/1668\/revisions\/2269"}],"wp:attachment":[{"href":"https:\/\/www.jhouseconsulting.com\/jhouseconsulting\/wp-json\/wp\/v2\/media?parent=1668"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.jhouseconsulting.com\/jhouseconsulting\/wp-json\/wp\/v2\/categories?post=1668"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.jhouseconsulting.com\/jhouseconsulting\/wp-json\/wp\/v2\/tags?post=1668"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}