在學習Java的反序列化漏洞的時候,就不得不學習他的一個利用鏈。不少剛剛入門的對於利用鏈這個詞可能比較陌生。那麼這裏先來了解一下Java反序列化和反序列化漏洞的一個產生。html
文章首發:Java安全之URLDNS鏈java
Java提供了一種對象序列化的機制,用一個字節序列表示一個對象,該字節包含對象的數據、對象的類型、對象的存儲屬性。字節序列寫出到文件後,至關於能夠持久報錯了一個對象信息,這過程叫作序列化。序列化對象會經過ObjectOutputStream
的writeObject
方法將一個對象寫入到文件中。git
而反序列化是使用了readObject
方法進行讀取並還原成在序列化前的一個類。github
這一步驟並無什麼安全問題,可是若是反序列化的數據是可控的狀況下,那麼咱們就能夠從某個輸入點,輸入惡意代碼,再去查找在哪一個點,咱們的輸入會被一層一層的帶去到咱們的觸發點去,而這一步叫作尋找利用鏈的步驟。api
至於ysoserial就很少敘述了,自行百度。安全
ysoserial項目地址:ysoserialmaven
拉取項目源碼,導入到IDEA中。ide
看到pom.xml知道該項目是個maven的項目,點擊pom.xml 進行刷新,將缺乏的依賴給下載下來學習
下載完成,直到不爆紅了後,就能夠開始調試ysoserial了。測試
先來查找一下該程序的入口點,點開pom.xml搜索mainclass就能夠找到入口點的類
ctrl+左鍵點擊跟蹤進去,運行測試一下。
運行發現爆了一些錯誤,這裏是由於咱們並無去傳入值。
點擊Edit configurations,設置參數
再次運行就能夠看到成功執行了。
這樣咱們就獲取到了一個序列化的數據。
咱們的ysoserial就能在idea裏面去運行了。
URLDNS是ysoserial裏面就簡單的一條利用鏈,但URLDNS的利用效果是隻能觸發一次dns請求,而不能去執行命令。比較適用於漏洞驗證這一塊,並且URLDNS這條利用鏈並不依賴於第三方的類,而是JDK中內置的一些類和方法。
在一些漏洞利用沒有回顯的時候,咱們也可使用到該鏈來驗證漏洞是否存在,好比shiro反序列化就是使用dnslog來驗證漏洞是否存在,(盲猜的,並無去分析過,後面能夠去分析一下)。
下面先來使用ysoserial的URLDNS
java -jar .\ysoserial.jar URLDNS "http://2mdw9p.dnslog.cn"
獲得序列化後的數據,若是須要執行,咱們須要對其進行反序列化,這裏先不執行。先來看看在ysoserial中,該數據是怎麼獲取的。
打開ysoserial/payloads/URLDNS.java
的源碼
上面的註釋也寫明白了他的調用鏈
具體怎麼執行的咱們還得去debug看。
觸發點在hashmap的put方法,咱們在put地方打一個斷點
來到hashmap的readobject中看到
這裏使用了hash方法對key的值進行了處理,咱們來跟蹤一下hash這個方法看看他具體的實現
這裏的key的是java.net.URL的實例對象調用了key的hashcode。再跟進一下他的hashcode方法。
在hashcode方法中還調用了handler的hashcode。先來跟蹤一下hanler
調用 URLStreamHandler 的hashcode。進行跟蹤URLStreamHandler.hashcode。
跟進一下getProtocol方法
在jdk的api文檔裏面寫着該方法是用來獲取協議的名稱的
回到剛剛的地方
再來跟蹤一下getHostAddress
來到這裏後,能夠發現會調用getHost
、getByName
這兩個方法。
JDKapi文檔查看 InetAddress.getByName方法
該方法會使用遠程請求,進行獲取主機的ip,那麼這時候就會觸發一次請求,到了這裏咱們的dnslog平臺,就能夠收到響應了。這就是這個URLDNS鏈的一個觸發點。
HashMap.readObject() -> HashMap.putVal() -> HashMap.hash() -> URL.hashCode()->URLStreamHandler.hashCode().getHostAddress ->URLStreamHandler.hashCode().getHostAddress ->URLStreamHandler.hashCode().getHostAddress.InetAddress.getByName
下面來測試一下
import java.io.*; public class main { public static void main(String[] args) throws IOException, ClassNotFoundException { FileInputStream fis = new FileInputStream("out.bin"); ObjectInputStream bit = new ObjectInputStream(fis); bit.readObject(); } }
執行後再看咱們的dnslog平臺
在URLDNS裏面其實致使反序列化的根本緣由是由於hashmap重寫了readobject反序列化方法,而重寫後的readobject方法調用了putVal致使的一個利用鏈
https://www.cnblogs.com/kuaile1314/p/13690210.html https://www.cnblogs.com/ph4nt0mer/p/11994384.html https://www.cnblogs.com/v1ntlyn/p/13549991.html https://zhuanlan.zhihu.com/p/30045174 https://www.cnblogs.com/litlife/p/12596286.html
其實調試URLDNS這條鏈相對來講是比較簡單的,雖然前面也花了很多時間去摸索,參考了大量的文章。可是等明白了後,發現其實URLDNS鏈仍是比較簡單的。