CDN流量放大攻擊思路
首先,為了對CDN進行攻擊,我們必須清楚CDN的工作原理,這里我們再來簡單介紹一下CDN的工作模型。

CDN的全稱是Content Delivery Network(內容分發網絡),通過在網絡各處的加速節點服務器來為網站抵擋惡意流量,把正常流量進行轉發。用簡單點的話來說,CDN一般有三個作用
1. 跨運營商加速:我們自己的網站常常只屬于一個運營商(比如:電信),而加速節點遍布每家運營商,于是和網站不同運營商(比如:聯通)的用戶訪問起來就不會那么慢了。
2. 緩存加速:很多的靜態資源以及一部分頁面更新都是比較慢的(比如首頁),這個時候CDN就會根據瀏覽器的max-age和last-modified值以及管理員的預設值來進行緩存,于是很多流量CDN節點就不會每次都來向網站請求,CDN節點可以直接自作主張地將命中的緩存內容返回。
3. 惡意流量過濾:這是CDN非常重要的一個作用,也是很多網站會用CDN的原因,因為CDN能為我們抵擋攻擊大流量攻擊、普通的攻擊(比如注入等),只有正常流量才會轉發給網站。
這里還要說明幾個名詞:
源站:我們自己的那個網站就被稱為是源站。
反向代理:CDN節點向源站請求數據的方式就叫反向代理,也就是上文所說的轉發。
回源:CDN節點向源站請求數據的行為就叫做回源。
下面開始我們的探究之旅。
我們在做OpenCDN測試的時候,遇到了一些小問題。發現一個沒有人訪問的網站居然會有流量,并且有著驚人的訪問次數。

我們的OpenCDN有2分鐘一次的反向代理檢測,但是這次數加起來也就區區的720次,而這400萬的訪問次數是哪里冒出來的?然后我們查看了日志,發現單個域名的日志到達了58G之多,而將其打開之后發現X-Forwarded-For字段中(X-Forwarded-For機制是通過一層代理后記錄一個IP,讓源站在使用CDN后能夠獲得真實的訪客IP而不是CDN節點IP)充斥著大量有的IP,而且都是本服務器IP。我們瞬間明白了什么,然后去管理端上驗證了一下,果不其然地,我們一不小心把源站IP設成了CDN節點的IP,不過當時我們并沒有發現。于是這么大的流量也好解釋了,由于2分鐘一次的檢測觸發CDN節點的回源,而這個站點的源站是CDN節點本身,于是CDN就開始不斷自身反向代理死循環,這樣一個請求就被無限地放大了。當超時或者HEADER太大(就是X-Forwarded-For字段導致HEADER溢出)的時候,請求會被丟棄。
把站點的源站IP設為CDN節點本身,能夠讓CDN節點進行自我的反向代理死循環,然后放大流量。
貌似有點意思,小伙伴們于是馬上就行動起來了,進行了實驗。
我們在安全寶上成功地將源站IP設置成了某個為我們加速的CDN節點IP,然后在美帝的一臺小vps上開webbench用2000個線程去打這個這個站點(無論是哪個CDN節點收到請求,請求最終都會匯聚到那個無辜的被設源站的CDN節點),不過實驗結果并不理想,節點沒有宕機,通過IP反查找到一臺和我們公用一個CDN節點的網站,通過這個CDN節點反向代理訪問那個網站,出現了卡頓和打不開情況,僅此而已。由于沒法采集到安全寶的這個節點的性能數據,我們也沒法對我們的攻擊做出評估。而且我們這個實驗缺少了一個對照組,到底是因為死循環把流量放大導致CDN節點卡頓,還是這個2000線程本身就能把CDN節點打卡。
于是我們總結了一下,猜想這種節點反向代理自身的攻擊手法可能可以適用于這樣的場景
你想要攻擊某個CDN節點,但是如果打404頁面消耗不了太多,而如果打CDN中的某個站點,因為流量會穿透過去,可能還沒有把CDN節點打掉,背后的站點早被穿透死了。這個時候,如果讓節點進行自身反向代理死循環,他就會把所有的流量給吃進去,并且沒法吐出來,這個時候可以產生一定量的流量杠桿效應,可以使得CDN節點出現異常。
不過話說回來,這種攻擊的防御方式也異常簡單,只要在設置源站IP的時候,不讓設置CDN節點IP就行了,只要在網站前端交互輸入的時候加點驗證就行了。
我們考慮到我們沒法對不是我們的CDN節點的帶寬上限,性能上限有個很好的評估,黑盒式的摸索可能帶來不了什么,于是我們拿我們自己的CDN節點開刀。
同時我們繼續對這個思路進行探索。我們發現,既然一個節點能死循環,那兩個節點怎么樣?結果是肯定的,并且產生了質的變化。我們假設了這樣的一個場景
我們的opencdn.cc在甲CDN服務商注冊服務,并且在乙CDN服務商注冊服務,然后我們得到甲CDN服務商的一個CDN加速節點1.1.1.1,然后又得到乙CDN服務商的一個CDN加速節點2.2.2.2。 然后聰明的你一定已經猜到了。我們把在甲CDN服務商設置源站為乙的加速節點2.2.2.2,在乙CDN服務商設置源站為甲的加速節點1.1.1.1,然后甲會問乙去索取源站,乙又來問甲索取源站,于是1.1.1.1和2.2.2.2就很開心地并且不停地交流了起來~

