一種高級的DoS攻擊-Hash碰撞攻擊
這是迄今為止第一個讓我覺得後怕的攻擊方式,涉及的範圍廣難以防禦,攻擊效果立竿見影。大量的網站和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格式
一. 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風格的接口如下:
Data: {"action":"create-account","data":""}
如上接口,我們直接把攻擊的數據放入data參數中,服務端接收到數據後肯定會做jsonDecode(),很方便的就達到了攻擊的目的。
如何防禦
要想防禦Hash Collision Dos攻擊,行業內已經有很多成熟的方案了,不過都是建議換語言或者重寫HashTable。這裏隻說當前json格式解析的問題。首先我們需要增加權限驗證,最大可能的在jsonDecode()之前把非法用戶拒絕。其次在jsonDecode()之前做數據大小與參數白名單驗證。舊項目的改造與維護成本如果很高,建議自己重寫jsonDecode()方法。
未完待續
寫了這麼多,其實最有樂趣的地方還是如何生成攻擊數據。之後我會詳細的寫這部分。最後,Golang和Python能躲過Hash Collision Dos測試嗎?敬請期待
我的博客-原文鏈接:一種高級的DoS攻擊-Hash碰撞攻擊
最後更新:2017-06-01 06:31:37