Monday, October 23, 2006

MIIS Solutions: Designing Effective Schema Extensions for Active Directory, part 3

Pre-Windows 2000 Compatible Access

Since Active Directory debuted it has contained a special group called the Pre-Windows 2000 Compatible Access group. Let's see what Microsoft has to say about this group:

The Pre-Windows 2000 Compatible Access group is used for backward compatibility for computers that are running Microsoft Windows NT 4.0 and earlier. Members of this group have Read access on all users and groups in the domain. Add users to this group only if they are running Windows NT 4.0 or earlier.

Figure 1

When you either upgraded or initially installed your domain (each of them if you have multiple) you were faced with a choice during DCPromo (see Figure 1) that asked you whether or not you wanted to enable Pre-Windows 2000 compatibility. If you said yes (and most of you did), then you are allowing not only Anonymous connections to your Active Directory (sometimes called null sessions), but the old NT4 style group "Everyone" has access to Read pretty much all data in your directory. So why would someone need to be in this mode to begin with? Well, according to TechNet:

In Windows NT 4.0 and earlier server operating systems, services running in the context of the Local System account communicate with other services over the network by using null sessions (a session in which a user name or password is not provided). In Windows 2000 and later operating systems, services running in the context of the Local System account on the local computer use the local computer account to authenticate to other servers. By default, Active Directory does not accept null session queries.

Of all the services that run in the context of the Local System account, Remote Access Services (RAS) is the most prominent. You cannot use null sessions to access network resources by using NTLM authentication unless the remote computer allows access with null credentials.

NOTE: If you are using ADMT or another migration utility and you are migrating passwords you will have a valid, albeit temporary, reason for having the Everyone and Anonymous entries nested.

So now that we know a little bit about this group, precisely what level of access does it have to our domain?

Figure 2

In Figure 2 we see that this group has "Special" access to both User and Group objects. Digging a bit further reveals that the "Read All Properties" right is granted to both object types. This means that Everyone, Authenticated Users, and Anonymous can read every property on every User and Group object by virtue of being in this group. This also means that whatever you do with new custom attributes in an attempt to hide them or restrict access to Read them, this group will still have access. What you should also notice here is that Authenticated Users does not have any rights granted to the User object at the root of the domain, but looking at the effective rights of a User object shows that Authenticated Users has Read access to several properties; so where are these rights being granted?

Default Security

If you open the Active Directory Schema snap-in and navigate your way to the User class you can see the Default Security of the class as shown in Figure 3.

Figure 3

Setting security on a schema class allows you to affect only the default permissions when new objects are created - it does not affect the permissions on existing objects of the referenced class.

It is very important to note that you should not, under any circumstances, remove the default rights for Authenticated Users here. Many applications (like Exchange) rely on these default rights and removing them would prevent certain applications from working with new user objects. So, how do you change the permissions and restrict security?

Affecting Existing Permissions

Pre-Windows 2000 Compatible Mode

If you want to restrict Read permissions to an existing attribute or Property Set of the User class and you are affected by the Pre-Windows 2000 Compatible group then you have few options for doing so:

  • Remove the nestings for the Pre-Windows 2000 Compatible group - by far your best option. If you can do it, removing all of the groups nested here will not only remove the default Read All Properties right, but will tighten security in other areas as well.
  • Add a Deny Read ACE for the attribute or Property Set in question - this is a bit riskier and if you can at all avoid it you should always attempt to avoid Deny rights as they significantly complicate troubleshooting. See the next section on Deny rights...

Inherited Deny vs Explicit Read

Active Directory permissions allow you inherit permissions from the parent object and this affects Deny privileges in a slightly different way. You would expect a Deny ACE to inherit everywhere and in File Permissions a Deny always takes precedence but in AD an Inherited Deny right can be overridden by an Explicit Read permission. The precedence order, from most precedent to least, is as follows:

  1. Explicit Deny
  2. Explicit Allow
  3. Inherited Deny
  4. Inherited Allow

Therefore, it is entirely legal to grant Read permissions to a group you've denied (or one that you're nested into) at another higher container within your OU hierarchy. As stated before - this severely complicates troubleshooting and is not intuitive when looking at an interface, but if you have no other option, you can use this method to restrict access.

Authenticated Users

To change the default rights that Authenticated Users have assuming you're not also affected by the Pre-Windows 2000 Compatible group affords few choices since the rights are granted by the Default Security permissions applied at the time of object creation. Since these permissions affect only the General, Personal, Web and Public Property Sets you will only be concerned with restricting access to attributes defined within these sets. If you find yourself in this situation, here are some options:

