java反序列化——XMLDecoder反序列化漏洞


本文首發於“合天智匯”公眾號 作者:Fortheone

前言

最近學習java反序列化學到了weblogic部分,weblogic之前的兩個反序列化漏洞不涉及T3協議之類的,只是涉及到了XMLDecoder反序列化導致漏洞,但是網上大部分的文章都只講到了觸發XMLDecoder部分就結束了,並沒有講為什么XMLDecoder會觸發反序列化導致命令執行。於是帶着好奇的我就跟着調了一下XMLDecoder的反序列化過程。

xml序列化

首先了解一下java中的XMLDecoder是什么。XMLDecoder就是jdk中一個用於處理xml數據的類,先看兩個例子。

這里引用一下淺藍表哥的(強推淺藍表哥的博客https://b1ue.cn/

import java.beans.XMLEncoder;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;

/**
 * @author 淺藍
 * @email blue@ixsec.org
 * @since 2019/4/24 12:09
 */
public class Test {

    public static void main(String[] args) throws IOException, InterruptedException {

        HashMap<Object, Object> map = new HashMap<>();
        map.put("123","aaaa");
        map.put("321",new ArrayList<>());

        XMLEncoder xmlEncoder = new XMLEncoder(System.out);
        xmlEncoder.writeObject(map);
        xmlEncoder.close();

    }
}

這樣就把map對象變成了xml數據,再使用XMLDecoder解析一下。

/**
 * @author 淺藍
 * @email blue@ixsec.org
 * @since 2019/4/24 12:09
 */
public class Test {

    public static void main(String[] args) throws IOException, InterruptedException {
        String s = "<java version=\"1.8.0_131\" class=\"java.beans.XMLDecoder\">\n" +
                " <object class=\"java.util.HashMap\">\n" +
                "  <void method=\"put\">\n" +
                "   <string>123</string>\n" +
                "   <string>aaaa</string>\n" +
                "  </void>\n" +
                "  <void method=\"put\">\n" +
                "   <string>321</string>\n" +
                "   <object class=\"java.util.ArrayList\"/>\n" +
                "  </void>\n" +
                " </object>\n" +
                "</java>";
        StringBufferInputStream stringBufferInputStream = new StringBufferInputStream(s);
        XMLDecoder xmlDecoder = new XMLDecoder(stringBufferInputStream);
        Object o = xmlDecoder.readObject();
        System.out.println(o);

    }
}

就可以把之前的xml數據反序列化回map對象,那么如果對xml數據進行修改,使其變成一個執行命令的數據。比如說:

<java version="1.7.0_80" class="java.beans.XMLDecoder">
 <object class="java.lang.ProcessBuilder">
  <array class="java.lang.String" length="1">
    <void index="0"><string>calc</string></void>
  </array>
  <void method="start"></void>
 </object>
</java>

然后對其反序列化即可執行命令彈出計算器。

現在我們知道了如果使用XMLDecoder去反序列化xml數據,數據中包含的命令會被執行。接下來就對其進行分析一下。

XMLDecoder反序列化漏洞成因

一、XML數據解析前的函數處理

在readObject處打上斷點開始debug

進入了parsingComplete方法,跟進。

其中使用XMLDecoder的handler屬性DocumentHandler的parse方法,並且傳入了我們輸入的xml數據,跟進。

這里調用了SAXParserImpl類的parse方法。

然后又進了xmlReader的parse方法。

這里又調用了xmlReader父類AbstractSAXParser的parser方法。

最后進入了XML11Configuration類的parse方法。

二、XML數據的處理

在XML11Configuration中進行了很多解析XML之前的操作,我們不去仔細研究,看到處理XML數據的函數scanDocument。跟進查看

這個函數通過迭代的方式對XML數據的標簽進行解析,網上有些文章寫道“解析至END_ELEMENT時跟進調試”,但是我看了一下我這里的END_ELEMENT。

里面沒有函數可以跟進啊,然后搜了一些其他的文章,是因為jdk版本的問題,處理的邏輯放在了next函數里。在do while循環里跳了大概十次,就開始解析了xml的標簽。

跳到XMLDocumentScannerImpl中的next方法

跳到XMLDocumentFragmentScannerImpl中的next方法,解析到endtag時會走到scanEndElement方法里。

然后就到了網上說的endElement方法里,跟進。

這一部分的解析可以參考下圖:

也就是說解析時會按照標簽一個一個解析。

這里調用了DocumentHandler的endElement方法。接下來就是很重要的部分

這里的handler是StringElementHandler,但是這個類沒有重寫endElement方法,所以調用的是父類ElementHandler的endElement方法,其中調用了getValueObject來獲取標簽中的value值,這里的標簽是string標簽,所以獲取到的值是calc。

然后將其添加到其父類標簽VoidElementHandler的Argument屬性中。

然后將handler指向其父類VoidElementHandler。

繼續解析到void標簽,此時的handler就是VoidElementHandler,接着調用getValueObject。但是因為沒有重寫該方法,所以調用父類NewElementHandler的getValueObject。

繼續跟進發現實現了反射調用invoke方法,也就是執行了set方法。接着再解析Array標簽,按照上面的步驟解析,就完成了這一部分參數的解析。

<array class="java.lang.String"length="1">
  <void index="0">
      <string>calc</string>
  </void>
</array>

那么再按照上面的步驟解析object標簽,然后調用new 方法實例化 ProcessBuilder類。

然后解析到void標簽獲取到start方法,然后通過調用start方法實現了命令執行,彈出計算器。

也就相當於最后拼接了 new java.lang.ProcessBuilder(new String[]{"calc"}).start();

文章有說的不對的地方請師傅們指點,剛開始學java,大佬們輕噴。。。

參考文章

https://b1ue.cn/archives/239.html

https://zhuanlan.zhihu.com/p/108754274

https://blog.csdn.net/SKI_12/article/details/85058040

相關實驗

Java反序列漏洞

https://sourl.cn/23ajig

(本實驗通過Apache Commons Collections 3為例,分析並復現JAVA反序列化漏洞。)

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM