Recently, I was describing to a client how to correct a filter injection in their code based on the LDAP API they were using and I was struck by how poorly constructed the API was. In this case, it was the "cfldap" tag provided by Adobe ColdFusion [2][3]. Throughout the documentation, I see no mention anywhere about the dangers of dynamically constructing search filters. In addition, there's apparently no function provided to escape special characters in user-supplied strings for use in filters or DN syntax. Of course any developer could read the fairly straight-forward RFC on the topic [4] and write an encoding function themselves to convert things like "(" to "\28". But as I mentioned in my previous post, one can't really expect developers to be experts in external technologies like LDAP, directory servers, and filter syntax. To add insult to injury, the documentation even provides code examples which are vulnerable to filter injection:
...
<form action="cfldap.cfm" method="POST">
<input type="text" name="name"><br><br>
<input type="submit" value="Search">
</form>
<!--- make the LDAP query --->
<!-- Note that some search text is required.
A search filter of cn=** would cause an error -->
<cfif (isdefined("form.name") AND (form.name IS NOT ""))>
<cfldap
server="ldap.airius.com"
action="query"
name="results"
start="ou=People, o=Airius.com"
scope="onelevel"
filter="(&(cn=*#form.Name#*)(l=Santa Clara))"
attributes="cn,sn,ou,mail,telephonenumber"
sort="ou,sn"
maxrows=100
timeout=20000
>
...
There you go, taking a value straight from the form submission and inserting it into a query. How can you expect the typical ColdFusion developer to protect their code from this kind of vulnerability when the API and documentation is effectively setting them up for failure? As one can imagine, ColdFusion isn't alone in this kind of API negligence:
- PHP's LDAP API does provide an escaping function [5], but it isn't mentioned at all on the ldap_search page, and this page even provides a code example that is almost as vulnerable as ColdFusion's [6].
- Under Java, the Apache Directory LDAP API does not appear to offer any escaping function and also doesn't mention anything about the risks of dynamically constructed filter expressions [7].
- For .NET, I have yet to find a method that allows one to escape values prior to including them in search filters (outside of some provided in older C++ APIs). The DirectorySearcher class doesn't seem to contain any mention of the security risks of dynamic filter expressions [8]. Other MSDN pages [9][10] do discuss the escape syntax, but I haven't yet found any security warnings associated with it.
- Query template APIs, A.K.A. "parameterized prepared statements". Here, programmers are expected to provide a query template along with a series of (potentially untrusted) dynamic values, each mapped to a particular element within the template. Encoding is automatically performed based on data type (or is unnecessary if the database server supports parsing the query templates).
- Object-Relational Mapping (ORM) or more abstract APIs. Here, an abstract object representation is provided to developers which effectively eliminates the need to construct queries in most situations.
For those keeping score, here's a summary of the limited set of LDAP APIs I've looked at so far and how well they fair in providing safe interfaces and documentation:
API | Unsafe Examples | Security Risks Documented | Encoding Function | Filter Templates | ORM-like API |
---|---|---|---|---|---|
ColdFusion 10 | YES | NO | NO | NO | NO |
PHP 5 | YES | NO | YES | NO | NO |
Apache | NO | NO | NO | NO | NO |
.NET | NO | NO | NO | NO | NO |
python-ldap | NO | YES | YES | YES | NO |
Perl Net::LDAP | NO | YES | NO | NO | NO |
There's a lot of documentation to cover here, so it's certainly possible I missed something in one or more of these. If I misrepresented anything, post a comment below and I'll happily fix it.
References
- LDAP Injection: Are your web applications vulnerable? -- Sacha Faust, SPI Dynamics Inc.
http://www.networkdls.com/articles/ldapinjection.pdf - ColdFusion Documentation Wiki: cfldap
https://wikidocs.adobe.com/wiki/display/coldfusionen/cfldap - Adobe ColdFusion 10 - Querying an LDAP directory
http://help.adobe.com/en_US/ColdFusion/10.0/Developing/WSc3ff6d0ea77859461172e0811cbec0eb56-7fe5.html - RFC 4515: LDAP String Representation of Search Filters
https://tools.ietf.org/search/rfc4515 - PHP: ldap_escape
http://php.net/manual/en/function.ldap-escape.php - PHP: ldap_search
http://php.net/manual/en/function.ldap-search.php - Apache Directory API: Searching (...)
http://directory.apache.org/api/user-guide/2.3-searching.html - MSDN: DirectorySearcher.Filter Property
http://msdn.microsoft.com/en-us/library/system.directoryservices.directorysearcher.filter(v=vs.110).aspx - MSDN: Search Filter Syntax
http://msdn.microsoft.com/en-us/library/aa746475%28v=vs.85%29.aspx - MSDN: Creating a Query Filter
http://msdn.microsoft.com/en-us/library/ms675768%28v=vs.85%29.aspx