于是我們也進行了實驗。這次我們采用POST包進行測試。

用POST包的原因有兩個
1.CDN節點是會有緩存機制的,剛剛你請求的地址命中緩存,那么就直接返回,不會成為死循環了,而POST包則有一個很好的特性,絕對回源,一點也不含糊。
2.POST包可以擴大體積,在同等連接數的情況下讓效應更加明顯。
我們本次測試發送500個POST包,每個體積大概為10k左右。然后總共發送的流量為5M。
然后讓我們來看下兩個節點的反應

不過似乎到了帶寬上限。因為我們手中的機器畢竟也不是很給力。
然后讓我們來看下這500個POST包產生的效果
58.215.139.124 RX bytes:5473847154 (5.0 GiB) TX bytes:17106340685 (15.9 GiB) RX bytes:6014294496 (5.6 GiB) TX bytes:17717990777 (16.5 GiB) 流入 540447342(515MB) 流出 611650092(583MB) 112.65.231.233 RX bytes:5583125549 (5.1 GiB) TX bytes:5022744608 (4.6 GiB) RX bytes:6133578284 (5.7 GiB) TX bytes:5649798353 (5.2 GiB) 流入 550452735(524MB) 流出 627053745(598MB)
我們拿最小的進行測算吧,大概把流量擴大了100倍左右,然后如果把流入流出加起來就是擴大了200倍左右。
這一種攻擊方式和前一種相比有兩個優點
1.CDN服務商不能把源站IP做限制來防御,因為他無法知道別家的CDN節點IP。
2.能借刀殺人,可以用一家CDN服務商的CDN節點來打另外一家CDN服務商。
然后我們還進行了一些聯想,一個站點可以把兩個節點陷入死循環,如果把更多的節點來進來呢?
我們可以這樣。讓多個CDN節點和一個CDN節點死循環,把中間的CDN節點帶寬耗盡。

我們還可以這樣。讓三個CDN節點死循環,如果有做流量上的流入流出探測限制,這樣能保證流入流出不為一個IP。

畢竟在CDN服務商添加一個域名的代價是很小的(免費),我們可以用一個一個域名將節點串起來,然后啪一下開始流量死循環震蕩。
好了,讓我們用四個字總結一下這次的漏洞的特點:借力打力。
那么如何來防御這種以及可能演化出來的攻擊呢?
1. 禁止把源站IP設為CDN節點本身(這是必須的)。
2. 限制每個站點的帶寬。
3. 對請求超時的源站做一定限制。
4. 通過X-Forwarded-For來進行限制,超過多少層自動丟棄。
以及CDN節點已經存在的一系列的軟硬防都可以讓一部分的攻擊流量無法成型,自然也無法形成死循環震蕩。
本文僅為一種CDN流量放大攻擊的思路,只是做過一些小規模的實驗,也歡迎大牛們進行驗證。如有不足之處或者邏輯上的錯誤還請提出,謝謝您的閱讀。