In July 2018 I informed Fortinet development team about a vulnerability I discovered in the way the FortiGate (version 6.0.2 and earlier) managed the LDAP credentials stored in the device, this allowed an administrator with read access to modify the LDAP request to point to another server and thus capture the credentials in plain text. In this post I will explain how I discovered the vulnerability and certain recommendations for Active Directory administrators when configuring service accounts for LDAP.
I want to thanks Fortinet Team who kept the communication active from the moment I reported the vulnerability until the resolution of it; We discussed how this could be abused by a cybercriminal and in November 2018 Fortinet made the vulnerability public and thanks me on their website https://fortiguard.com/psirt/FG-IR-18-157 for responsible disclosure and assigned the CVE ID CVE-2018-13374 to the discovery.
What is a CVE? Common Vulnerability Exposure, is a list of public information security vulnerabilities. It helps identifying each vulnerability, assigning each one a unique code.
Explanation of the Discovery
While configuring LDAP in the FortiGate, I noticed that after saving the configuration when I tried to edit it back the password box was filled with *****
At that time I asked myself, what if I could read this password? I opened Burp Suite to analyze the request and when I clicked on “Test Connectivity”, I noticed that it was generating a GET request with some parameters in json format.
My attention was drawn to some variables: server, port and secure. As this request is being made from my browser, it means that I have control of its content and if the FortiGate is not applying internal controls it could accept any value I sent. At that moment I thought, What would happen if I change the IP to my machine? I started netcat on my machine, listening on port 389 and edit the IP address in the request, and I got the following result:
Eureka! I can make the FortiGate send me the LDAP password in plain text.
I continued with my research, looking for a way to protect my credentials and configured LDAPS, this is the variation of LDAP that incorporates SSL to transfer credentials in a secure way. After making the configuration, and trying to connect this was the result.
Now the password is encrypted and we can not read it, however, let’s compare both requests and highlight the most important fields:
The request with LDAPS change the port to 636 (LDAPS’s default port), changes the value of secure to 2 and includes the certificate in the variable ca.
However, at that moment I asked myself, What would happen if I change the value of the secure variable to how it was with the LDAP (“secure”: 0)? and here the result:
In this way I was able to capture the LDAP credentials of the FortiGate, regardless of whether the connection is encrypted or not. But not everything ended here, continuing the tests I created a read-only user and to my surprise, this could also extract the LDAP credentials.
This was very critical to me, because some administrators share certain tasks with other departments and/or users, and usually create read-only accounts for certain tasks, if this is the case, any user with read or write permissions could obtain the LDAP credentials, if an accounts with high privileges it’s being used this could result in compromising the entire Active Directory.
Python Script - CVE-2018-13374
To simplify the testing of this vulnerability I created a script in python3 that performs the entire process of user capture the LDAP credentials.
The source code is in my Github repository.
Fortinet fixed the vulnerability in version 6.0.3, those who use previous versions are exposed to this vulnerability. I would like to mention some others things:
- There are no updates of this vulnerability for versions 5.4 and 5.6.
- A user with write privileges can still obtain the credentials, the correction only applies to read-only users.
This recommendations are for any integration with Active Directory, not only FortiGate LDAP. When configuring service accounts that need some kind of integration with Active Directory, it’s common to use accounts with more privileges than needed (example Domain Admins), this practice can affect organizations if these accounts are compromised by some methods.
For administrators when configuring LDAP service accounts, here are some recommendations:
- Create an account for specific purposes, avoid reusing accounts in multiple services.
- Set complex passwords, with at least 25 characters.
- Avoid using groups such as Domain Admins for these accounts.
- In most cases it is not necessary to use an account with administrative privileges, you can use a regular account for these configurations.
- In case that more privileges than the regulars are necessary, specifically assign the necessary privileges.
- Apply special controls to service accounts such as:
- Monitoring of logins or queries to Active Directory.
- Restrict the login, to avoid that in the case of compromised it can’t be used by an attacker.
- Configure special permissions for the necessary attributes.
This vulnerability opens the possibility to discover other solutions with the same problem. I urge the curious to test the solutions they handle and find more vulnerabilities of this type to prevent them from being used by a cybercriminal before being publicly known.
God bless you!
Serving Christ is not a task, but a relationship. Friends of God Jn 15:15