13161216443

您所在位置: 首頁> java技術> java培訓班 | JDK反序列化Gadgets-7u21

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

發布百知教育 來源:java技術 2019-12-06

從fastjson1.24版本的反序列化利用方式知道有使用jdk7u21的版本利用鏈,ysoserial利用工具中也有7u21利用鏈?,F在都是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中?。?/p>


  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.akpsimsu.com/java2019

注釋:部分內容來自公眾號雷神眾測








上一篇:大數據培訓班 | 新手學習大數據必問的十個問題

下一篇:應屆生去公司找個Java程序員的職位需要什么技能?

相關推薦

www.akpsimsu.com

有位老師想和您聊一聊

關閉

立即申請