Technical Analysis of GLPi Blind SQL Injection

This article provides an in-depth technical analysis of CVE-2022-31061, a blind SQL injection vulnerability discovered in GLPI during LDAP authentication. This vulnerability was tested on GLPI version 10.0.1. We explore the exploitation process, pinpointing the exact location and underlying causes of the vulnerability.

You can download the vulnerable version of GLPI from the following URL: https://github.com/glpi-project/glpi/releases/download/10.0.1/glpi-10.0.1.tgz

First, we need to activate LDAP authentication from the settings so that it appears as a login source in the menu, as shown below:

Pasted image 20240626220558 - Copy

LDAP authentication can be easily activated by navigating to Home > Setup > Authentication > LDAP directories, and adding a new directory.

Pasted image 20240626220628 - Copy

Set the directory to active by selecting ‘Yes’ and provide an appropriate name for the directory. The name itself doesn’t affect the functionality.

Pasted image 20240626220643 - Copy

We entered a test username and password, and selected ldap-auth as the login source we created earlier.

Pasted image 20240626220547

By capturing the request, we can see how our data is being sent. The most important piece of information is the auth parameter.

Pasted image 20240626220933 - Copy

The code snippet shows part of the login process in /glpi/front/login.php. Here, we can see that the auth parameter is being checked around line 68. Then, on line 88, it’s passed to the login() function. The values of the parameters being passed are visible in the ‘Locals’ variables area.

Pasted image 20240626221255 - Copy

The login() function in the glpi/src/Auth.php file appears to handle login requests. When the function receives an auth parameter with a value like ldap-1, it splits the value into an array containing two elements: "ldap" and "1". The first element, "ldap", represents the authentication method, which is checked around line 742. If the method is LDAP, the code jumps to another function to proceed with LDAP authentication.

Pasted image 20240626221517 - Copy

The code creates a new array named search_params. This array will contain three elements used in the SQL query.

The three elements in the search_params array are:

  • 'name': Represents the username entered by the user during login.
  • 'authtype': 3 indicate that LDAP authentication is being used.
  • 'auths_id': This element represents the directory ID associated with the LDAP authentication. It is retrieving this value from the $this->user->fields["auths_id"] variable.

Pasted image 20240626221750 - Copy

In the file glpi/src/CommonDBTM.php, the function getFromDBByCrit() constructs an SQL query using the crit parameter. This query is executed directly without any sanitization. This means user input might be directly included in the query, making the application vulnerable to SQL injection attacks.

The execution occurs on line 385, with the result being stored in the iter variable. The complete SQL query can be observed in the “Local” variables section.

SELECT `id` FROM `glpi_users` WHERE `name` = 'test' AND `authtype` = '3' AND `auths_id` = '1'

Pasted image 20240626222053 - Copy

We attempted a SQL injection attack using the following payload:

ldap-1'+UNION+SELECT+SLEEP(5) #+

This payload causes the application to pause for 5 seconds, demonstrating that it is vulnerable to SQL injection.

Pasted image 20240626222253 - Copy

Pasted image 20240626222314 - Copy

Our payload was successfully injected into the SQL query, causing the application to hang for 5 seconds.

Pasted image 20240626222408 - Copy

I did not attempt to write a complete exploitation due to time constraints. However, for a fully functional proof of concept that can actually extract data, you can refer to this PoC: https://github.com/Feals-404/GLPIAnarchy/blob/main/exploits/CVE202231061.go

Thank you for reading!.

Written on June 27, 2024