觀點

網站管理員的惡夢 - HTTP DoS

2011 / 12 / 31
OuTian
網站管理員的惡夢 - HTTP DoS

以往,一般人對防護DoS/DDoS攻擊的想法是:「就是比誰頻寬大嘛!我拉10條線路跟攻擊者玩玩!」、「我有強力的設備守護,在頻寬塞滿前絕對不會倒!」、「即使用人海戰術衝到伺服器層,我用機海戰術守下來!」。但筆者近來常聽到的疑問是:「我已經建置了防火牆、入侵防禦系統,網路頻寬也沒異常上升,為何網站仍然倒了?」先前筆者曾在資安人雜誌65期發表過「DDoS攻擊手法與防禦對策」,當中廣泛列舉各式各樣網路層及應用層的攻擊手法剖析及實例探討,其中亦提到應用層的Application Layer DoS,本文即深入探討其中最常發生的「HTTP DoS」。
「HTTP DoS」是一個泛稱,顧名思義,即針對HTTP協定所進行的Denied Of Service攻擊,手法有許多種,目的皆為癱瘓目標網站。以下即提出近年較常見的幾種攻擊手法。

無言的結局-癡癡守候的伺服器
手法1. GET with unended request
此攻擊手法於2007年時開始被討論,而最有名的是2009年由RSnake所撰寫的攻擊程式Slowloris,一支簡短卻殺傷力強大的perl腳本(附錄1)。根據RFC 2616(HTTP協議)之規範,完整之HTTP GET Request結尾為連續兩CRLF,伺服器端即視此請求完成,開始作後續處理。如下圖為使用IE 8開啟http://www.google.com.tw/ 時送出之HTTP Request –


  
每一個開啟網頁元件的請求,瀏覽器均依此模式與伺服器溝通,但若此請求永遠不結束呢?若攻擊者使用程式模擬此行為,與伺服器80 port建立連線後,送出以下HTTP Header –

  
由於各伺服器並沒有明確規範及定義HTTP Request Header的長度及Header數量,因此攻擊者可不斷重複傳送亂數的Header及內容,只要不連續兩組CRLF,伺服器即會視此請求尚未結束,繼續痴痴等待。

雖然一般伺服器均有設定若使用者端過久未傳送任何資料,即視其為離線而中斷連線(IDLE Timeout)。因此此攻擊一般會同時開啟許多thread,讓每個thread於逾時前,傳遞一個Header,甚至一個byte亦可,如此即可在僅使用少量頻寬的情況下,佔住伺服器端的大量連線。少數連線時此攻擊不致於造成影響,但若此連線數多到伺服器的上限時(例如Apache的Max Clients設定),伺服器程式所有的連線槽均用於等候這些永遠不會結束的請求,自然無暇處理其他新進連線,即被DoS掉了。

經實測的結果,一般Apache伺服器主機可承載的最高Max Clients約在3,000左右,但只要一台攻擊機,可輕易發出上萬組連線進行此攻擊,因此此攻擊對於Apache服務器的殺傷力非常強,少量的Botnet殭屍機即可擊垮數十台以上的伺服器組。根據Slowloris作者的測試,Apache伺服器易受此攻擊方式癱瘓,IIS、lighttpd、nginx等則較不受影響。

手法2. POST with unreached body
於2010的OWASP AppSec年會中,提出了概念類似Slowloris的HTTP DoS方法,但改用HTTP POST方式,以達到更好的效果。當瀏覽器欲傳遞參數給網站時,一般常見為使用GET方法並將參數挾帶於網址「?」後方,並以「&」作參數分隔,特殊符號則作URL Encoding編碼。但若資料量較大或有保密需求不可置於網址列(例如登入表單),則一般會使用POST方式,將資料置於HTTP Request之post body區,並於Header宣告欲傳遞之資料大小。例如下圖為登入Google服務之示意圖 –

  
注意的是當使用POST時,請求之結束將不再是連續兩CRLF,而是在post body區域中,接收到使用者在Content-Length Header中指定的資料長度,才視此請求為結束。但是若此請求永遠不會結束呢?若攻擊者使用程式模擬此行為,與伺服器80 port建立連線後,送出如以下HTTP Header –
  

