SSRF protocol smuggling involves an attacker injecting one TCP protocol into a dissimilar TCP protocol. A classic example is using gopher (i.e. the first protocol) to smuggle SMTP (i.e. the second protocol):
The key point above is the use of the CRLF character (i.e. %0D%0A
) which breaks up the commands of the second protocol. This attack is only possible with the ability to inject CRLF characters into a protocol.
Almost all LDAP client libraries support plaintext authentication or a non-ssl simple bind. For example, the following is an LDAP authentication example using Python 2.7 and the python-ldap library:
In many LDAP client libraries it is possible to insert a CRLF inside the username or password field. Because LDAP is a rather plain TCP protocol this makes it immediately noteworthy.
You can see the CRLF characters are sent in the request:
Real World Example
Imagine the case where the user can control the server and the port. This is very common in LDAP configuration settings. For example, there are many web applications that support LDAP configuration as a feature. Some common examples are embedded devices (e.g. webcam, routers), Multi-Function Printers, multi-tenancy environments, and enterprise appliances and applications.
Putting It All Together
If a user can control the server/port and CRLF can be injected into the username or password, this becomes an interesting SSRF protocol smuggle. For example, here is a Redis Remote Code Execution payload smuggled completely inside the password field of the LDAP authentication in a PHP application. In this case the web root is ‘/app’ and the Redis server would need to be able to write the web root:
Client Libraries
In my opinion, the client library is functioning correctly by allowing these characters. Rather, it’s the application’s job to filter username and password input before passing it to an LDAP client library. I tested out four LDAP libraries that are packaged with common languages all of which allow CRLF in the username or password field:
Library | Tested In |
---|---|
python-ldap | Python 2.7 |
com.sun.jndi.ldap | JDK 11 |
php-ldap | PHP 7 |
net-ldap | Ruby 2.5.2 |
Summary Points
- If you are an attacker and find an LDAP configuration page, check if the username or password field allows CRLF characters. Typically the initial test will involve sending the request to a listener that you control to verify these characters are not filtered.
- If you are defender, make sure your application is filtering CRLF characters (i.e. %0D%0A)