Anonymous LDAP operations in Windows 2003 AD

Background

By default, anonymous LDAP operations, except rootDSE searches and binds, are not permitted on Windows 2003 domain controllers. This means that when trying to perform unauthenticated search in Active Directory, you can query for attributes of the RootDSE object only – any other query will result in domain controller requesting authenticated bind to LDAP and refusing to your query.


Actually this is new behavior compared to Windows 2000 domain controllers which allowed anonymous operations and the query results were based only on the permissions of the objects.
“So what is it good for?” you might ask yourself. Well, one of the reasons is minimizing the impact of potential denial of service (DoS) attacks against AD. Consider a malicious application performing an anonymous LDAP query against domain controller. Theoretically, by crafting a very complicated LDAP filter with a “Sub” scope, an attacker could overload the LDAP server which would result in significant degradation in domain controller performance and even total denial of service.
Why you might want to enable anonymous binds? Usually this is desired when you need to provide an easy access to a subset of information stored in AD to 3rd party applications that are not capable of authenticating to AD or the information is intended to be in public domain from the beginning and you are storing it in AD. The scenarios are infinite, but before enabling anonymous operations make sure that you truly understand the implications of this action – the change (though reversible) does increase the security risks to your environment.
Let’s have a look at what are we allowed to see when we are trying to perform an anonymous lookup against W2K3 domain controller.
The query below is performed from a Linux machine just to eliminate the query tools attempts on Windows to perform GSSAPI authentication in the background.
ldap1 small
Just to decipher the syntax above:

-h descartes.antid0t.net perform the query against host descartes.antid0t.net
-b ” Use RootDSE as the search base
-x Use simple bind
-LLL Print responses in LDIF format without comments and version
-s base Do base search (as opposed to subtree or onelevel)
‘objectClass=*’ LDAP filter which basically means: return anything you find

Not much, right? Just enough to be able to negotiate the correct authentication dialect, learn about LDAP protocol versions supported, enumerate the partitions and acquire some more details about the LDAP semantics supported by the server.
Notice that I had to use “base” scope query. Trying to perform “Subtree” or “OneLevel” query would yield the DC requiring authenticated bind:

ldap2 small Enabling anonymous LDAP operations

  1. Launch ADSI Edit (part of support tools) and navigate to:
CN=Directory Service,CN=Windows NT,CN=Services,

Where <forestRoot> is the root domain of your forest (in my case this is DC=antid0t,DC=net)
anonym1

  1. Right click the “CN=Directory Services” container, choose “Properties” from the context menu and scroll down to the dsHeuristics attribute

ldap4

  1. If the attribute is not set (has no value), fill in “0000002” in the value field. The last (seventh) character is the one that controls the way you can bind to LDAP service. “0” or no seventh character means that anonymous LDAP operations are disabled. Setting the seventh character to “2” permits anonymous operations (you are still subject to Access Control Lists of the objects in AD)

anonym3

Warning: if the attribute already contains a value, make sure you are changing only the seventh character from the left – this is the only character that needs to be changed in order to enable anonymous binds. So for example if the current value is “0010000”, you will need to change it to “0010002”.
If the current value is less than 7 characters, you will need to put zeros in the places not used: “001” will become “0010002”

  1. Make yourself a cup of coffee and wait till the change is replicated to all you DCs in the forest. The new value will be picked up without any need for server reboots or service restarts. Meanwhile you can get a bit more details about the process from MS KB article 326690.

Let’s test it:
ldap6 small
As you can see, now we are allowed a little more: we are allowed to perform “Sub” queries against all the AD partitions. Though this step allows unauthenticated operations against AD, only a very small subset of attributes are being exposed. The step can be compared to opening the lobby door of an apartment building – you can travel around, but all the doors to the apartments are closed.

Granting anonymous read access

This step involves granting “NT AUTHORITY’\ANONYMOUS LOGON” (well know security principal) access to objects you want to be able to be located by the means of anonymous lookups. This can be compared to opening some doors to the apartments inside the building.
Let’s give it a try and expose some details about one of my computers to the public:

  1. Open Active Directory Users and Computers.
  2. Make sure “View Advanced Features” is checked.
  3. Navigate to the object you want to expose it’s information and double click it.
  4. Go to Security tab and click Add button.
  5. Type in ” ANONYMOUS LOGON” and acknowledge the dialog.
  6. In the ACL you will notice that now ” ANONYMOUS LOGON” has access to some property sets of the computer object (you can actually grant more granular access permissions to the object, but this is beyond the scope of this article).

ldap7
Let’s test it:
ldap8 small
Hey! This didn’t work! Well, apparently there is a good reason for that: you need to grant at least “List Contents” permission to the “ANONYMOUS LOGON” on the OU the object, you are querying for, resides in.
How do you do that?

  1. In Active Directory Users and Computers, right-click the OU the object is located in and choose Properties.
  2. Click the Security tab and click advanced.
  3. Click the Add button and in the dialog that opens type in “ANONYMOUS LOGON”.
  4. Acknowledge the dialog. This will open a new dialog window.
  5. In the “Apply to” drop-down box choose “This object only” and tick the “List Contents” checkbox as shown in the picture:

ldap9
Now let’s try it again:
ldap10
Hurray! Now it works.
Happy binding!