1. 程式人生 > >一種高級的DoS攻擊-Hash碰撞攻擊

一種高級的DoS攻擊-Hash碰撞攻擊

讀取 turn variable 重寫 我們 targe count http 返回結果

原文鏈接

這是迄今為止第一個讓我覺得後怕的攻擊方式,涉及的範圍廣難以防禦,攻擊效果立竿見影。大量的網站和Web接口都未做Hash碰撞攻擊的防禦,一拿一個準。

隨著RESTful風格的接口普及,程序員默認都會使用json作為數據傳遞的方式。json格式的數據冗余少,兼容性高,從提出到現在已被廣泛的使用,可以說成為了Web的一種標準。無論我們服務端使用什麽語言,我們拿到json格式的數據之後都需要做jsonDecode(),將json串轉換為json對象,而對象默認會存儲於Hash Table,而Hash Table很容易被碰撞攻擊。我只要將攻擊數據放在json中,服務端程序在做jsonDecode()時必定中招,中招後CPU會立刻飆升至100%。16核的CPU,16個請求就能達到DoS的目的。

所有測試程序都在Mac Pro下進行,為了測試方便我只構造了65536條json鍵值對,真正發起攻擊時可以構造數十萬甚至百萬千萬的數據。

幾個簡單的Demo

攻擊數據我已經轉換為json格式

  1. Hash攻擊json數據

  2. 普通json數據

  3. Java版本Hash攻擊數據

一. JavaScript測試

//只需要一行代碼就能看到效果
var jsonSrc = ‘這裏輸入json數據‘;

我們只需要在js中輸入一行代碼就能看到效果,普通數據和Hash攻擊數據都是65536行鍵值對。我本地測試的效果如下:
通過Chrome自帶的任務管理器可以看出CPU馬上升到100%,將近1分鐘才執行完成,而普通的數據幾毫秒就能執行完成;

二. PHP測試

$json = file_get_contents("https://raw.githubusercontent.com/laynefyc/php_thread_demo/master/hashNomal.json");

$startTime = microtime(true);
$arr = json_decode($json,true);
$endTime = microtime(true);
echo "Nomal:".($endTime - $startTime)."\r\n";

$json = file_get_contents("https://raw.githubusercontent.com/laynefyc/php_thread_demo/master/hash.json");

$startTime = microtime(true);
$arr = json_decode($json,true);
$endTime = microtime(true);
echo "Attack:".($endTime - $startTime)."\r\n";

PHP中我們通過file_get_contents遠程去拿數據,運行對比一下時間,相差10多秒,php-fpm單進程占用CPU 100%。

三. Java測試

public String index(){

    String jsonStr = "";

    try
    {
        FileReader fr = new FileReader("t.log");//需要讀取的文件路徑
        BufferedReader br = new BufferedReader(fr);
        jsonStr = br.readLine();
        br.close();
        fr.close();     //關閉文件流
    }catch(IOException e)
    {
        System.out.println("指定文件不存在");//處理異常
    }

    Map<String, Object> map = new HashMap<String, Object>();

    map = JSONObject.fromObject(jsonStr);
    return "Hash Collision ~";
}

Java中我們通過讀文件的方式做測試,Java的Hash算法與PHP和JavaScript有略微的差別,但是大同小異,我們同樣構造了6萬行簡單的數據。Spring boot框架中瀏覽器發起一次訪問,26秒之後才返回結果,期間CPU被打滿。

四. 其他語言還在研究中……

HashTable是很通用的數據結構,數據結構與算法上專門有一節課來說它,所以Hash Collision是普遍存在的,各語言在實現上只是散列算法和Table存儲上有細微差別。

為了驗證Java的Hash碰撞攻擊也生效,我整個端午假期都在看Java HashTable相關的文章,經過努力最後還是成功的生成了攻擊數據。過程非常不簡單,這也驗證了一個思想--所有高個上的東西最後分解出來都是基礎的數據結構知識。

如何攻擊

幾年前PHP的版本還是5.2,我們可以把所有的Hash Key都放在POST請求的Body中,比如:

https://www.test.com/create-account

Post Data: k1=0&k2=0&k3=0...k999998=0&k999999=0

服務端拿到數據後會將所有參數存儲到Hash Table($_POST)中,通過這種方式能很方便的實現攻擊。但是現在這種方式行不通了,因為我們很容易就能在Nginx層和PHP層限制Http請求的參數個數和大小。PHP默認只允許1000個參數,這個量級對服務器完全沒影響。

現在是2017年,json格式和RESTful風格的接口已經非常流行。帶給我們便捷編碼的同時,也給Hash Collision Dos提供了新的方式。現在很多RESTful風格的接口如下:

https://www.test.com/v1

Data: {"action":"create-account","data":""}

如上接口,我們直接把攻擊的數據放入data參數中,服務端接收到數據後肯定會做jsonDecode(),很方便的就達到了攻擊的目的。

如何防禦

要想防禦Hash Collision Dos攻擊,行業內已經有很多成熟的方案了,不過都是建議換語言或者重寫HashTable。這裏只說當前json格式解析的問題。首先我們需要增加權限驗證,最大可能的在jsonDecode()之前把非法用戶拒絕。其次在jsonDecode()之前做數據大小與參數白名單驗證。舊項目的改造與維護成本如果很高,建議自己重寫jsonDecode()方法。

未完待續

寫了這麽多,其實最有樂趣的地方還是如何生成攻擊數據。之後我會詳細的寫這部分。最後,Golang和Python能躲過Hash Collision Dos測試嗎?敬請期待

原文鏈接

一種高級的DoS攻擊-Hash碰撞攻擊