Microsoft's official enterprise support blog for AD DS and more
It’s Randy again, here to discuss LDAP security. Lightweight Directory Access Protocol is an interface used to read from and write to the Active Directory database. Therefore, your Active Directory Administration tools (i.e. AD Users and Computers, AD Sites and Services, etc.) as well as third party tools are often going to use LDAP to bind to the database in order to manage your domain. As you can imagine, we rely on Windows security to authorize what users can do when accessing this important database. Access to this database is controlled by the Directory System Agent (DSA), which is represented by Ntdsa.dll on a domain controller. Ntdsa.dll runs as a part of the Local Security Authority (LSA), which runs as Lsass.exe.
The process of granting access is a two step process; Authentication and Authorization. This blog post will focus on the Authentication portion (verifying the user’s identity.) If you would like to learn more about the Authorization process, please read my post on security tokens. Objects in the Active Directory database conform to the same rules as other Windows objects. They have permissions and privileges that govern what the authenticated user can do.
I use the LDP.EXE utility in Windows 2008 to reproduce all of the scenarios that follow. This tool is a client GUI to connect, bind and administrate Active Directory. You also want to download Network Monitor if you are troubleshooting an LDAP problem or want to follow along in your own network traces.
If you open up LDP and choose “Connect…” under the Connection menu and do not put in any parameters:
And choose bind as currently logged on user:
The first thing that you will notice is that it just works. We locate a valid domain controller when we do not specify a target DC by leveraging the DC Locator process and we bind as the currently logged on user by leveraging the security packages included in Windows. So what do we see in a network trace? We will be filtering on LDAP when opening in Network Monitor 3.3.
Why do we get results in LDP.exe before we even Bind?
The first set of traffic that we see is a couple of LDAP Search Requests and Search Responses. You can see this in the Description field of the Frame Summary:
So why do we see an LDAP search request before we do the LDAP bind? This is because we first access the “RootDSE” partition of the Active Directory Database as an anonymous connection to query information on the rules to bind and authenticate to this DSA. We allow anonymous access to this root, but in Windows Server 2003 and later we deny anonymous access to all other partitions in Active Directory. You can change this setting by changing the DSHeuristics value; this will be a forest-wide change for the behavior of all domain controllers.
You can see the LDAP request parameters as “BaseDN: NULL” if you look at the Frame Details pane of the LDAP search request. Expand the “LDAP: Search Request “ , then expand the “Parser: Search Request” , then expand the “Search Request”:
“BaseDN” is the container where the search begins in the LDAP query. NULL is going to be the RootDSE of the domain controller. This is why results return in the right hand pane of the LDP utility before we even bind.
The “LDAP: Search Result” shows this same data if you expand the “LDAP: Search Result”, then expand the “Parser: Search Result”, then expand the “SearchResultEntry”:
Notice that the results in the trace are identical to what displays on the LDP.exe result pane. One important piece of information that we get is “supportedSASLMechanisms”. These are the supported security mechanisms that we can use in our LDAP bind. We will discuss this later in the post.
Why do we log on as ‘Null’ when we select to pass credentials?
So next we bind and select the default of currently logged on user. In the result pane of LDP it shows that we are logging on as ‘NULL’.
I consider this more as an idiosyncrasy of the tool and not completely accurate. When we perform the Bind, we do present ‘NULL’ credentials, but specify SASL as the authentication type. At this point, we are passing the authentication process off to the SASL mechanism to complete. We can see evidence of this in the network trace.
Looking at the Bind Request in the frame details pane, you will see some interesting information as you expand out the LDAP packet:
Here we see that we are passing NULL credentials, but negotiate SASL authentication. Simple Authentication and Security Layer (SASL) is a method for adding authentication support to connection-based protocols. So basically, LDAP binds with NULL credentials because we are handing off the logon process to SASL and letting it do all the work. We see details of the negotiation process in the bind request and where we present the Kerberos session ticket as a result of selecting the GSS-SPEGNO SASL mechanism:
So how does SASL provide authentication?
For detailed information, you can check out the IETF explanation of SASL. Similar to how the Security Support Provider Interface (SSPI) uses security packages, SASL will use registered SASL mechanisms to complete the authentication process. During the initial LDAP query for supportedSASLMechanisms described earlier. We retrieve a list of all the mechanisms from which the client and server will choose. Below is a list of the default mechanisms in Windows Server 2008.
GSS-SPNEGO, in turn, uses Kerberos or NTLM as the underlying authentication protocol.
GSSAPI, in turn, always uses Kerberos as the underlying authentication protocol.
Used to allow a client to authenticate itself using information provided outside of the LDAP communication. Can be used to present certificates to establish TLS or IPSec.
Encrypts authentication using Digest-MD5
The LDP tool allows you to choose various mechanisms and is a great tool to test connections when other tools fail. You can select the appropriate bind specifications in order to closely simulate what your application is trying to perform.
The application will decide how it will bind to the database by what functions are used to establish the connection (i.e. LDAP_Simple_bind, LDAP_Sasl_bind, etc )
What about LDAP signing?
If you have ever looked through security settings in Group Policy, you may have stumbled on a couple related to LDAP.
Domain controller: LDAP server signing requirementsNetwork security: LDAP client signing requirements
These are both under Computer Configuration \ Windows Settings \ Security Settings \ Local Policies\Security Options .
Signing LDAP traffic is a way to prevent man-in-the-middle attacks. By signing the LDAP traffic, this guarantees that the LDAP response did originate from the DC of whom the request was made. With these settings enabled, computers would not be able to intercept the traffic and modify the data on the wire. You can see the digital signing value in the network trace below. This value will be on every LDAP response from the DC where signing is done.
What is a Simple Bind?
An LDAP Simple Bind will send username and password in clear text to provide credentials to the LDAP server. This is not secure, so if your application is using simple binds it needs to be reconfigured or updated. You can create a Simple Bind using this option in LDP.exe or calling the LDAP_Simple_bind function in your code. In a network trace we can see the username and password in the LDAP BIND Frame.
With Signing required in my domain, I was unable to perform a simple bind with LDP.exe. I received the error “LDAP_Simple_Bind failed: Strong Authentication Required”.
What is an Anonymous Bind?
As mentioned earlier, every LDAP connection is going to perform an anonymous bind to query RootDSE of the LDAP server. Also mentioned earlier, by changing the DSHueristics value on your AD Forest, you can permit Anonymous Bind LDAP searches for all the AD Partitions. The anonymous bind is still restricted by the permissions on the Directory Objects themselves. I did an anonymous bind and performed a search for all the user objects in the domain and resulted in only one user because I had manually granted permissions on that User object.
I also had to grant permissions on the Organization Unit that contained the user; otherwise the anonymous logon was unable to traverse containers where it had no permissions. I did not have to grant access to the Domain Naming Context at the root. I was able to set permissions in “AD Users and Computers” by selecting the “Advanced Features” option in the View Menu.
What about LDAPS?
LDAPS uses SSL/TLS technology to establish an encrypted tunnel between the client and the LDAP server. The tunnel is encrypted with the LDAP server’s PKI Certificate, this way no one else can read the traffic except for the client and LDAP server so the Client is free to perform a simple bind and safely pass the credentials in clear text. LDAPS is an entirely different subject that deserves its own post. Luckily James Carr has written it, check it out here.
Developers have a plethora of ways to bind to an Active Directory database. This provides supportability for numerous flavors of LDAP clients, but it does require some configuration on the part of the AD administrator. Farewell for now…
Randy “Baby Elvis, thank you verah muuuch” Turner
<p>I am running Windows Server 2008 as a DC, AD LDS, AD, WSUS, etc and I'm trying to bnd to the LDAP (via AD LDS) using a 3rd party utility. I can not bind to it at all ...then I found a KB to add userProxy class to the AD LDS but I'm unable to finish creating the object because the userProxy object class does not exist!</p>
<p>I DID import the 2 LDF files but the directions are not clear </p>
<p>Am I supposed to EXport the scheme from AD and import that into AD LDS?????</p>
<p>many KBs say use userProxy ....but in this TechNet KB, it is User-Proxy!</p>
<p><a rel="nofollow" target="_new" href="http://technet.microsoft.com/en-us/library/cc771943.aspx">http://technet.microsoft.com/en-us/library/cc771943.aspx</a></p>
<p>In <a rel="nofollow" target="_new" href="http://technet.microsoft.com/en-us/library/cc731759">http://technet.microsoft.com/en-us/library/cc731759</a>(WS.10).aspx#BKMK_8 I am unable to add the child because the objectclass=userProxy does NOT exist ...and I've even looked at the 2 LDF files ...userProxy IS in there!</p>
<p>What am I doing wrong?</p>
<p>Can you bind to port 389 with LDP.EXE from the same computer running the 3rd party utility?</p>
<p>Here's a good one. We have a multi-tree forest. I ran a quick test using an LDAP browser.</p>
<p>basedn of tree1</p>
<p>bind creds for tree2</p>
<p>search base for tree3.</p>
<p>according to the trace, tree1 autentcated me via simple LDAP bind, but my cred info is stored on tree2. How is this possible? I thought I would get a referral from tree1 dc to tree2 dc.</p>
<p>Does the tree1 DC proxy the ldap bind request?</p>
<p>You are most likely using Digest SSP when binding to the target LDAP DC. This is a challenge\response authentication where the LDAP DC itself will take the credentials and pass them to the user's DC in the user domain. If you take a simultaneous trace from the client and the target DC, you will see the ldap DC forward the authentication to the user's DC.</p>
<p>On the LDAP DC trace, you will see some traffic between the LDAP Bind Request and Response.</p>
<p>There will be an RPC connection between the two DCs on Logon(NRPC)</p>
<p>Good point. This may be the case and here is why I think you are correct. </p>
<p>One of the details I forgot to mention is that the LDAP call is a GC lookup (3268)</p>
<p>This is what is probably happening</p>
<p>1) KDC\LDAP (tree 2)server looks up the user</p>
<p>2) KDC\LDAP Sees that he is in a different partition (tree 3)</p>
<p>3) The KDC\LDAP (tree 2) gets the DN of the user ID and determines it is in another tree (tree 3) </p>
<p>4) The KDC\LDAP (tree 2) proxies the authentication with the KDC\LDAP (tree 3) using digest</p>
<p>Do you have any docs\urls or blogs on this process?</p>
<p>Because you are searching on GC, that DC can answer your query, there is no LDAP referral to a different DC, the first DC that the client talks with does host that partition.</p>
<p>Now all you have to worry about is authenticating the credentials of the client on the DC performing the LDAP Bind and LDAP Search.</p>
<p>Keep in mind that Kerberos has the client do all the authentication legwork. The client goes and gets the tickets and talks to all the DCs and just delivers the session key to the resource of which he is trying to connect.</p>
<p>NTLM and Digest are Challenge\Response authentication methods and makes the target resource do all the work. In this case it is the DSA (directory service attendant) on the DC. Do not be confused that this DC is authenticating the user. This could just as easy be a file share on a file server. In this case the service just happens to be running on a DC.</p>
<p>So with Challenge\Response, the resource requests some information from the client (in your case the user's name and password.) The Resource then asks the Domain Controller responsible for authenticating you the same question and provides him with the response that was given from the client. The DC then tells the resource wether or not the client is who he says he is.</p>
<p>This is the same transaction that you would see if the client was accessing a file share on a file server.</p>
<p>Here is a link to how NTLM works</p>
<p><a rel="nofollow" target="_new" href="http://msdn.microsoft.com/en-us/library/aa378749">http://msdn.microsoft.com/en-us/library/aa378749</a>(VS.85).aspx</p>
<p>Here is a link to how Digest works</p>
<p><a rel="nofollow" target="_new" href="http://technet.microsoft.com/en-us/library/cc780170">http://technet.microsoft.com/en-us/library/cc780170</a>(WS.10).aspx</p>
<p>Great info, thanks.</p>
<p>Is there a way to totally disable anonymous binds in AD?</p>
<p>That is any anonymous bind attempt would be rejected by an appropriate ldap error (like resultcode 48 - inappropriateAuthentication )</p>
<p>There are LDAP servers out which have a config/switch for totally disable anonymous binds like that.</p>
<p>Driving reason: There are many bad applications which do transfer blank passwords to the LDAP bind level. This way a successful anonymous bind is achieved, while the app wrongly assumes the user to be correct. The LDAP server could be a great help of a fix for such situations, while waiting for a proper fix.</p>
<p>Anonymous binds have been disabled in AD LDAP since Win2003 (except to ROOTDSE, which must be anonymous to allow functionality of what LDAP version/controls/etc are supported) - if you are seeing them, someone may have turned those back on in your environment.</p>
<p>326690 Anonymous LDAP operations to Active Directory are disabled on Windows Server 2003 domain controllers</p>
<p><a rel="nofollow" target="_new" href="http://support.microsoft.com/default.aspx?scid=kb;EN-US;326690">support.microsoft.com/default.aspx</a></p>