
Static code audit of CVE-2024-57521, an authenticated SQL injection in RuoYi-Vue's generator module, with source-to-sink analysis and a %0b filter bypass PoC.
Figure 1: CVE-2024-57521 SQL Injection Vulnerability Data Flow Audit Diagram
This repository is intended for security research and educational purposes only. Do not use the techniques in this document for unauthorized attacks. All tests were completed in a local static code audit environment.
ruoyi-generator module)ruoyi-generator/src/main/java/com/ruoyi/generator/controller/GenController.javaKey Code:
@PostMapping("/createTable")
public AjaxResult createTableSave(@RequestParam("sql") String sql, @RequestParam("tplWebType") String tplWebType)
{
try
{
SqlUtil.filterKeyword(sql); // Calls the filter before entering business logic
Analysis: A backend administrator can pass arbitrary database table creation statements through the sql parameter of an HTTP POST request. The entry point does not sufficiently restrict user input and directly hands it off to the subsequent filter for processing.
Screenshot Evidence:

· File Location: ruoyi-common/src/main/java/com/ruoyi/common/utils/sql/SqlUtil.java
Core Flawed Code:
// Line 16: Blacklist definition, note the keywords have [trailing spaces]
public static String SQL_REGEX = "\u0008|%0A|and |extractvalue|updatexml|sleep|information_schema|exec...";
// Lines 61-66: Filtering logic
String normalizedValue = value.replaceAll("\\p{Z}|\\s", ""); // First clears all spaces from the input
String[] sqlKeywords = StringUtils.split(SQL_REGEX, "\\|");
for (String sqlKeyword : sqlKeywords)
{
if (StringUtils.indexOfIgnoreCase(normalizedValue, sqlKeyword) > -1)
{
throw new UtilException("Request parameter contains sensitive keyword " + sqlKeyword + ", potential security risk");
}
}
Flaw Analysis: The filter first executes replaceAll("\\p{Z}|\\s", "") to remove all whitespace characters from the input. However, the keywords in the blacklist SQL_REGEX (such as "and ", "select ") have trailing spaces. This causes matching to inevitably fail. As long as the attacker uses %0b (vertical tab) instead of a space after the keyword, the blacklist check can be perfectly bypassed.
Screenshot Evidence:
· File Location: ruoyi-generator/src/main/resources/mapper/generator/GenTableMapper.xml
Key Code:
<update id="createTable">
${sql}
</update>
Analysis: In MyBatis, ${} directly concatenates strings rather than using the safe precompiled #{}. This causes malicious SQL that has bypassed the filter to be sent to the database for execution. This is a typical "blacklist filtering + unsafe concatenation" combination vulnerability.
Screenshot Evidence:
· Method: The attacker uses %0b (MySQL's vertical tab, which falls within the \s matching range) to replace spaces in the SQL statement.
%0b: CREATE table xxx as SELECT%0b111 FROM sys_job WHERE 1=0 AND%0bIF(<condition>, 1, 1/0);filterKeyword method, %0b is matched by \s and cleared, and the string becomes select111 and andIF."select " (with a space), "select111".indexOf("select ") returns -1, successfully bypassing the blacklist interception.${sql} concatenates it into the database.%0b is treated as a valid whitespace character, and the SQL is successfully injected and executed.· Detection Principle: Use IF(<condition>, 1, 1/0) as the detector for boolean blind injection.
· Condition is false: Triggers a division-by-zero error, and the server returns HTTP 500.
· Condition is true: Normal, no error.
· Extraction Method: Using binary search, database data can be guessed bit by bit.
This vulnerability is a typical bypass caused by "incomplete remediation." When the developer fixed a previous similar SQL injection, they introduced a blacklist mechanism, but overlooked that the blacklist depends on spaces, while the preceding logic that clears spaces breaks the blacklist's matching conditions, ultimately leading to a new bypass (CVE-2024-57521).
· Abolish the blacklist mechanism: Do not rely on blacklists; a whitelist mechanism is the foundation of security.
· Use precompilation: Change ${sql} in MyBatis to the #{} precompiled approach. If SQL must be passed dynamically (such as for table creation or Order By), strict Abstract Syntax Tree (AST) parsing or strict parameter validation should be used.
· Improve the filter: If a blacklist must be used, remove the trailing spaces from the blacklist keywords and perform unified normalization before comparison (e.g., uniformly convert to lowercase, replace %0b etc. with spaces).
· NVD - CVE-2024-57521 · RuoYi-Vue Gitee Repository
poc/poc_boolean.py (Note: It is recommended to rename the file to poc_error_based.py later to match the actual logic)extractvalue() function to trigger an XPath error, and extracts data by regex-matching XPATH syntax error: '~...~'. The Payload uses /**/ instead of spaces to bypass blacklist filtering.
CREATE//table//{random table name}//as//SELECT/**/extractvalue(1,concat(0x7e,({query statement}),0x7e))
%0b WAF bypass and extractvalue error-based injection was successfully verified. The script has stably extracted the MySQL version (5.7.26), the current database name (ry), and the database connection user (root@localhost).