HTTP/2 Rapid Reset:解構破紀錄的攻擊

自 2023 年 8 月 25 日起,我們開始注意到很多客戶遭受到一些異常大型的 HTTP 攻擊。我們的自動化 DDoS 系統偵測到這些攻擊並加以緩解。但是,沒過多久,它們就開始達到破紀錄的規模,峰值最終剛好超過每秒 2.01 億次請求。這幾乎是之前記錄在案的最大規模攻擊的 3 倍。
而更加深入後發現,攻擊者能夠利用僅由 20,000 台機器組成的 Botnet 發起此類攻擊,而如今的 Botnet 規模可達數十萬或數百萬台機器。整個 web 網路通常每秒處理 10-30 億個請求,因此使用此方法可以將整個 web 網路的請求數量等級集中在少數目標上,而其實是可以達成的。
偵測和緩解
這是一種規模空前的新型攻擊手段,但 Cloudflare 的現有保護主要能夠吸收攻擊的壓力。我們一開始就注意到一些客戶流量影響 (在第一波攻擊期間約影響 1% 的請求); 如今,我們仍在持續改善緩解方法,以阻止對任何 Cloudflare 客戶發動的攻擊,而且不會影響我們的系統。
我們注意到這些攻擊,同時也有其他兩家主流的業內廠商(Google 和 AWS)發現相同的狀況。我們竭力強化 Cloudflare 的系統,以確保現今所有客戶都能免於此新型 DDoS 攻擊方法的侵害,而且沒有任何客戶受到影響。我們還與 Googel 和 AWS 合作,協調披露受影響廠商和關鍵基礎架構提供者遭受的攻擊。
此攻擊是透過濫用 HTTP/2 通訊協定部分功能和伺服器實作詳細資料才得以發動(請參閱 CVE-2023-44487 瞭解詳細資料)。因為攻擊會濫用 HTTP/2 通訊協定中的潛在弱點,所以我們認為任何實作 HTTP/2 的廠商都會遭受攻擊。這包括每部現代 Web 伺服器。我們與 Google 和 AWS 已經將攻擊方法披露給預期將實作修補程式的 Web 伺服器廠商。在這段期間,最佳防禦就是針對任何面向 Web 的網頁或 API 伺服器使用 DDoS 緩解服務(例如 Cloudflare)。
本文將深入探討 HTTP/2 通訊協定、攻擊者用於發動這些大規模攻擊的功能,以及我們為確保所有客戶均受到保護而採取的緩解策略。我們希望在發布這些詳細資料後,其他受影響的 Web 伺服器和服務即可取得實施緩解策略所需的資訊。此外,HTTP/2 通訊協定標準團隊和未來 Web 標準制定團隊,都能進一步設計出預防此類攻擊的功能。
RST 攻擊詳細資料
HTTP 是支援 Web 的應用程式通訊協定。HTTP 語意為所有版本的 HTTP 所共用;整體架構、術語及通訊協定方面,例如請求和回應訊息、方法、狀態碼、標頭和後端項目欄位、訊息內容等等。每個 HTTP 版本將定義如何將語意轉化為「有線格式」以透過網際網路交換。例如,客戶必須將請求訊息序列化為二進位資料並進行傳送,接著伺服器會將其剖析回可處理的訊息。
HTTP/1.1 採用文字形式的序列化。請求和回應訊息交換為 ASCII 字元串流,透過 TCP 等可靠的傳輸層傳送,並使用下列格式(其中的 CRLF 表示斷行和換行):
HTTP-message = start-line CRLF
*( field-line CRLF )
CRLF
[ message-body ]
例如,對 https://blog.cloudflare.com/
非常簡單的 GET 請求在網路上看起來像這樣:
GET / HTTP/1.1 CRLFHost: blog.cloudflare.comCRLFCRLF
回應如下所示:
HTTP/1.1 200 OK CRLFServer: cloudflareCRLFContent-Length: 100CRLFtext/html; charset=UTF-8CRLFCRLF<100 bytes of data>
此格式框住網路上的訊息,表示可使用單一 TCP 連線來交換多個請求和回應。但是,該格式要求完整傳送每則訊息。此外,為使請求與回應正確關聯,需要嚴格排序;表示訊息會依次交換且無法多工處理。以下是 https://blog.cloudflare.com/
和 https://blog.cloudflare.com/page/2/
的兩個 GET 請求:
GET / HTTP/1.1 CRLFHost: blog.cloudflare.comCRLFCRLFGET /page/2/ HTTP/1.1 CRLFHost: blog.cloudflare.comCRLFCRLF
回應如下:
HTTP/1.1 200 OK CRLFServer: cloudflareCRLFContent-Length: 100CRLFtext/html; charset=UTF-8CRLFCRLF<100 bytes of data>CRLFHTTP/1.1 200 OK CRLFServer: cloudflareCRLFContent-Length: 100CRLFtext/html; charset=UTF-8CRLFCRLF<100 bytes of data>