近期收到某友方SRC發來的郵件,迴響網站中存在可被Dos的風險,複測後發現確實存在此類風險。
隨後嘗試對其進行修復,過程滿有意思的,所以匯總了一下在PHP開發中容易引起Dos的幾個點。
Ps:所有內容僅供學習研究及分析,請勿用於進行互聯網惡意攻擊行為,因惡意攻擊造成的損失均與本文作者無關。
會引起Dos的幾種案例
CVE-2015-4024
CVE-2015-4024
早起危害較大的Dos漏洞,挺有代表性的。其原理是php解析body part的header時進行字串拼接,而拼接過程重複拷貝字元導致DOS。對應官方bug:
https://bugs.php.net/bug.php?id=69364
https://bugs.php.net/bug.php?id=69364
XML待辦事項
XML Dos
也叫XML Bomb,其原理是通過無限制的遞迴,或傳遞的實體內容過大造成記憶體占滿,從而實現Dos。
XML Bomb
背部
Json Dos
它主要利用了PHP Hash Collision,早在2013年被發現並收到重視。但是在開發中,濫用相關函數便會造成此類Dos的出現。
PHP Hash Collision
在較老的版本中通過提交POST參數,也能實現PHP Hash Collision。
POST
PHP Hash Collision
攻擊實例
CVE-2015-4024
該漏洞是比較老的一個的,已被修復很久網上也有很多文章及介紹,當然官方bugs裏寫個人認為是描述最全的,給Shusheng Liu大佬點贊。
bugs
Shusheng Liu
具體產生原因則需要追PHP的引擎程式碼了,在這我就不贅述了應用說明概括
由於php沒有妥善處理multipart/form-data請求的body part請求頭,對於換行內容多次重新申請記憶體,導致耗盡CPU資源,拒絕服務電腦。-- PHITHON
multipart/form-data
body part
複現過程:
复现过程:
首先通過docker運行一個未升級版的php-fpm容器
docker
php-fpm 容器
nginx應用為物理機,php-fpm則啟動容器方便切換不同版本。
nginx
php-fpm
PHP檔案(post_exp.php)簡單構造一個from表單,接收POST過來的參數並輸出:
post_exp.php
現在我們來看看,正常提交參數的回應時間是多少:
僅0.03/s,通過BurpSuite改成惡意請求後提交查看本次服務器響應時長。
0.03/s
BurpSuite
服務器回應時間為:11.16/s,說明本次複現成功。
11.16/s
XML Dos
該風險常發生在對外提供介面,並接收惡意XML(對接過Dot Net的同學都知道WSDL吧)實體,從而讓應用進行無限制的遞迴,導致耗盡CPU資源。
XML
Dot Net
WSDL
PHP檔案(xml_exp.php)用於接收POST過來的XML實體,處理後輸出:
xml_exp.php
前面已知一個正常的請求相應時長一般在0.03/s之內,超出時間則表示攻擊成功。現在發送一個可遞迴的POST請求並發送。
0.03/s
本次攻擊並沒有生效,懷疑是SimpleXML擴展已被修復並限制了遞迴深度,超出則終止應用。
SimpleXML
將要提交的xml內容修改為只保留一行,並引用&a:
&a
就像圖中看到的,雖然單個請求看起來效果不大,如果是多個呢?(文章中用的壓測工具是Jmeter)
當然,我的小水管電腦肯定和服務器級別的沒法比,這裡僅供學習研究了。
然後我在官方bugs中又看到一個有意思場景,可直接占滿伺服器記憶體(當前php-fpm版本:5.5.30)。
bugs
php-fpm版本:5.5.30
抱歉此處沒有配圖,電腦的記憶體被php-fpm行程占滿,多達6G內容使用量。直至超過50秒行程被kill
Json Dos
這類攻擊早在2011年就被發現並利用,根據搜尋引擎找到大神Laruence的個人部落格,其在2011-12-29日至30日的文章中有詳細介紹。攻擊的原理很簡單,就是將語言底層保存POST數據的Hash錶因為衝突(碰撞)而退化成鏈表.
Laruence
冲突(碰撞)
詳見:http://www.laruence.com/2011/12/30/2435.html
通過情况下,只要給提交POST參數一個接收最大個數即可緩解此類情况。但隨著業務越來越複雜,數據互動時類型的多樣性而變的脆弱。
POST
假設該場景,用戶在頁面視窗填寫帳號密碼並點擊登入,此時會通過AJAX發送拼接好的json字串到介面。
PHP檔案(json_exp.php)用於接收POST過來的json字串,並處理成數組:
json_exp.php
一次正常的請求應用回應時間是在毫秒以內,現在我們構造一段惡意的json,並發送至介面。
{“0”:0,“65536”:0,“131072”:0,“196608”:0,“262144”:0,“327680”:0,“393216”:0,“458752”:0,……,“4294836224”:0,“4294901760”:0}
看到了嗎,一次請求的響應時長是20多秒,至於如何避免該問題請看防禦章節(高效一招防)。
20多秒
順便實驗了一下現時5.6.×以下所有版本均有這個問題,直到PHP7才被減緩優化至4秒(贊鳥哥)。
5.6.×
PHP7
如何防禦
知攻不知防,幾年都瞎忙
對於CVE-2015-4024的利用只需要升至最新的PHP版本即可。
CVE-2015-4024
XML Dos
我們都知道在PHP中防禦外部DTD攻擊,只需要在解析XML內容之前,加入libxml_disable_entity_loader(true);函數即可。
libxml_disable_entity_loader(true);
但這種XML Bomb使用的是內部DTD,遺憾的是我翻過官方手册也google了一圈,並沒有發現PHP中有禁用內部DTD的函數及方法。
XML Bomb
所以這裡只能使用正則匹配去識別攻擊了,匹配DTD中的關鍵字:<!DOCTYPE和<!ENTITY,或者SYSTEM和PUBLIC。
<!DOCTYPE 和 <!ENTITY,或者 SYSTEM 和PUBLIC。
而解析大的XML檔案可能會花費大量時間和記憶體。如果你的體系結構允許,可以考慮將大的XML檔案解析放在非同步進行。當XML文件上傳時,將它們移到隊列中,並有一個單獨的行程將它們從隊列中取出並處理解析任務。
這種方法將提高系統的可擴展性和穩定性,因為繁重的分析工作不會使Web服務器離線。
Json Dos
該攻擊的防禦蠻簡單的,不要使用json_decode函數中的第二個參數。也是就常用來將json對象轉數組的參數。
json_decode
第二个参数
我的解決辦法是用PHP的強制類型轉換,替換json_decode的功能(不知道是我搜尋引擎使用方法不對還是咋的,居然沒有看到用這種方法去解决的栗子,也是醉了)。
PHP的强制类型转换
json_decode
耗時0.112秒!!!
0.112
隨後對$arrays變數怎麼使用就不說了,基本操作。但有一點很重要:不要去遍歷它,不要去遍歷它,不要去遍歷它
$arrays
.21442;.32771
https://www.leavesongs.com/PHP/PHP-Multipart-form-date-remote-DOS-Vulnerability.html
http://nikic.github.io/2011/12/28/supercalliding-a-PHP-array.html
https://yq.aliyun.com/articles/92194
https://msdn.microsoft.com/zh-cn/magazine/ee335713.aspx