Active Directory authentication using ldap3 python, how to avoid clear text password

Nik picture Nik · Apr 14, 2017 · Viewed 8.2k times · Source

I know the below question has been asked multiple times and answer which i could find is that get SSL certs.

But how to go around it without SSL?

Here is the problem:

I have been implementing a Rest based API which authenticates a user with Active Directory.

Our security team has concern that passing plain text password from UI to API is a security risk.

But we are doing it because Active Directory needs password in plain text. It just goes in JSON format in a POST request :

{"user":"uname","password":"password"}

Here is the AD auth code that i use from python ldap3 module.

    s = Server(AD_SERVER, port=AD_PORT, use_ssl=True, get_info=ALL)
    c = Connection(s, user=userName, password=password, authentication=NTLM)
    c.bind()

So in above is there a way to send password in any hash or any encrypted format. I am not sure if Active Directory or ldap3 supports such mechanism for this connection.

Any leads would be appreciated.

Answer

benjimin picture benjimin · Apr 15, 2017

LDAP (or the python ldap3 package) supports a variety of authentication (bind) schemes. Some transfer the user's password to the server more or less in plaintext, while others (e.g. NTLM) use cryptography (to prove that the client represents the user, without transmitting the password to the server, e.g. like only transmitting a hash of the password convolved with a unique challenge that was issued to the client by the server).

The problem is that ldap3 tries to implement its own computation of the challenge-response. (This requires the password to be available to python, and is insecure and inconvenient.) Instead it should utilise the SSP Interface, i.e., pass the server's challenge to the client's operating system and let the OS compute the response for sending to the server. The OS will use the credentials from when the user logged on, and does not expose the password to python.

Similarly, the server application should not try to validate the response itself, but instead defer to the server's OS which forwards the challenge/response to the Domain Controller and returns whether they check out.

Some coding will be necessary, but here is an example of python ntlm sspi (applied for http instead of ldap), and there are also some demos in the pywin32 de facto standard library.

Probably however the correct way to do a restful application on a windows domain is to forget about ldap. Instead try to enable Integrated Windows Authentication on your webserver, or try something like flask-Kerberos or PyAuthenNTLM2.