前言

最近在研究java的反序列化,然后也写了相关的Poc,这里稍微简单的分几部分介绍下学习的过程,这里先大概聊一下Weblogic系列的洞。

正文

这篇Blog我们先来看一下Weblogic的XML的反序列化的洞,我们先看下java怎么解析xml的。weblogic利用的是XMLDecoder这个库,然后我们先创建个maven项目:

然后java文件中内容是:

要解析的xml文件为

我们其实在看到readObject的时候就知道肯定是反序列化相关了,那么XMLDecoder是怎么具体将xml文件解析成具体的类,调用ProcessBuilder.start()函数来执行open ./等命令呢,我们首先跟进到start函数处,打上断点来进行调试

开启debug后我们先大致浏览下调用栈:

整个调用栈还是很长的,但是主要的函数操作都是在对xml文档进行解析,我们同时也看到用到了很多invoke方法,利用反射来具体完成了函数的调用,我们直接从readObject开始,然后跳过前面的一些解析准备工作,直接跟进到scanDocument的地方

可以看到这个函数是用迭代的方式,一行一行的扫描xml文件,然后在DocumentHandler.java中是注册着许多标签相对应的handler去进行相应的处理,然后具体解析xml标签的方式我不想找用太多篇幅去贴代码,总体的思路就是一直扫描遇到起始标签就一路继续往下面扫,形成一个类似链表的结构,同时会注册处理好,标签的父标签等信息,然后知道遇到结束标签,开始解析里面的内容,并且看是不是起父标签需要的参数,可能大概的思路就是这样,如果有什么不对的地方请纠正,这里我们继续往下看。

我们继续跟进刚刚的调用栈到scanStartElement,这个函数主要是开始处理标签,继续跟进到具体的处理

startElement直接跳过了,因为开始标签中没有什么东西,到了endElement中

我们看下emptyElement的逐级调用知道在ElementHandler中的调用,

看到这里是调用了getValueObject方法,我们跟进到getValueObject中

可以看到最终的调用的是ObjectElementHandler中的getValueObject的方法,我们来看下具体的代码

关键点是最后两行代码,Expression类的作用简单来说就是动态调用对象的指定方法(本质上还是调用了invoke,利用了反射机制)

Expression expression = new Expression(bean, name, args);

这个是将我么的参数传递进去实例化,bean是类即target,name是方法,args是可能的参数,然后我们跟进到下一行的getValue中观察其具体做了什么

看到setValue设置由invoke反射机制生成的ProcessBuilder实例,然后此时的Expression类中的变量情况我们也看一下

截取了其中最重要的部分

我们可以看到xml中扫描到的ProcessBuilder,下方包含了执行的命令是两个参数open ./,以及由VoidElementHandler最后传递进来的start函数,然后看下对invoke的描述

对于反射的具体实现原理我还没有仔细研究,之后会进行更多的研究,然后最终经过这一系列的调用成功调用了ProcessBuilder.start()函数,完成了整个命令执行,这里借一张图总下下整个流程。

总结

这里先大概介绍下基础部分,后面几个具体的cve再做介绍,其实再看来就是xml在做解析的时候没有对可能存在的恶意类进行防护(或者说这里本来就不应让XMLDecoder来做防护),然后被其利用了反射机制invoke在解析整个xml的时候来构造了一个恶意类来进行操作。