前言

作为一名安全研究人员(java安全菜鸡),知道拿到exp怎么打还不够,还得进一步分析exp构造原理与漏洞原理才行。本篇文章主要分析FastJson1.2.24中针对TemplatesImpl链的构造原理以及ysoserial中针对jdk7u21基于TemplatesImpl加动态代理链的构造原理。内容可能巨详细,希望没接触过这部分的同学可以耐心看下去。

1.TemplatesImpl初相识

FastJson1.2.24中基于com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl这条链的入口点在TemplatesImpl的getOutputperties函数。当然本篇文章不再描述具体如何到这一步,有兴趣的可以参考我之前的一篇文章。一步一步学习某Json1.2.47远程命令执行漏洞
因此在下图所示下断点在此,这里环境为jdk7u21。

这里首先将调用newTransformer(),首先定义类TransformerImpl的对象,其入口参数第一个为Translet的对象

因为此时调用了getTransletInstance(),跟进看看

其返回的是一个Translet类的对象,这里面判断_name 不能为null,否则就拿不到Tranlet对象,后面_class能不能为null,先留着,但是这里明显看到后面要用到_class

这里要用到_class,说明_class里面肯定是有东西的,要么是我们自己赋值,要么就是通过上面的defineTransletClasses()得到了,我们先跟进defineTransletClasses()看看

这里首先判断_bytecodes不能为null,为null将抛出错误信息

接着这里将拿到类加载器,通过它我们就可以对目标类进行加载,我们知道classloader除了调用loadclass来加载类以外,还可以调用findclass里的definedclass来通过加载字节码来在jvm中加载类,那么它肯定是classloader的子类,跟进看看其确实继承自ClassLoader,并且也看到了熟悉的defineclass函数,我们只要知道此时经过该类的definclass就能进行类的加载

继续往下看,下图中实际上取的是_bytecodes[i],并且i的范围也是我们可控的,这里我们知道defineClass是可以通过字节数组来在JVM创建类的,所以这里通过将恶意类的字节码放到_bytecodes里面就能够加载到JVM里

接着将拿到刚刚加载到JVM中的类的父类要求其父类必须是ABSTRACT_TRANSLET,不满足则放到_auxlclass里面,要是新加载的所有类的父类没有一个是ABSTRACT_TRANSLET的话,后面此时_transletIndex < 0处的判断就要报错,因为_transletIndex初始值为-1


此时我们已经知道通过defineTransletClasses函数我们可以通过defineclass来从_bytecodes中加载恶意类,所以我们肯定要让这里的_class为null

我们已经知道_class数组中存储的是加载进来的恶意类,下标_transletIndex就是该恶意类对应的下标,所以接着就调用newInstance()来实例化我们的恶意类,那么我们把要执行的命令放在恶意类的static区或者构造方法中都可以

其中我们的其中恶意类如下,至于要声明两个transform是由于这里是继承自抽象类,所以在其子类中必须实现,这里不声明的话idea也会提示让你实现,idea真香2333~

事实也证明如此,我们可以clac了

并且经过以上分析最终的payload可以缩减为以下形式:
整个调用过程挺短的,实际上就是
TemplatesImpl -> getOutputProperties()
TemplatesImpl -> newTransformer()
TemplatesImpl -> getTransletInstance()
此时在getTransletInstance()函数中将调用恶意类的构造函数,即
_class[_transletIndex].newInstance()导致RCE

2.AnnotationInvocationHandler完美链接

这一部分的分析主要就是通过最外层的readObject反序列化直达getOutputProperties()的调用,即newTransformer()的调用。而ysoserial中已经包含了该链的构造过程,其getobject函数就能拿到该链最外层的对象,而调试ysoserial也很容易,不传命令的话会默认传calc.exe

这里我们传入要执行的命令后调用createTemplatesImpl即可,那么我们可以看看yso中是如何构造该对象的

这里首先通过class.forname获得了三个我们构造该链要用到的类,然后将要执行的命令和这三个类传入createTemplatesImpl 来返回一个经过精心构造的TemplatesImpl对象

这里首先newInstance()获得一个初始的TemplatesImpl对象,用于后面的装饰,然后创建首先创建一个CtClass的容器,我们可以用它按需读取类文件来构造 CtClass 对象,并且保存 CtClass 对象以便以后使用

Java 字节码以二进制的形式存储在 .class 文件中,每一个 .class 文件包含一个 Java 类或接口。Javaassist 就是一个用来 处理 Java 字节码的类库。它可以在一个已经编译好的类中添加新的方法,或者是修改已有的方法,并且不需要对字节码方面有深入的了解。同时也可以去生成一个新的类对象,通过完全手动的方式。
由上面的解释也可以看出来这是一个功能强大的类。这里将首先会插入一个最原始的模板类,这个也就是作为我们用来执行命令的恶意类

通过以下这句代码我们就能够获得恶意模板类的对象,通过它我们就能够对该类的结构进行修改

然后将为该恶意模板类创建静态代码块,并插入rce的代码

点击收藏 | 4 关注 | 2
  • 动动手指,沙发就是你的了!
登录 后跟帖