文/Nick Sullivan翻譯/Tao Wan
防止惡意請求循環
文/Nick Sullivan1翻譯/Tao Wan2
Web是一個協作的生態系統。 Web標準的存在,保證了網絡的參與者以可預見的方式行事。如果網絡參與者偏離了既定標準,就會發生意想不到的結果,本文描述的就是這樣一個意想不到的結果。
最近一組研究人員發表在NDSS 2016 的一篇論文 “Forwarding Loop Attacks in the Content Delivery Networks“ (針對內容分發網絡的轉發環路攻擊)[1]中,描述了Web服務如果以不兼容的方式進行交互時會發生什么。他們描述的攻擊,惡意用戶可以讓多個服務提供商相互發送其請求,從而導致無休止的循環。這樣的請求循環可以導致服務供應商的資源枯竭和服務拒絕。該論文還展示了,轉發環路攻擊對大批的CDN是可行的。
針對上述論文提到的攻擊,我們已經對CloudFlare的服務做了相應的修改,使之符合于HTTP代理的相關標準。然而要徹底避免上述攻擊,所有的代理服務必須都遵循相關標準。如果有一個服務供應商不遵循標準,其他所有遵循標準的服務商,仍然可以被攻擊。在本文中,我們將介紹這種新型的攻擊,并說明一個供應商如何從問題的一部分,變成解決方案的一部分。
CloudFlare 是使用反向代理來工作的。當HTTP(S)請求進入CloudFlare的網絡,會發生下面的兩種情況之一:一是CloudFlare返回緩存的響應;二是CloudFlare向原始網站發出請求,并轉發原始網站返回的相應。CloudFlare可以檢查和修改通過其網絡的請求,該能力使得許多強大的功能成為可能,如高速緩存、WAF(Web應用防火墻)、RocketLoader等。
另外,在一個網站的前面使用多個反向代理也并不少見。這種做法稱為堆疊代理(Stacking proxies),通常被用來提供多個不同的服務特性。例如,可以使用CloudFlare進行緩存,但使用另外一個服務商的WAF。雖然我們更希望客戶使用CloudFlare提供的先進的WAF,但使用其他的WAF也是合理的,并且很多客戶也是這么做的。多個代理可以在原始服務器的前面被堆疊,但是,如果最后一個代理指向了第一個代理會發生什么?這將得到一個代理循環。
兩個代理形成的循環很容易理解。配置第一個反向代理使用第二反向代理作為源網站,同時配置第二個反向代理使用第一個作為它的源網站,如圖1所示。
從理論上說,發給該網站的任何請求最終會在兩個代理之間被來回發送。每次循環都將導致一個請求被發送,并消耗資源。幸運的是,大多數反向代理都有保護,可以避免這樣的簡單攻擊。
HTTP 1.1的作者意識到請求循環的可能性,并在制定標準時,定義了相應的保護。這個環路保護是通過 “Via” 報頭來實現的。下面的段落來自 RFC 7230的5.7.1部分:
“Via”頭字段,表示在用戶代理和服務器之間(請求方向),或者在原始服務器和客戶端之間(響應方向),存在中間協議和接收者。這類似于電子郵件的“Received”頭字段(RFC5322 的3.6.7)?!癡ia”頭字段可以用來向前追蹤消息,從而避免請求循環,并發現請求/響應鏈中發件者的協議功能。
一個“Via”頭字段的多個域值可以被用來表示單個代理或網關。每一個中間人都追加自己的信息,來表述如何接收到該消息,最終結果是,所有轉發代理形成了一個排序。一個代理在轉發每個消息時, 必須按照以下要求,添加相應的“Via”頭字段。一個HTTP到HTTP的網關必須在每個入站請求消息中添加 “Via”頭字段,可以在轉發的響應消息中添加“Via”頭字段。

圖1
例如,一個請求消息可以從HTTP / 1.0的用戶代理被發送到一個叫“fred”的內部代理,該內部代理使用HTTP / 1.1把請求轉發到一個公共代理p.example.net,該公開代理則將請求轉發到原始服務器www.example.com, 從而完成了該次請求。www. example.com接收到的請求將有以下的 Via頭字段:

圖2
Via: 1.0 fred, 1.1 p.example.net
一個發送者,不應該合并“Via” 的多個條目,除非它們屬于同一個組織,并且主機信息已經被匿名化了。如果“Via”的多個條目包含了不同的協議值,則絕對不可以被合并。
CloudFlare目前使用了這一機制,以防止請求循環。當一個請求通過CloudFlare的網絡時,并且不在緩存中,CloudFlare將創建一個新的請求,發給原始網站。CloudFlare發出請求的“Via”頭字段中, 包含從上一個節點收到請求的HTTP 協議版本,和一個CloudFlare專用值:
Via:1.1 CloudFlare
如果一個請求進入“CloudFlare”網絡時,其Via頭字段里包含了“cloudflare”這個值,則會返回錯誤。這可以避免在CloudFlare網絡中形成請求循環,如圖2所示。
然而,實施這種保護手段,就可以保證CloudFlare不會受到HTTP請求循環的攻擊嗎?對此不要過快下結論。
并不是所有的反向代理服務都遵循RFC 7230標準。一些代理服務給客戶提供過濾或修改HTTP頭的能力,包括“Via”頭。這其實是RFC不允許的:代理有義務保留其他代理添加的“Via”頭字段里的標簽。代理只允許修改其自身組織添加的頭部分。允許代理修改其他代理添加的“Via”頭字段,會導致壞事的發生。
我們用上面的兩個代理回路的例子來解釋。假設兩個代理服務器在發送請求時,都會添加自己的的Via頭,并在收到帶有自己“Via”頭的請求時,返回錯誤。假設第二個代理會把接收到的請求里的“Via”頭過濾掉。當請求從第二代理返回時,第一個代理已經無法確認它已經轉發過該請求。然后,該請求會被當正常請求一樣處理,被發送給第二個代理。第二個代理如果不做回路檢查,則會繼續將該請求發送回給第一個代理,如此循環往復,如圖3所示。

圖3
這種攻擊可以造成很大的傷害,耗盡兩個服務提供商的資源。它還可能導致自動攻擊防御系統的意外行為,從而進一步導致一個服務提供商被另外一個封鎖。
有一些Web服務器,如果收到的請求包含“Via”頭字段,在缺省情況下,不會壓縮返回的響應。這可以導致你的服務器在給CloudFlare發送數據時,浪費不必要的帶寬。這時可以咨詢CloudFlare的知識庫,來學習如何測試所在服務器是否有此行為,以及如何將其禁用。如果不知該如何修改服務器的配置,可以聯系CloudFlare的技術支持。
上述NDSS論文的作者們在論文發布之前,聯系了受影響的CDN廠家,但可能不是所有的廠家都已經修復了。如果所在組織向公眾提供反向代理服務,我們建議實現以下邏輯:一是在任何情況下,都不要讓客戶刪除或修改到達他們網站的請求里的“Via”頭字段。二是進行代理時,追加符合RFC 7230標準的“Via”頭字段。三是如果一個請求包含你自己的“Via”頭字段,請返回相應的錯誤。
一個不符合標準的反向代理服務可能會給大家導致不良后果,讓我們一起努力,以避免請求循環。
(作者單位:1為CloudFlare;2為Huawei Canada)
[1] Jianjun Chen, Jian Jiang, Xiaofeng Zheng, Haixin Duan, Jinjin Liang, Tao Wan, Kang Li, Vern Paxson, Forwarding-Loop Attacks in Content Delivery Networks, accepted by NDSS 2016 。NDSS是國際網絡安全四大會議之一,本文獲NDSS 2016年杰出論文(Distinguished Paper)。
[2]論文下載:http://netsec.ccert.edu.cn/duanhx/files/2010/12/cdn_loop-final-cameraready.pdf
[3]原文地址: https://blog.cloudflare.com/preventing-malicious-request-loops/