前段時(shí)間上海一家游戲娛樂(lè)公司的網(wǎng)站遭到了基于頁(yè)面請(qǐng)求的DDOS分布式拒絕服務(wù)攻擊,網(wǎng)站陷入完全癱瘓狀態(tài),并被黑客的匿名信勒索,金額高達(dá)10萬(wàn)元,而在勒索過(guò)程中,這群黑客還表示會(huì)對(duì)騰訊QQ等網(wǎng)站下手,隨后QQ“服務(wù)器維護(hù)”幾天。12月5號(hào)的時(shí)候,全球BitTorrent服務(wù)器也受到了很強(qiáng)烈的DDOS攻擊,一度陷入癱瘓。而DDOS攻擊中最流行的也是威力最大的就是基于頁(yè)面的DDOS以及將這個(gè)攻擊理論發(fā)揮得淋漓盡致的攻擊工具CC,本文特邀CC作者和我們共同了解CC的相關(guān)攻擊原理和防范方法,希望能讓更多的朋友了解這樣的攻擊方式并能防范它。
我寫CC的思路及防范方法
文/ kiki
很多朋友都知道木桶理論,一桶水的最大容量不是由它最高的地方?jīng)Q定的,而是由它最低的地方?jīng)Q定,服務(wù)器也是一樣,服務(wù)器的安全性也是由它最脆弱的地方?jīng)Q定的,最脆弱的地方有多危險(xiǎn)服務(wù)器就有多危險(xiǎn)。DDOS也是一樣,只要你的服務(wù)器存在一個(gè)很耗資源的地方,限制又不夠,就馬上成為別人DDOS的對(duì)象。比如SYN-FLOOD,它就是利用服務(wù)器的半連接狀態(tài)比完全連接狀態(tài)更耗資源,而SYN發(fā)動(dòng)方只需要不停的發(fā)包,根本不需要多少資源。 一個(gè)好的DDOS攻擊必須是通過(guò)自己極少資源的消耗帶來(lái)對(duì)方較大的資源消耗,否則比如ICMP-FLOOD和UDP-FLOOD都必須和別人一樣大的帶寬,對(duì)方服務(wù)器消耗多少資源自己也得賠上多少資源,效率極其低下,又很容易被人發(fā)現(xiàn),現(xiàn)在基本沒(méi)有什么人用了。
攻擊原理
CC主要是用來(lái)攻擊頁(yè)面的。大家都有這樣的經(jīng)歷,就是在訪問(wèn)論壇時(shí),如果這個(gè)論壇比較大,訪問(wèn)的人比較多,打開頁(yè)面的速度會(huì)比較慢,對(duì)不?!一般來(lái)說(shuō),訪問(wèn)的人越多,論壇的頁(yè)面越多,數(shù)據(jù)庫(kù)就越大,被訪問(wèn)的頻率也越高,占用的系統(tǒng)資源也就相當(dāng)可觀,現(xiàn)在知道為什么很多空間服務(wù)商都說(shuō)大家不要上傳論壇,聊天室等東西了吧。
一個(gè)靜態(tài)頁(yè)面不需要服務(wù)器多少資源,甚至可以說(shuō)直接從內(nèi)存中讀出來(lái)發(fā)給你就可以了,但是論壇就不一樣了,我看一個(gè)帖子,系統(tǒng)需要到數(shù)據(jù)庫(kù)中判斷我是否有讀讀帖子的權(quán)限,如果有,就讀出帖子里面的內(nèi)容,顯示出來(lái)——這里至少訪問(wèn)了2次數(shù)據(jù)庫(kù),如果數(shù)據(jù)庫(kù)的體積有200MB大小,系統(tǒng)很可能就要在這200MB大小的數(shù)據(jù)空間搜索一遍,這需要多少的CPU資源和時(shí)間?如果我是查找一個(gè)關(guān)鍵字,那么時(shí)間更加可觀,因?yàn)榍懊娴乃阉骺梢韵薅ㄔ谝粋€(gè)很小的范圍內(nèi),比如用戶權(quán)限只查用戶表,帖子內(nèi)容只查帖子表,而且查到就可以馬上停止查詢,而搜索肯定會(huì)對(duì)所有的數(shù)據(jù)進(jìn)行一次判斷,消耗的時(shí)間是相當(dāng)?shù)拇蟆?
CC就是充分利用了這個(gè)特點(diǎn),模擬多個(gè)用戶(多少線程就是多少用戶)不停的進(jìn)行訪問(wèn)(訪問(wèn)那些需要大量數(shù)據(jù)操作,就是需要大量CPU時(shí)間的頁(yè)面)。很多朋友問(wèn)到,為什么要使用代理呢?因?yàn)榇砜梢杂行У仉[藏自己的身份,也可以繞開所有的防火墻,因?yàn)榛旧纤械姆阑饓Χ紩?huì)檢測(cè)并發(fā)的TCP/IP連接數(shù)目,超過(guò)一定數(shù)目一定頻率就會(huì)被認(rèn)為是Connection-Flood。 使用代理攻擊還能很好的保持連接,我們這里發(fā)送了數(shù)據(jù),代理幫我們轉(zhuǎn)發(fā)給對(duì)方服務(wù)器,我們就可以馬上斷開,代理還會(huì)繼續(xù)保持著和對(duì)方連接(我知道的記錄是有人利用2000個(gè)代理產(chǎn)生了35萬(wàn)并發(fā)連接)。
可能很多朋友還不能很好的理解,我來(lái)描述一下吧。我們假設(shè)服務(wù)器A對(duì)Search.asp的處理時(shí)間需要0.01S(多線程只是時(shí)間分割,對(duì)結(jié)論沒(méi)有影響),也就是說(shuō)他一秒可以保證100個(gè)用戶的Search請(qǐng)求,服務(wù)器允許的最大連接時(shí)間為60s,那么我們使用CC模擬120個(gè)用戶并發(fā)連接,那么經(jīng)過(guò)1分鐘,服務(wù)器的被請(qǐng)求了7200次,處理了6000次,于是剩下了1200個(gè)并發(fā)連接沒(méi)有被處理。有的朋友會(huì)說(shuō):丟連接!丟連接!問(wèn)題是服務(wù)器是按先來(lái)后到的順序丟的,這1200個(gè)是在最后10秒的時(shí)候發(fā)起的,想丟?!還早,經(jīng)過(guò)計(jì)算,服務(wù)器滿負(fù)開始丟連接的時(shí)候,應(yīng)該是有7200個(gè)并發(fā)連接存在隊(duì)列,然后服務(wù)器開始120個(gè)/秒的丟連接,我們發(fā)動(dòng)的連接也是120個(gè)/秒,服務(wù)器永遠(yuǎn)有處理不完的連接,服務(wù)器的CPU 100%并長(zhǎng)時(shí)間保持,然后丟連接的60秒服務(wù)器也判斷處理不過(guò)來(lái)了,新的連接也處理不了,這樣服務(wù)器達(dá)到了超級(jí)繁忙狀態(tài)。
蝴蝶:我們假設(shè)服務(wù)器處理Search只用了0.01S,也就是10毫秒(這個(gè)速度你可以去各個(gè)有開放時(shí)間顯示的論壇看看),我們使用的線程也只有120,很多服務(wù)器的丟連接時(shí)間遠(yuǎn)比60S長(zhǎng),我們的使用線程遠(yuǎn)比120多,可以想象可怕了吧,而且客戶機(jī)只要發(fā)送了斷開,連接的保持是代理做的,而且當(dāng)服務(wù)器收到SQL請(qǐng)求,肯定會(huì)進(jìn)入隊(duì)列,不論連接是否已經(jīng)斷開,而且服務(wù)器是并發(fā)的,不是順序執(zhí)行,這樣使得更多的請(qǐng)求進(jìn)入內(nèi)存請(qǐng)求,對(duì)服務(wù)器負(fù)擔(dān)更大。
當(dāng)然,CC也可以利用這里方法對(duì)FTP進(jìn)行攻擊,也可以實(shí)現(xiàn)TCP-FLOOD,這些都是經(jīng)過(guò)測(cè)試有效的。
防范方法
說(shuō)了攻擊原理,大家肯定會(huì)問(wèn),那么怎么防御?使用硬件防火墻我不知道如何防范,除非你完全屏蔽頁(yè)面訪問(wèn),我的方法是通過(guò)頁(yè)面的編寫實(shí)現(xiàn)防御。
1. 使用Cookie認(rèn)證。這時(shí)候朋友說(shuō)CC里面也允許Cookie,但是這里的Cookie是所有連接都使用的,所以啟用IP+Cookie認(rèn)證就可以了。
2. 利用Session。這個(gè)判斷比Cookie更加方便,不光可以IP認(rèn)證,還可以防刷新模式,在頁(yè)面里判斷刷新,是刷新就不讓它訪問(wèn),沒(méi)有刷新符號(hào)給它刷新符號(hào)。給些示范代碼吧,Session:
1 then
Session(“refresh”)=session(“refresh”)+1
Response.redirect “index.asp”
End if
這樣用戶第一次訪問(wèn)會(huì)使得Refresh=1,第二次訪問(wèn),正常,第三次,不讓他訪問(wèn)了,認(rèn)為是刷新,可以加上一個(gè)時(shí)間參數(shù),讓多少時(shí)間允許訪問(wèn),這樣就限制了耗時(shí)間的頁(yè)面的訪問(wèn),對(duì)正??蛻魩缀鯖](méi)有什么影響。
3. 通過(guò)代理發(fā)送的HTTP_X_FORWARDED_FOR變量來(lái)判斷使用代理攻擊機(jī)器的真實(shí)IP,這招完全可以找到發(fā)動(dòng)攻擊的人,當(dāng)然,不是所有的代理服務(wù)器都發(fā)送,但是有很多代理都發(fā)送這個(gè)參數(shù)。詳細(xì)代碼:
這樣會(huì)生成CCLog.txt,它的記錄格式是:真實(shí)IP [代理的IP] 時(shí)間,看看哪個(gè)真實(shí)IP出現(xiàn)的次數(shù)多,就知道是誰(shuí)在攻擊了。將這個(gè)代碼做成Conn.asp文件,替代那些連接數(shù)據(jù)庫(kù)的文件,這樣所有的數(shù)據(jù)庫(kù)請(qǐng)求就連接到這個(gè)文件上,然后馬上就能發(fā)現(xiàn)攻擊的人。
4. 還有一個(gè)方法就是把需要對(duì)數(shù)據(jù)查詢的語(yǔ)句做在Redirect后面,讓對(duì)方必須先訪問(wèn)一個(gè)判斷頁(yè)面,然后Redirect過(guò)去。
5. 在存在多站的服務(wù)器上,嚴(yán)格限制每一個(gè)站允許的IP連接數(shù)和CPU使用時(shí)間,這是一個(gè)很有效的方法。
CC的防御要從代碼做起,其實(shí)一個(gè)好的頁(yè)面代碼都應(yīng)該注意這些東西,還有SQL注入,不光是一個(gè)入侵工具,更是一個(gè)DDOS缺口,大家都應(yīng)該在代碼中注意。舉個(gè)例子吧,某服務(wù)器,開動(dòng)了5000線的CC攻擊,沒(méi)有一點(diǎn)反應(yīng),因?yàn)樗械脑L問(wèn)數(shù)據(jù)庫(kù)請(qǐng)求都必須一個(gè)隨機(jī)參數(shù)在Session里面,全是靜態(tài)頁(yè)面,沒(méi)有效果。突然發(fā)現(xiàn)它有一個(gè)請(qǐng)求會(huì)和外面的服務(wù)器聯(lián)系獲得,需要較長(zhǎng)的時(shí)間,而且沒(méi)有什么認(rèn)證,開800線攻擊,服務(wù)器馬上滿負(fù)荷了。
代碼層的防御需要從點(diǎn)點(diǎn)滴滴做起,一個(gè)腳本代碼的錯(cuò)誤,可能帶來(lái)的是整個(gè)站的影響,甚至是整個(gè)服務(wù)器的影響,慎之!