由於使用者宣告欲傳送10,000,000 bytes的資料,因此只要在連線IDLE Timeout前傳入任何一個字,伺服器端將不斷等待,直到將資料接收完畢。但一般在收完資料前,所有的連線槽就已經被佔滿無法服務了!

經實測的結果,只要佔住的連線數達到Apache的Max Clients設定,即可癱瘓其服務。而即使將Microsoft IIS設定為「連線數無上限」,但約在20,000連線數時(無關伺服器硬體等級),IIS亦會停止服務。

預設情況(未安裝任何修正或模組)下,是否易攻擊成功 –

攻擊類型 Microsoft IIS Apache
GET with unended request NO YES
POST with unreached body YES YES

手法3. HTTP Flood
許多人將連續大量的GET攻擊稱之為GET Flood,但因實際上亦可使用POST、甚至HEAD方法達到相同目的,因此此處統稱為HTTP Flood攻擊。有別於前述使用佔滿伺服器連線槽,以達到DoS的目的的手法,此種HTTP Flood的攻擊,直接模擬大量的使用者,對目標網站不斷進行正常HTTP請求,因使用人數過多,使網站無法負荷而癱瘓。

此種手法一般有幾種常見的攻擊目標頁 –
(1) 首頁 ( 即 /  )
(2) 負荷較重的功能頁-例如搜尋功能、或報表功能等
(3) 登入頁面,通常可進行Brute Force測試帳號密碼
(4) 由網站產生的CAPTCHA圖形驗證碼
此種攻擊手法雖然簡單,但同時也是最難以抵禦的,因所有的動作均為正常的HTTP請求,一般網路層防護設備不會作阻擋,可有效打擊到伺服器層。且因HTTP/1.1協定可做到one connection / multiple request,因此攻擊者可建立少量的TCP連線,即不斷進行HTTP Request,而不一定要單一IP建立大量連線(容易被辨識而阻擋)。

手法4. CC攻擊
此攻擊手法的命名由來有此一說--早期中國的綠盟科技有個著名防DDoS的產品名為「黑洞」,當時有人前去面試卻遭羞辱,回去後不服氣,撰寫了攻擊程式去「挑戰黑洞(Challenge Collapsar)」,還真的成功將之癱瘓了,因此後續類似的攻擊手法便稱為「CC攻擊」。
此手法目前常見有兩種應用 –
(1) 搭配大量代理伺服器進行HTTP Flood,且通常會針對目標網站的繁重功能頁面,被攻擊者因受到大量的Proxy IP存取而較難辨識真正的攻擊來源,一般限制單一IP連線數的機制也難以發揮效果。
(2) 於熱門的網站、論壇或微博等插入iframe,內指向欲攻擊的目標網站,則所有開啟該熱門頁面的使用者,同時也會連向目標站,而達到借他人之手進行大量正常請求的目的。

防護對策:記錄、分析、主動出擊
1. 對抗攻擊手法1、手法2
於網路設備的角度,可採用支援「delayed binding」機制的高階負載平衡設備,於伺服器前進行TCP三向交握及接收到完整的HTTP Request後,才往後傳遞給伺服器。如此即可避免伺服器接到不完整的請求而佔用資源。
一般Client <-> Server 的正常HTTP Request過程如下圖所示 –
  
  
在中間介入高階負載平衡器後,可見到其確定完成TCP連線及接到完整HTTP請求後,才向後方伺服器連立連線、傳送請求。因此任何連線層的攻擊及不完整的HTTP請求,皆會攔截於負載平衡器上,而無法傷害後方伺服器。
  
  
於伺服器主機的角度,由於攻擊者會用特定來源IP建立大量連線,因此伺服器端只要列出連線表,觀察單一IP佔大量連線的情況,即可將該IP封鎖。但隨之而來的可能是更換數千個IP攻來,使管理者疲於奔命。因此以下的網路層防護方式,需可做到自動化處理,儘量減少人為介入處理的時間,才能較有效防護。

網路層防護方式:
(1) 限制單一來源IP的同時連線數(若有特定來源IP需開放,可加入白名單機制)
(2) 找出在進行此攻擊的IP並直接阻擋
  