Not Recommended

  • Although extensive effort is required and there is as much risk associated with doing so, it is possible to change the permissions on every User object in the domain (using something like DSACLS) to remove or modify the default rights granted to the Property Set in question. In order to be effective this would need to be paired with the same change to the Default Security Permissions on the User object in Schema. Extensive testing is required for all existing and future applications that may rely on these default rights to be present.
  • As each Property Set is a collection of assembled attributes you may be tempted to remove one or two attributes from the Property Set. This will have the immediate effect of removing rights to the attributes. However, the same extensive testing required when modifying the Default Security rights is still required for all existing and future applications that may rely on gaining access, by default, to the attributes you've removed. NOTE: While this is not a recommended method for removing access to attributes, adding a custom attribute to an existing Property Set is an excellent way to grant access equal to the affected Property Set. Adding a new or existing attribute to a Property Set requires that the attribute not currently be a member of a Property Set (only one set at a time) and that the attributeSecurityGUID of the attribute match the rightsGuid of the Property Set you want to add it to (you'll need the GUIDConverter tool mentioned in the first installment to convert the formats).


  • If you only need to restrict Read access to an attribute then you may be able to set a single bit flag on the attribute to restrict casual access. This feature is called the Confidentiality Bit and is only available if all of your Domain Controllers are running on Windows 2003 Server with SP1 applied. Furthermore, all Administrative level identities (like Domain Admins, Enterprise Admins, etc) will still be able to Read the attribute casually. One of the biggest advantages of using this approach is that the change is applied at the Schema level and doesn't affect any ACLs or add any ACEs (so no ACL bloat). Refer to the section on setting the Confidentiality Bit later. NOTE: Not all attributes can have their Confidentiality Bit set - certain system attributes are prevented from being set. Refer to the section on setting the Confidentiality Bit later for limitations.
  • Finding yourself in the predicament of needing to restrict access to one or more attributes that are in the before mentioned Property Sets is an excellent reason to extend the Schema and create new attributes and even Property Sets. While this is not a trivial task, it is certainly much less riskier than any of the "not recommended" options and with the proper planning can be the most flexible of all options. Combined with the Confidentiality Bit, this approach is extremely effective at limiting Read access.

Setting the Confidentiality Bit

As mentioned earlier, the Confidentiality Bit has the following limitations:

  • Windows 2003 Server SP1 is required on all Domain Controllers in the Domain; however this setting is independent of Domain or Forest Functional Level
  • System attributes, a.k.a. Category 1 attributes (like employeeID) cannot have this bit enabled due to system restrictions on objects of this type - there are over 1000 existing attributes that are considered Category 1
  • Only good for limiting Read access to non-Admin type accounts - Write access is not affected
  • A special Control Access ACE entry is required to delegate Read permissions to attributes with this bit set - tools like DSACLS or the ADAM R2/SP1 version of LDP are able to create the entry

To tell whether or not you can set this bit on an attribute (assuming you've met all of the above requirements) you will need to verify the setting of the systemFlags bitmask on the attribute in question. If bit 4 (16 decimal/10 hex) is enabled then it is a Category 1 attribute and cannot be modified. You can use any LDAP query tool to locate attributes in this state. You can use the following filter to search via LDP, LDIFDE, or any other query tool:

  • LDAP Query Filter: (&(objectCategory=attributeSchema)(systemFlags:

To enable the Confidentiality Bit, you add 128 to the existing value of the searchFlags bitmask. To set the bit you will need to use a tool like LDP, an LDIF file or the ADSI Edit MMC snap-in. The following examples will utilize the ADSI Edit method:

  1. Use the Connect To option to specify the Schema NC

  2. Expand the selection and then select the attribute that you would like to modify

  3. Take the Properties of the attribute and locate the systemFlags entry
  4. Edit the searchFlags entry and add 128 to the value already present
  5. Update the Schema for the changes to take affect

Or use this example for an LDIF script (copy this text into Notepad and save it):

dn: CN=[Your Schema Attribute Here],CN=Schema,CN=Configuration,DC=fabrikam,DC=com changetype: modify replace: searchFlags searchFlags: 128 -

# Commit the changes:

dn: changetype: ntdsSchemaModify add: schemaUpdateNow schemaUpdateNow: 1 -

NOTE: There is no way for LDIF scripts to add to an existing value using the "replace" command. If you need to modify attributes with existing values then you will need to consider writing a script to handle the additions or produce an LDIF script with the modified values before hand.

Run the file using LDIFDE like so:

ldifde -i -f [filename]

In part 4 we will explore how to model our Property Sets, assign attributes to them, and work with Auxiliary classes.

Newer Posts Older Posts Home