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
Success create table:
The vulnerability occurs here when an attacker can inject arbitrary SQL commands into the user input.
Debug:
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.
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.
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.
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.
Next, the application iterates through each SQL statement in sqlStatements
with the element sqlStatement
.
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.
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
→ 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));
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
https://www.cvedetails.com/cve/CVE-2022-48114/?q=cve-2022-48114