探祕PHP拒絕服務攻擊

edithfang發表於2014-12-29
你可以自己模擬一下簡單的攻擊,以更加了解如何才能更安全。
 
它是怎麼起作用的
       
在通常的情況下,雜湊表被優化的速度非常快。但如果有人將互相沖突的鍵值插入,效能就會突然變得很糟糕。

 

 

如果雜湊表使用開放的地址來實現,一個衝突的鍵值會針對連結列表中的所有元素做出檢查。如果你插入了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位雜湊掩碼的衝突。


 

如果把上面的JSON API樣例託管在一個實際的伺服器上,並且做出一些攻擊,我們也會得到同樣的結果。函式會達到平衡,因為Apache伺服器處理每條請求的時間被限制在30秒以內。


 

我在AWS上跑了一個測試,其中有一個攻擊者(藍色)和一個受害者(黃色),並且為CPU佔用率截了圖。你能很容易就看明白,儘管攻擊者除了傳送POST請求外其他幾乎什麼事情都沒有做,受害者為網頁頁面提供提供服務的效能還是會受到影響。



 

其他潛在的攻擊載體
       
有趣的是,解析XML並沒有使用內部的雜湊圖。


 

       
我確定還有很多使用者資料和雜湊表一起被呼叫的其他種情況。
 
自己嘗試一下
       
我把測試指令碼和樣例頁面放在github庫裡了,甚至還增加了上千個自衝突鍵值。

原文:http://lukasmartinelli.ch/web/2014/11/17/php-dos-attack-revisited.html

(翻譯:PHP100_Alex)
來自:PHP100
評論(1)

相關文章