5.7K Star 41.1K Fork 22.3K

GVP若依 / RuoYi

 / 详情

因为sql语句过滤不当引起的sql注入和dos攻击

已完成
创建于  
2023-05-25 18:01

在若依全版本(也可能是4.x往后的版本),使用了正则表达式判断order的参数是否正确,这避免了大部分sql注入

package com.ruoyi.common.utils.sql;

import com.ruoyi.common.exception.UtilException;
import com.ruoyi.common.utils.StringUtils;

/**
 * sql操作工具类
 * 
 * @author ruoyi
 */
public class SqlUtil
{
    /**
     * 定义常用的 sql关键字
     */
    public static String SQL_REGEX = "and |extractvalue|updatexml|exec |insert |select |delete |update |drop |count |chr |mid |master |truncate |char |declare |or |+|user()";

    /**
     * 仅支持字母、数字、下划线、空格、逗号、小数点(支持多个字段排序)
     */
    public static String SQL_PATTERN = "[a-zA-Z0-9_\\ \\,\\.]+";

    /**
     * 检查字符,防止注入绕过
     */
    public static String escapeOrderBySql(String value)
    {
        if (StringUtils.isNotEmpty(value) && !isValidOrderBySql(value))
        {
            throw new UtilException("参数不符合规范,不能进行查询");
        }
        return value;
    }

    /**
     * 验证 order by 语法是否符合规范
     */
    public static boolean isValidOrderBySql(String value)
    {
        return value.matches(SQL_PATTERN);
    }

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

但是因为允许多个字段排序且并没有对字段的数量进行限制,order后的值仍然是用户部分可控的,所以可以构造一个庞大的请求,因为过于庞大,我将请求的内容以附件的形式发送

请求将调用java和mysqlyunxingsql语句,这个请求会大量消耗服务器的资源,cpu占用率很高,服务其运行缓慢,最终服务器崩溃,整过过程只需要很少量的请求就会导致ruoyi的崩溃(具体会不会崩溃取决于服务器性能,若果是2核2g的个人服务器,可能会导致整个服务器系统的崩溃),服务无法访问,但是内存仍然占用(大概1000个左右,测试环境使用4核8g的服务器)
同时,order by后接into可以向不包含.等特殊字符的文件中写入数据,采用16进制的方式代替文件名字符串可以绕过对引号的检测,也可以占用大量服务器的磁盘空间。
image

image

poc.txt

评论 (7)

springkill 创建了任务
springkill 任务状态待办的 修改为进行中
springkill 任务状态进行中 修改为待办的
展开全部操作日志

您好,请问贵团队对此有何看法,谢谢

这个不算是BUG,只是传入的参数过多导致的,和下载数据量差不多,这个最好的办法就是自己去限制一下,

post限制请求大小,或者order by 限制一下,

com.ruoyi.framework.web.page.PageDomain.getOrderBy

正常情况下不应该允许传入这么多参数的吧,怎么能不算是bug

http可以设置请求参数大小,可以自己去设置 和框架没有关系,或者自己对order by截取一下长度,或判断超出xxxx抛出异常,这个在startpage方法里面可以做这些。

如果一个使用者不了解ruoyi的这个潜在问题,没有加以限制,攻击者就可以用少量的几台机器发起dos攻击,甚至无法使用ip黑名单进行封禁,因为请求数量过低
就像你回答的“对order by截取一下长度”,这就相当于使用者自己修复了这个问题,我觉得作为一个易用的框架应当要求使用者即使不熟悉代码也能轻松上手并且避免一些安全问题,如果全都是自己修改,那么前面的shiro反序列化是否也是因为用户没有修改默认密钥导致的,也不算问题,fastjson也是因为使用者没有正确设置autoType导致的,也不能算作安全问题呢。
传入数据,执行操作,只不过,一个是执行命令,另一个是进行服务器资源的大量损耗,这不简单是带宽损耗而是mysql的计算问题,还希望能仔细考虑

若依 任务状态待办的 修改为已完成
springkill 任务状态已完成 修改为待办的
若依 任务状态待办的 修改为已完成

输入图片说明
ruoyi系统中的这个拒绝服务可以称得上是一个安全问题,相似的漏洞如上图所示,按理说这种限制 不应由用户自身进行 ,因为 大部分用户不会在使用时看源码和进行测试 ,字段数量一共就那么几个传入字段不该在默认情况下可以达到上限
并且该漏洞的 触发点不在于数据量的大小而在于mysql在一个请求中不断地进行上万次排序导致的性能损耗以及cpu,内存的占用 ,不只是网络层面那么简单

springkill 任务状态已完成 修改为待办的

:ok_hand: 已经限制了,更新仓库最新代码即可。排序属性orderBy参数限制长度
https://gitee.com/y_project/RuoYi/commit/e8d8325eadda7c41360621b9fc511c4d97cbffd5

若依 任务状态待办的 修改为已完成

登录 后才可以发表评论

状态
负责人
里程碑
Pull Requests
关联的 Pull Requests 被合并后可能会关闭此 issue
分支
开始日期   -   截止日期
-
置顶选项
优先级
参与者(2)
1151004 y project 1578942802
Java
1
https://gitee.com/y_project/RuoYi.git
git@gitee.com:y_project/RuoYi.git
y_project
RuoYi
RuoYi

搜索帮助