ruoyi-v4.7.8-RCE分析
前言
应朋友的邀约看了看CNSS的夏令营题,基本是去年招新的原题,很简单。出了一道ruoyi不是原题,版本是4.7.7,这里也是直接拿下一血,借此做一个分析。
其实Ruoyi在4.7.6以前都是可以直接在定时任务打snakeyaml写内存马或者jndi,但是4.7.7后把bean能调用的一些class给ban了,而且4.7.8可以看到限制了http(s)/ldap/rmi的执行,其实不算是完全限制,只是在函数字符串位置限制了。
分析
调试分析我就偷个懒,这里浅浅Copy一下~~
Blacklist & Whitelist
这里其实就跟那些博客写的一样,我们需要找到一个方法能够使payload写入定时任务,这里我们找到的是sql注入的方式,用十六进制绕过限制。
4.7.6往前的RCE也很简单,直接定时任务写入:
1 |
|
打snakeyaml反序列化,这里一般用的是http把yaml-payload.jar挂vps上,或者
1 |
|
直接调用lookup打JNDI。
但是使用http这种会遇到:
因为在SysJobController.java
黑名单设置:
而且设置了计划任务白名单和违规字符过滤:
黑白名单在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注入来绕黑白名单,接下来就介绍这一部分。
SQL Injection
在 ruoyi 4.7.5 版本之前,后台接口/tool/gen/createTable
处存在 sql 注入(CVE-2022-4566)
而 genTableService 的实现类是 GenTableServiceImpl:
对应的 Mapper 语句:
1 |
|
运行结果:
RCE
根据上文可知,ruoyi 计划任务能调用 bean 或者 class 类,SQL 注入依赖于 GenTableServiceImpl#createTable。
如果 GenTableServiceImpl 是 bean 对象,就可以直接调用 GenTableServiceImpl#createTable 执行 SQL 语句
在启动类中打印所有加载的 bean,其中包括 genTableServiceImpl:
1 |
|
于是可以调用 genTableServiceImpl.createTable 实现 sql 语句执行,所以 RCE 的思路:配合注入在 sys_job 数据表中直接插入恶意计划任务,即可不调用 addSave 方法添加计划任务内容,成功绕过黑白名单限制:
而SQL语句是支持十六进制操作的,那我们就可以在添加SQL定时任务时,使用十六进制转换绕过。
1 |
|
成功调用 genTableServiceImpl.createTable 方法:
成功修改:
执行代码:
如此这般,所有的都拉通了。
既然这里可以十六进制绕过,那么无论是打Snakeyaml的反序列化还是JNDI都是为所欲为。
回到题目
因为题目用的公共环境,我也不想别人蹭车(嘻嘻),所以就没打内存马,直接JNDI反弹shell打的:
首先是这个方法测了一下DNS:
收到回显,那么直接游戏结束了。
首先我创了几个任务,那个cront语句仿照那个随便写写就可以了,对上id,
JNDI原始payload:
1 |
|
转十六进制后写入一个新创的定时任务(这里我是写入id=7的定时任务里):
1 |
|
然后在表盘打开任务状态,在更多操作处选择执行一次,会发现id=7的定时任务已经写入payload:
然后在将id=7的定时任务执行一次,JNDI反弹shell:
参考:
若依4.7.8版本计划任务rce复现_若依计划任务rce-CSDN博客
RuoYi 4.7.8 执行任意SQL语句导致RCE漏洞-腾讯云开发者社区-腾讯云 (tencent.com)
N/A|RuoYi v4.7.8若依后台管理系统RCE漏洞(POC)-腾讯云开发者社区-腾讯云 (tencent.com)
最新Ruoyi组合拳RCE分析 - 先知社区 (aliyun.com)
ruoyi漏洞poc汇总及其原理分析(源码分析)-CSDN博客
lz2y/yaml-payload-for-ruoyi: A memory shell for ruoyi (github.com)