Active Directory Permissions : Security Descriptors
This article of the SelfADSI tutorial explains how to read or set permissions on Active Directory objects by script. The following sections are available:
Permissions in Active Directory are defined by so-called security descriptors, which are stored as properties directly in the AD objects. Actually, two different Active Directory attributes are internally structured as a security descriptor:
nTSecurityDescriptor | Alle Objekte | Hier
werden die Berechtigungen f?r das Objekt selbst gespeichert. Jedes Objekt hat einen eigenen Security Desriptor. |
msExchMailboxSecurityDescriptor | Postfach-Benutzer | Diese Eigenschaft existiert nur in Microsoft Exchange-Umgebungen bei Benutzern mit Postfach. Es wird festgelegt, wer auf das betreffende Postfach zugreifen darf - allerdings nur zum Zeitpunkt der Erstellung des Postfachs. Sp?ter werden Postfachrechte nur durch dieses Attribut repr?sentiert, k?nnen jedoch nicht dar?ber gesetzt werden. |
The basic LDAP attribute data type for these attributes is a is Microsoft's proprietary LDAP attribute syntax called String (NT Sec Desc). Basically, this is a binary format, but the data contents of a security descriptor can be fortunately read by scripts through the ADSI interface. The relevant objects are described in detail in the ADSI reference:
But before we deal with the reading and setting of permissions in the Active Directory in scripting, we should take a look at the internal structures of a security descriptor. The exact structure of a general security descriptor value is described in these documents Micrsoft:
- Microsoft Data Type Reference [MSDTY]
- Technet : How Security Descriptors and Access Control Lists Work
Note: Security Descriptor structures are found not only at the permissions on directory objects, but also at
permissions in the NTFS file system, registry permission or in general with all permissions on system objects
(services, printers, etc.). This article focuses more on the specifics of the permissions in Active Directory, this
concerns mainly the construction of ACEs and Access Masks.
The internal structureof a Security Descriptors (SD)
The internal structure of a security descriptor is quite complex because we must consider several elements that are nested within each other: The Security Descriptor as a whole consists of a header, the owner information, and two different acces lists (ACLs). Regarding these, the actual ACL permissions are included in the Discretionary ACL (DACL). This DACL in turn consists of several Access Control Entries (ACEs), four of which are relevant to us.
When creating scripts this means the following: When a script wants to read the permissions of an Active Directory , it must first read the Security Descirptor and the included DACL to get the list of ACEs. In that ACEs are the actual permissions stored. If you want to set permissions, so you have rarely to built up a security descriptor from nothing by yourself - there simply are no AD object that is not already configured with permissions. Immediately after the object creation permissions automatically result from the inheritance of the default settings. Granting or revoking permissions in scripts is thus based always on the change of the existing list of ACEs.
Let us first consider the security descriptor with its construction of a header, owner information and ACLs. As mentioned above, we find a detailed description of the technical structure of a security descriptor in the Microsoft Technet:
Header: A structure that includes a general revision value as well as various control bits. These flags provide information about how and of what elements the security descriptor in question is composed of - or will put together, if you want to create the structure with just a new Secruity descriptor. In addition, the control flags determine whether the permissions and audit settings are inherited by parent structures, or whether the inheritance is blocked in this security descriptor. Additionally, the header technically still contain offset addresses to determine the internal storage addresses of other components of the security descriptor.
Owner: The Object owner - technically in the form of a SID (security identifier). The owner is the user account that created the object. Owners may always change the permissions on the object. A special feature: Did a member of the pre-defined group of administrators create the object, then this group is registered as owner. When this field is set in a script, you can directly use a Windows login name, eg 'SELFADSI\pfoeckel'.
Owner Group: The group of the object owners - technically in the form of a SID (security identifier). The group owner is rarely
used in practice, usually only the owner plays a role - the owner group is simply the primary group of the owner.
SACL - System Access Control List: The SACL is the list in which the auditing settings for that object are stored (Which requests by whom are monitored and how?). Only those who have the policy privilege 'Manage Auditing and Security Log' on the domain controllers can
read or write the SACL. Also keep in mind that there are still global audit flags which must be active for the directory service auditing on a domain controller (done via GPO).
DACL - Discretionary Access Control List: The DACL contains the access permissions on an object (Who can do what?). This is list with the actual permissions. It can always be changed by the owner of the object and of all those who are authorized with WRITE_DAC (see list of Access Masks Bits) on the object. To read the Discrentionary Access Control, you need the READ_CONTROL right.
Access Control Lists (ACLs)
An Access List (regardless whether a System ACL for auditing or a Discretionary ACL for permissions) always consists of a header and a number of Acces Control Entries (ACEs). The exact technical structure of an ACL is described here:
It should be noted that the revision value for an Active Directory ACL must always 4. The ACEs are so to speak the individual permissions that we see in the normal administrative management tool:
Access Control Entries (ACEs)
An ACE is the config strucutre for a single permision grant (or denial of rights) for a particular user or a particular group. There are many different types of ACEs, but in the permissions for Active Directory, there are only four different types of meaning, two each for granting and the denying of permissions. The detailed technical structure of ACEs is described here:
There is a simple ACE form, which can be used to grant/revoke permissions for the entire Obekt (including standard inheritance). There are still the more complex forms of the so-called Object ACEs. Because in the following cases, the simple form of ACEs are not enough:
- Permissions do not apply to the entire object, but only for a particular attribute or set of attributes (eg, write permission to the address information of a user object).
- For permission to create/delete sub-objects, when this shall concerns only certain classes (eg the right to create child groups).
- Special permission must be granted (some of which are maybe specific for other applications), eg the right to reset user passwords, or the right to send mail on behalf of another user, or the right to perform an AD data replication.
- Rights must be assigned to produce a self-reference to the object, eg the right to set yourself in a group as a member.
The four ACE-Types which are relevant for us, in detail:
Access Allowed ACE:
In this ACE the type field is always set to 1. It is designed for easy assignment of rights to the entire object. The ACE flags determine whether this is an inherited or explicitly given permission. An authorization of the ACE type 0 is always passed down to child objects.
Access Allowed Object ACE:
In this ACE the type field is to always set to 5. This object ACE can set both ACE special rights or limited rights, eg granted only for certain attributes (=> ObjectType GUID) as well as a special inheritance can be configured so they can inherit only certain classes of objects that right, or that the permission applies only to the object itself and is not inherited (=> Interhited Type GUID). The flags field indicates whether there is an object type field or a inherited type field, or both.
Access Denied ACE:
In this type of ACE is to always set to 1. It is designed for simple revoking of permissions for the entire object. The ACE flags determine whether this is an inherited or explicitly assigned object revoking. A denial of the ACE type 5 is always propgated down to child objects.
Access Denied Object ACE:
In this ACE the type field is to always set to 6. This object ACE can revoke both ACE special rights or limited rights, eg revoked only for certain attributes (=> ObjectType GUID) as well as a special inheritance can be configured so they can inherit only certain classes of objects that right, or that the permission denial applies only to the object itself and is not inherited (=> Interhited Type GUID). The flags field indicates whether there is an object type field or a inherited type field, or both.
Control Flags in the SD Header
The header of a security descriptor contains the so-called control flags. Many of the flags do not matter when dealing with normal Active Directory permissions. The exact structure of the control flag is described here:
If you read a security descriptor, the following flags play an important role:
Control Flag | Bit Value | Meaning |
DACL_AUTO_INHERITED | 1024 | The security descriptor is created through normal inheritance. |
DACL_PROTECTED | 4096 | The security descriptor does NOT inherit permissions from parent objects. So if this flag is set, the rights inheritance for that AD object is disabled. |
If you write or newly create a Security Descriptor, the following flags are important:
Control Flag | Bit Value | Meaning |
OWNER_DEFAULTED | 1 | The Owner information is generated automatically. You can create a new Security Descriptor with this flag and does not need extra specify the Owner. In this case, the SID of the creating user himself is the owner (Exception: If a member of the default administrators creates an object, then the group and not the user account is the owner). |
GROUP_DEFAULTED | 2 | The Owner Group information is generated automatically. You can create a new security descriptor with this flag, then an extra group ID for the owner do not need to be specified. In this case, the primary group of the creating user is used as the owner group. |
DACL_DEFAULTED | 8 | The DACL (the permissions) will be automatically inherited from the parent container/object. You can use this flag to create a new security descriptor and simply inherit its rights without expicitely specifiying any permissions. |
SACL_DEFAULTED | 32 | The SACL (the aduit settings) will be automatically inherited from the parent container/object. You can use this flag to create a new security descriptor and simply inherit its audit settings without expicitely specifiying any settings. |
Flags in ACEs
The flags which are described here are part of every single Access Control Entry. So it may exist many times within one security descriptor. Caution, risk of confusion: In ACEs there are two types of flags: The "ACE Flags" and the "Flags". They control the inheritance settings of the regarding ACEs and may activate any existing Object type fields.
In every ACE there are "ACE Flags" that are part of the technical ACE header. These flags determine the mode of inheritance of new ACEs - or indicate the inheritance situation when you read the relevant ACE.
Flag | Abbreviation in SDDL |
Value (dez) |
Value (hex) |
Explanation |
ADS_ACEFLAG_INHERIT_ACE also called CONTAINER_INHERIT_ACE |
CI | 2 | 2 | Child objects inherit the permissions. The flag 'Object Inherit (OI)' which plays an important role in the permissions for files and directories, is not required for AD rights. In AD permissions only the "Container Inherit (CI)" flag is used. It refers to all objects, even those who do not have sub-objects to themselves. |
ADS_ACEFLAG_NO_PROPAGATE_INHERIT_ACE | NP | 4 | 4 | Only the immediate child objects inherit the permissions. Can be set as an addition to the CI flag. |
ADS_ACEFLAG_INHERIT_ONLY_ACE | IO | 8 | 8 | The permission is valid only for the child objects, but not for the actual object itself. Can be set as an addition to the CI flag. |
ADS_ACEFLAG_INHERITED_ACE | ID | 16 | 10 | This flag indicates that this is a permission inherited from the top down. This flag can not be set, but can be checked to find inherited rights. |
There are also other flag values they either don't exist in Active Directory ACLs, or aren't important for permissions, but for the audit settings in SACLs. A complete documentation of the flags can be found here:
The propagation of the permission to child objects can be specified more detailed in the more complex object ACEs (ACE type 5 and 6). There it can be determined for example whether such a right should only apply to child objects users, or only to groups. These must be placed in the appropriate ACEs the "Inherited Type". Whether this is the case, you can see in the so-called 'Flags' field:
Flag | Bit Value | Meaning |
OBJECT_TYPE_PRESENT | 1 | The Object Type field in the ACE exists and contains an Object GUID with the following meaning
|
INHERITED_OBJECT_TYPE_PRESENT | 2 | The Inherited Object Type field in the ACE exists and contains an Object GUID of an object class from the AD schema. |
A complete documentation of the flags can be found here:
List of permissions - Access Mask Bits in the ACEs
This is a list of permissions on Active Directory directory objects, as contained in the above-described access control entries (ACEs). For some access masks, various bits can be set simultaneously, eg there can be defined in a single ACE that someone has the permission to create user objects as well as to delete them (CC + DC). However, there are obvious limitations, because in a single object-ACE is room for exactly one ObjectType GUID, so it's as not possible to set the permission to delete user objects and for writing the address properties in the same ACE.
The technical description of the Access mask bits from Microsoft:
Permission | Abbreviation in SDDL |
Value | Value (hex) |
Explanation |
ADS_RIGHT_DS_CREATE_CHILD | CC | 1 | 1 | Create child Objects. This right can be restricted to certain classes of objects. In this case the ACE property ObjectType must be set to the GUID of the appropriate object class (SchemaIDGuid in the class definition of the schema). |
ADS_RIGHT_DS_DELETE_CHILD | DC | 2 | 2 | Delete child Objects. This right can be restricted to certain classes of objects. In this case the ACE property ObjectType must be set to the GUID of the appropriate object class (SchemaIDGuid in the class definition of the schema). |
ADS_RIGHT_ACTRL_DS_LIST | LC | 4 | 4 | List child objects. |
ADS_RIGHT_DS_SELF | WS (auch SW) |
8 | 8 | Perform so called 'Validated Writes'. This right can be restricted to certain Validated Writes, eg 'Add yourself as a member', 'Set the own DNS address' etc. In this case the ACE property ObjectType must be the GUID of the appropriate ExtendedRights included (RightsGuid value from the Configuration Partition \ Extended-Rights). |
ADS_RIGHT_DS_READ_PROP | RP | 16 | 10 | Read properties / attribute values of the regarding object. In this case the ACE property ObjectType must be set to the GUID of the appropriate attribute (SchemaIDGuid in the attribute definition of the schema). |
ADS_RIGHT_DS_WRITE_PROP | WP | 32 | 20 | Write properties / set attribute values of the regarding object. In this case the ACE property ObjectType must be set to the GUID of the appropriate attribute (SchemaIDGuid in the attribute definition of the schema). |
ADS_RIGHT_DS_DELETE_TREE | DT | 64 | 40 | Delete all subordinate child objects, no matter which permission is configured in the regarding sub structure. |
ADS_RIGHT_DS_LIST_OBJECT | LO | 128 | 80 | List the object in question, although the general permission "ADS_RIGHT_ACTRL_DS_LIST" was maybe denied in the regarding container. It's kind of an overwrite for individual objects that are visible, although the rest of the container is hidden. This permission is effective only when the third dsHeuristics flag is set to 1. |
ADS_RIGHT_DS_CONTROL_ACCESS | CA (auch CR) |
256 | 100 | Perform extended rights. This can be further restricted to specific extended rights, such as "Reset Password", "Change Rid Master", "Replication Synchronization", "Migrate SID History", etc. In this case the ACE property ObjectType must set to the GUID of the appropriate ExtendedRights (RightsGuid value from the Configuration Partition \ Extended-Rights). |
ADS_RIGHT_DELETE | DE | 65536 | 10000 | Delete the regarding object. |
ADS_RIGHT_READ_CONTROL | RC | 131072 | 20000 | Read the permissions (DACL) and the owner properties of the regarding object. |
ADS_RIGHT_WRITE_DAC | WD | 262144 | 40000 | Change The permissions (DACL) of the regarding object. Note that the owner can always change the DACL, even if he do not have explicitly this right. |
ADS_RIGHT_WRITE_OWNER | WO | 524288 | 80000 | Change the owner property of the regarding object. |
ADS_RIGHT_SYNCHRONIZE | SY | 1048576 | 100000 | You will not see this permission when you deal with AD object rights - nor set this permission flag by yourself for any AD object. It's a generic permission and not required for Active Directory objects. |
ADS_RIGHT_ACCESS_SYSTEM_SECURITY | AS | 16777216 | 1000000 | You will not see this permission when you deal with AD object rights - nor set this permission flag by yourself for any AD object. This bit has a meaning Only in SACLs audit settings: You can specify that the access to the SACL itsel fis audited . |
ADS_RIGHT_GENERIC_ALL | GA | 268435456 | 10000000 | You will not see this permission when you read AD object rights. However, you can use this bit if you set AD object permissions, the system is internally translating this bit into the following combination of 'real' AD object rights:
|
ADS_RIGHT_GENERIC_EXECUTE | GX | 536870912 | 20000000 | You will not see this permission when you read AD object rights. However, you can use this bit if you set AD object permissions, the system is internally translating this bit into the ADS_RIGHT_ACTRL_DS_LIST permission (list chlid objects): |
ADS_RIGHT_GENERIC_WRITE | GW | 1073741824 | 40000000 | You will not see this permission when you read AD object rights. However, you can use this bit if you set AD object permissions, the system is internally translating this bit into the following combination of 'real' AD object rights:
|
ADS_RIGHT_GENERIC_READ | GR | 2147483648 | 80000000 | You will not see this permission when you read AD object rights. However, you can use this bit if you set AD object permissions, the system is internally translating this bit into the following combination of 'real' AD object rights:
|
Object Type GUIDs in ACEs
In complex ACEs of type 5 and 6, there are a field named 'ObjectType GUID'. There may be three cases in which this field is used. In these situations, the flag OBJECT_TYPE_PRESENT (1) in the respective access control entry must be set. By the way, the GUID here can be read and set in script as a simple character string.
- For CC / DC permissions (Create Child / Delete Child), the child object class can be specified here. In this case there is the GUID of an object class from the AD schema the Object Type field (SchemaIDGuid value in the class definition of the schema). A few important GUID values:
Object Class GUID Organizational Units bf967aa5-0de6-11d0-a285-00aa003049e2 Computer bf967a86-0de6-11d0-a285-00aa003049e2 User bf967aba-0de6-11d0-a285-00aa003049e2 Groups bf967a9c-0de6-11d0-a285-00aa003049e2 Contacts 5cb41ed0-0e4c-11d0-a286-00aa003049e2
- For RP / WP permission (Read Property / Write Property) here, the attribute or the property set can be specified here. In this case the Object Type field must be filled with a GUID of an attribute from the AD schema or the property set GUID from the configuration partition (container "Extended Rights") in . A few important attribute GUID values:
Attribute GUID department bf96794f-0de6-11d0-a285-00aa003049e2 description bf967950-0de6-11d0-a285-00aa003049e2 displayName bf967953-0de6-11d0-a285-00aa003049e2 givenName f0f8ff8e-1191-11d0-a060-00aa006c33ed mail bf967961-0de6-11d0-a285-00aa003049e2 member bf9679c0-0de6-11d0-a285-00aa003049e2 physicalDeliveryOfficeName bf9679f7-0de6-11d0-a285-00aa003049e2 proxyAddresses bf967a06-0de6-11d0-a285-00aa003049e2 sn bf967a41-0de6-11d0-a285-00aa003049e2 telephoneNumber bf967a49-0de6-11d0-a285-00aa003049e2
A few examples for property set GUID values:
Property Set GUID General Information 59ba2f42-79a2-11d0-9020-00c04fc2d3cf Personal Information 77b5b886-944a-11d1-aebd-0000f80367c1 Private Information 91e647de-d96f-4b70-9557-d63ff4f3ccd8 Public Information e48d0154-bcf8-11d1-8702-00c04fb96050
- For extended CA rights (Control Access), the specific permission be specified here. In this case, the Object Type field must be filled with a GUID of an extended right from the config partition (container "Extended Rights"). Some examples of ExtendedRight GUIDs:
Extended Right GUID Administer Exchange information store d74a8762-22b9-11d3-aa62-00c04f8eedd8 Create Inbound Forest Trust e2a36dc9-ae17-47c3-b58b-be34c55ba633 Change Password ab721a53-1e2f-11d0-9819-00aa0040529b Migrate SID History ba33815a-4f93-4c76-87f3-57574bff8109 Reanimate Tombstones 45ec5156-db7e-47bb-b53f-dbeb2d03c40f Receive As ab721a56-1e2f-11d0-9819-00aa0040529b Replication Synchronization 1131f6ab-9c07-11d1-f79f-00c04fc2dcd2 Reset Password 00299570-246d-11d0-a768-00aa006e0529 Send As ab721a54-1e2f-11d0-9819-00aa0040529b Unexpire Password ccc2dc7d-a6ad-4a7a-8846-c04e3cc53501 View Exchange information store status d74a875e-22b9-11d3-aa62-00c04f8eedd8
Inherited Type GUIDs in ACEs
In complex ACEs of type 5 and 6, there are field named 'Inherited Object Type GUID'. It can be used to pass on the privilege only to specific classes of objects (eg "The display name can be changed, but only in groups"). In this case, the flag INHERITED_OBJECT_TYPE_PRESENT (2) in the respective access control entry must be set. In th the Inherited Object Type field, there is the GUID of an object class from the AD schema (SchemaIDGuid value in the class definition of the schema). By the way, the GUID here can be read and set in script as a simple character string. A few important object class GUID values:
Objektklasse | GUID |
Organizational Units | bf967aa5-0de6-11d0-a285-00aa003049e2 |
Computer | bf967a86-0de6-11d0-a285-00aa003049e2 |
User | bf967aba-0de6-11d0-a285-00aa003049e2 |
Groups | bf967a9c-0de6-11d0-a285-00aa003049e2 |
Contacts | 5cb41ed0-0e4c-11d0-a286-00aa003049e2 |
Trustees in ACEs
An Access Control Entriy (ACEs) always contains always the trustee, that means the account or group for which permissions are granted or revoked. When setting and reading trustee values, there may be two forms used:
- If you run a script to read or set permissions in the same Active Directory domain, then trustees will simply be represented in the NetBIOS notation 'DOMAIN\username' or 'DOMAIN\groupname'.
- If you are not automatically logged in the domain with your script, you have to use explicit credentials. Trustees must be specified then as technical security identifiers (SIDs), eg 'S-1-5-21-1621763826-2590103247-2238570322-1113'. You must of course know how to get the SID of a user or group.
There is a detailed SelfADSI tuorial article about the structure of Microsoft SIDs and how to deal with them: "Microsoft Security Identifier (SID) Attribute".
Permission Inheritance
In the inheritance of permissions for Active Directory objects, there are several interesting aspects:
- You may want to examine directory object in a script and check, whether the inheritance of permissions was basically disabled / blocked. Here you only need to check the DACL_PROTECTED bit in the control flags of the entire security descriptor.
- You may want to find out via script for a single existing permission, whether it was inherited from the top down, or set explicitly. You can check the relevant Access Control Entry, whether INHERITED_ACE the flag is set there in the ACEFlags.
- If you want to set new permissions by script, you want to determine whether and how these rights will be inherited by child objects. A large role is played by the flags in the ACE generated by you. You can use this matrix:
Read Active Directory Permissions in a Script
Here is an example how to read the permissions of a single Active Directory object. For this purpose we have to read and evaluate the LDAP attribute nTSecurityDesriptor:
The story becomes more complicated if you want a detailed analysis of the permissions and propagated inheritance. This is because the script have to seek and decode all the regarding GUIDs in the schema or the config partition. The two functions decode_permission and decode_propagation are used for this.
This script has to be run as an administrator on a system that is member in the regarding domain.
Set Active Directory Permissions in a Script
Here is an example of how to assign permission for a single object in the Active Directory. For this purpose, you have to read the nTSecurityDesriptor attribute first. Then you can change the DAC within by adding new ACE entries. Later, the entire attribute is written back.
A trustee (for example user or a group from the same AD forest) gets permissions on a OU:
- Delete this OU (this counts only for the OU itself, so it should be empty then)
- Write permissions on the attribute "description" for all objects in this OU
- Reset passwords for user accounts in this OU
Please note the appropriate ACE flags and object GUIDs which are used for this permissions. The script has to be run as an administrator on a system that is member in the regarding domain:
Remove Active Directory Permissions in a Script
Here is an example of how to get the permission for a single object in the Active Directory removed. For this purpose the nTSecurityDesriptor attribute has to be read. We read from the contained Discretionary Access Control List (DACL) all ACEs that are not inherited from above, and which do not grant permissions to the trustee which you want to remove from the DACL. In rewriting the entire attribute, then the permissions inherited from abovecome back automatically.