它是怎麼起作用的
在通常的情況下,雜湊表被優化的速度非常快。但如果有人將互相沖突的鍵值插入,效能就會突然變得很糟糕。
如果雜湊表使用開放的地址來實現,一個衝突的鍵值會針對連結列表中的所有元素做出檢查。如果你插入了n個元素,為了公平性你就得檢查 1+2+3+..+(n-1) 個元素(複雜度為O(n²))。
如果你想早知道更多關於這個在PHP裡是怎麼起作用的,你還可以讀讀這篇資訊量比較豐富的文章。
使用POST資料作為攻擊
為了方便訪問,PHP把所有的POST欄位都存放在$POST圖裡。
<!--?php echo $_POST ["param"]; ?-->
下面的POST請求是針對上賣弄的PHP頁面的,會導致5個鍵值衝。如果你傳送了2^16個鍵值,這時的計算量就相當於要讓i7處理器忙上30秒鐘。
curl--data"4vq=key1&4wP2=key2&5Uq=key3&5VP=key4&64q=key5"http://localhost:8080/index.php
儘管在一些語言(比如Python)裡雜湊函式已經為了防止此類的攻擊而做出了相應的修改,PHP通過在php.ini配置檔案裡簡單地引入了一個max_input_vars指令解決了這個漏洞問題。
預設情況下,該指令被設定為1000,這意味著你在一個請求中不能傳送超過1000個表單欄位。1000個衝突不是真正的問題,因為它與正常情況下請求相比速度只慢了1/3.
使用JSON API作為攻擊
由於Web已經進化到一個到處都是API的大網,我們可能已經忘記,在使用者使用輸入和陣列的地方PHP仍然存在著雜湊衝入漏洞攻擊。
Web API通常支援JSON,因此使用標準PHP庫的json_decode方法。這將預設解析所有在JSON檔案裡的鍵值到PHP圖中,引起許多衝突。
下面是一個很簡單的返回傳送者姓名和郵件地址的API:
<!--?php header('Content-Type: application/json'); $body = file_get_contents('php://input'); $params = json_decode($body); $response = array('name' =--> $params->{'name'}, 'email' => $params->{'email'}); echo json_encode($response); ?>
如果我們把一個修改後的JSON請求傳送給這個API,結果和POST引數會有一樣的影響。
curl -v -X POST \ -H "Accept: application/json" \ -H "Content-type: application/json" \ -d '{"4vq":"key1", "4wP2":"key2", "5Uq":"key3", "5VP":"key4", "64q":"key5" }' \ http://example.com/api.php
測試
我將json_decode和導致一個可怕的二次函式的時間畫了出來。在 2^16個鍵之後異常值出現了,原因是一個不同的雜湊掩碼,在當前陣列在陣列增長超過 2^16個元素時,我們的衝突預計會引起16位雜湊掩碼的衝突。
我在AWS上跑了一個測試,其中有一個攻擊者(藍色)和一個受害者(黃色),並且為CPU佔用率截了圖。你能很容易就看明白,儘管攻擊者除了傳送POST請求外其他幾乎什麼事情都沒有做,受害者為網頁頁面提供提供服務的效能還是會受到影響。
有趣的是,解析XML並沒有使用內部的雜湊圖。
我確定還有很多使用者資料和雜湊表一起被呼叫的其他種情況。
自己嘗試一下
我把測試指令碼和樣例頁面放在github庫裡了,甚至還增加了上千個自衝突鍵值。
原文:http://lukasmartinelli.ch/web/2014/11/17/php-dos-attack-revisited.html
(翻譯:PHP100_Alex)
來自:PHP100
評論(1)