25 February, 2015

Adventures in LDAP Injection: Exploiting and Fixing

Adventures in LDAP Injection: Exploiting and Fixing
Jason Gillam
Author: Jason Gillam
Share:
 

Every pen tester looks forward to that next encounter that includes one of those uncommon vulnerabilities that ultimately result in an exciting session of exploration and learning.  During a recent web penetration test I ran across one of these rare gems when I started seeing some odd behavior on a forgot password form.  In this case I was fortunate to be working virtually across the table from a development team member who could verify our hypotheses by reading through the code.

We had just determined that this form had a username harvesting flaw, where the email address was the username.  What was really odd is that this username harvesting flaw honored wildcards (i.e. ‘*’).  That by itself made for a really cool twist on a harvesting flaw because we no longer needed a dictionary of email addresses.  After looking into the code, my developer counterpart determined that wildcards were being honored because the email input was being concatenated to a LDAP search filter expression.

After a bit more experimentation we determined that we could not only use wildcards, but also append additional logical expressions (e.g. “And”, “Or”) to the filter.  Unfortunately since this form does not return the results of the expression we weren’t able to pull additional record details.  Then it occurred to me: SQL Injection is much like LDAP Injection, only much more common and better understood.  One form of SQL Injection is known as “Blind SQL Injection”, which occurs in situations where a series of yes/no queries can be used to pull information from a database.  It is like a game of 20 questions, e.g.: is there a table that starts with the letter ‘a’?  is there a table that starts with the letter ‘b’? etc….

So if SQL has its “Blind SQL Injection”, doesn’t LDAP have its “Blind LDAP Injection”?  It certainly does!  Within seconds we had worked out the syntax to get a yes/no response based on a guess for the first character of the phone number  LDAP attribute for the user account.  Run this through Burp Intruder and we were quickly able to discern the first, second, third character of the phone number.

This was cool, but we were really curious about whether or not we could retrieve a password hash.  We attempted a few different strategies to pull the password and in the end resorted to online research where we discovered that this particular LDAP implementation didn’t treat the password as a normal attribute and simply wouldn’t return it at all (hashed or otherwise).  Alas… no password.  But we were able to pull several other attributes, the most interesting of which is probably the user’s role (i.e are they an admin?).

So we found and exploited a Blind LDAP Injection flaw… but as a pen tester the job is not over yet.  We also have to provide an appropriate recommendation to address the flaw.  Since LDAP Injection is similar to SQL Injection I decided to start there.  First… can we do parameterized queries with LDAP?  In this case it turns out the answer is “no”.  The implementation was a JNDI search filter, which is actually just a String.  Unless you pull in third party library that does this for you, there really is no alternative to String concatenation.  That’s not very good news for the defensive side, and it only seems to go downhill from there…

What do us security professionals chant when we see injection flaws?  “Input Validation!”  So let’s take a look at that with respect to an LDAP injection flaw on a email address.  According to the OWASP Validation Regex Repository, a valid email address follows this pattern:

        ^[a-zA-Z0-9+&*-]+(?:.[a-zA-Z0-9_+&*-]+)*@(?:[a-zA-Z0-9-]+.)+[a-zA-Z]{2,7}$

For those who don’t understand regular expressions, don’t worry about it.  The important thing to note is that the valid email characters include ‘*’.  This means even with regex-based validation we still have working wildcards!   To address these we need to use output encoding with LDAP’s escape syntax, which is to substitute ‘2a’ for ‘*’, telling the LDAP expression to treat it as a literal ‘*’ instead of a wildcard.  There are actually several more characters that should also be escaped but I have yet to find an up-to-date reference.  OWASP has a Preventing LDAP Injection in Java page that appears to be accurate as of 2008.

So the take-away is: if during a web pen test you at all suspect LDAP on the back end, try wild cards (e.g. *, %) and some LDAP injection payload lists.  LDAP may not provide some of the cool command execution functionality you can get out of SQL Injection flaws but it can still be at least used to gather sensitive data so it is well worth the time and effort.

Jason Gillam is a Senior Security Consultant with Secure Ideas. If you are in need of a penetration test or other security consulting services you can contact him at jgillam@secureideas.com, on Twitter @JGillam, or visit the Secure Ideas – ProfessionallyEvil site for services provided.

Join the professionally evil newsletter

Related Resources