Contents

CVE-2022-4566

SQL Injection at Rouyi framework (CVE-2022-4566)

1. Description and Impact

CVE-2022-4566 is a critical vulnerability identified in the RuoYi Framework. This vulnerability occurs in the file com/ruoyi/generator/controller/GenController and is related to SQL injection attacks. Manipulating this file allows an attacker to execute arbitrary SQL commands, potentially compromising the security, integrity, and availability of the system.

Type Required Authentication ?-day CVSS Version Affected
SQL Injection Yes n-day 9.8 (NIST) ≤ 4.7.5

2. Root cause analysis

First, the application allows users to create tables by sending a POST packet containing SQL statements to the endpoint /tool/gen/createTables

https://github.com/user-attachments/assets/b34c589f-0f82-4353-b468-99a56d3dd005

Success create table:

https://github.com/user-attachments/assets/ffa17fc1-fccf-4a3f-90dc-c8e9d555c27e

The vulnerability occurs here when an attacker can inject arbitrary SQL commands into the user input.

Debug:

https://github.com/user-attachments/assets/4ed505ed-97c9-48b3-9585-f49a276945dd

Initially, the filterKeyword() method receives the sql value of String type, which is the user’s input.

Inside the filterKeyword() function, the application checks if there is input using the isEmpty() function. If there is, it moves to the next statement.

Here, the application uses the StringUtils.split() method to split the SQL_REGEX string into an array of SQL statements based on the pipe (|) delimiter, then assigns it to the sqlKeywords array.

https://github.com/user-attachments/assets/21a50d34-334d-460e-afeb-5555d4d43b17

https://github.com/user-attachments/assets/5ec28d96-6815-483d-a03d-a26b82239be5

Next, the application iterates through all elements of the sqlKeywords array, with sqlKeyword successively taking the value of each SQL statement in the sqlKeywords array.

https://github.com/user-attachments/assets/75490d0b-0c9d-40a3-825e-de3080cbf42a

The application uses the indexOfIgnoreCase() method to find the first occurrence of the sqlKeyword array in the value string, case-insensitive. If indexOfIgnoreCase() returns a value > -1, it means sqlKeyword has been found in value. This condition checks if the value string contains any SQL statement matching the blacklist.

If an SQL statement is found in value, this code snippet will throw an Exception: UtilException."参数存在SQL注入风险" which means Parameter has risk of SQL Injection attack.

After validating the input, the application will continue to run.

https://github.com/user-attachments/assets/bf803a4f-c20f-4356-addd-59ee948de5b4

Since the application allows multiple statements to be executed simultaneously, it uses the SQLUtils.parseStatements() method to split the input SQL string into a list of SQL statements and then assigns it to the sqlStatements

List<String>tableNames = new ArrayList<>(); : Creates a list to store the names of created tables.

https://github.com/user-attachments/assets/4c0a8a69-f5d8-47df-b70d-413f54e67152

Next, the application iterates through each SQL statement in sqlStatements with the element sqlStatement.

https://github.com/user-attachments/assets/27c1ca44-a6a8-4172-9589-dd915e274593

Here, the application checks if the statement is CREATE TABLE by using instanceof. If true, it converts that statement to a MySqlCreateTableStatement object.

Next, the application will call the genTableService.createTable method to execute the SQL statement.

https://github.com/user-attachments/assets/c19807bb-62b1-493c-9f4b-222fdd228d24

If successful, it retrieves the table name and adds it to the tableNames list.

If an error occurs, the application will jump to the catch block and output an error message along with e.getMessage() containing the result of the newly passed SQL statement.

→ This is the Sink of the vulnerability

https://github.com/user-attachments/assets/a6f1e2e3-fd19-4771-b9af-6bc6c1237a05

→ This is an Error-Based SQL Injection vulnerability.

3. Steps to reproduce

Send a POST request to the endpoint /tool/gen/createTable with the Payload:


sql=CREATE table keke as SELECT/**/* FROM sys_job WHERE 1=1 
AND/**/extractvalue(1,concat(0x7e,(select/**/version()),0x7e));

https://github.com/user-attachments/assets/06bd38e4-3cae-413d-b5ac-893531ede722

4. Recomendation

In version 4.7.6, RuoYi added a commit with the code 167970e5c4da7bb46217f576dc50622b83f32b40 to add some statements to the blacklist and not directly return e.getMessage() to summarize error information to avoid SQL injection.

References

https://gitee.com/y_project/RuoYi/issues/I65V2B

CVE-2022-4566 Details

https://www.cvedetails.com/cve/CVE-2022-48114/?q=cve-2022-48114