Apache防護方式:
(1) mod_reqtimeout (Apache > 2.2.15 )
(2) LimitRequestBody directive
(3) anti-slowloris.diff patch (only for Apache 2.2.11 prefork MPM)
(4) mod_antiloris
(5) Mod_Security


2. 對抗攻擊手法3、手法4
基本的幾個概念是-
(1) 若有攻擊特徵,則直接針對特徵作阻擋(如IP / Header / User-Agent / ... etc)
(2) 網路層限制 -
限制單一IP的連線數;限制單一IP的存取頻率。
(3) 應用層處理 -
Cookie Check;Javascript challenge。

當發現受到HTTP Flood或CC攻擊時,一定要開啟伺服器的存取記錄(Access Log),以對攻擊行為進行分析。一般的HTTP Flood,於Access Log中會有特定來源IP造成大量且單調的存取,妥善使用腳本程式定時分析,一經發現則直接自動將其封鎖、或限制存取頻率。


若遇到CC攻擊透過大量Proxy伺服器過來存取,則送來HTTP請求時,大多數正常的Proxy Server會挾帶一X-Forwarded-For Header,指出其代理的真正來源IP。因此可將該Header內容一併作記錄於Access Log中,再套用前述的方式自動化阻擋存取頻率過高之真正來源IP。
  
  
當攻擊者將目標網址置於熱門網站進行CC攻擊時,透過該網站轉連過來的使用者,會挾帶Referer Header,指出其來源連結頁面。此時若於Access Log中發現大量請求來自特定的Referer網站,則可暫時將此行為封鎖或限制其存取頻率。
  
  
除了由Log中分析存取頻率外,亦可由網站程式著手改寫來防護。例如設計成首次進入網站時,會由來源IP運算發出特定的Cookie,若是攻擊者程式不接收Cookie,則我們的網站就僅會反覆發放Cookie的動作,無法攻擊到真正耗資源的程式功能。

但是考慮到大多數的攻擊軟體,可輕易的挾帶指定的Cookie或Header,所以程式端可以再進一步使用client端程式作運算檢查,例如javascript、java applet,甚至flash,一般的瀏覽器可執行指定的動作,則視其為正常的使用者;攻擊軟體一般無法執行用戶端外掛,因此可分辨並視其為非正常使用行為,所以予以阻擋。

上述防護機制可透過高階負載平衡設備或反向代理伺服器完成,或於伺服器上撰寫腳本分析Access Log,達到自動化的阻擋機制。此外,部份伺服器有相關的模組可直接套用,達到類似的防護效果 –
* Apache:
   mod_evasive
* nginx
   HttpLimitZoneModule
   HttpLimitReqModule

結論
本文提出幾種近來常見針對HTTP層的DoS攻擊手法,簡單摘要如下表-

攻擊類型 攻擊目標 攻擊特點
GET with unended request 伺服器資源(Connection) 使用標準HTTP GET,佔滿伺服器連線數
POST with unreached body 伺服器資源
(Connection)
使用標準HTTP POST,佔滿伺服器連線數
HTTP Flood 伺服器資源
(CPU & Memory )
模擬大量使用者行為使伺服器負荷過載
CC攻擊 伺服器資源
(CPU & Memory )
借用其他代理伺服器、或網站內嵌iframe,產生對目標網站的大量存取,以使其負荷過載


一般來說較難處理的是HTTP Flood及CC攻擊,若管理者經驗不足,很可能遭遇時即手足無措,只能眼睜睜看著網站癱瘓。切記受攻擊時莫慌亂,可參考本文所提到的一些解決方向,通常可使症狀有效減緩。但若攻擊量已大到無法用正常方式防護,建議諮詢專業的資安廠商,以適合的設備或解決方案作防護。

附錄:以下皆為十分建議參閱的參考資料、或測試工具,建議讀者詳加研究。
(1) Slowloris
(2) Slowloris DOS Mitigation Guide
(3) Layer 7 DDoS - OWASP
(4) Universal HTTP DoS - OWASP 2011 Presentation
(5) OWASP HTTP Post Tool
(6) Leveraging the Load Balancer to Fight DDoS

本文作者專長為入侵事件分析、網站安全防護、DDoS攻防