<progress id="zxlfw"></progress>

<tbody id="zxlfw"><noscript id="zxlfw"></noscript></tbody>

<rp id="zxlfw"></rp>

      <tbody id="zxlfw"></tbody>
      <rp id="zxlfw"></rp>

      400-616-5551

      您所在位置: 首页> 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.youjiefx.com/java2019

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








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

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

      相关推荐

      澳门牛魔王四肖选一肖

      关闭

      立即申请

      www.youjiefx.com