我將在本文介紹如何將受害者的Web 瀏覽器變成一個異步的傳播平台,通過暴露一個獨立的服務器網站和內部網絡來轉移請求走私的邊界。你將學習如何將跨域請求與服務器漏洞相結合,以攻擊瀏覽器連接池、安裝後門,並釋放異步攻擊。使用這些技術,我將攻擊包括Apache、Akamai、Varnish、Amazon 和多個Web VPN 在內的目標。
接下來我將分享一種結合瀏覽器特點和自定義開源工具的方法。除此之外,我還將介紹一種黑盒分析策略,該策略解決了長期存在的異步障礙,並揭示了一種極其有效的新穎異步觸發器。由此產生的後果將包括客戶端、服務器端甚至MITM 攻擊。最後,我將介紹修改HTTPS 以在Apache 上觸發MITM 驅動的異步。
本文使用的術語“瀏覽器驅動的異步攻擊”表示可以通過Web 瀏覽器觸發的所有異步攻擊。這包括所有客戶端異步攻擊,以及一些服務器端攻擊。
本文的示例都是取材於真實網站。本文中引用的所有漏洞均已報告給相關供應商,並已修補,除非另有說明。
連接狀態攻擊如果你沒有嘗試請求走私攻擊,很容易忘記HTTP 連接重用並將HTTP 請求視為獨立對象。畢竟,HTTP 應該是無狀態的。然而,下面的層(通常是TLS)只是一個字節流,很容易找到實現不佳的HTTP 服務器,假設通過單個連接發送的多個請求必須共享某些屬性。
在野外看到的主要漏洞是服務器假設通過給定TLS 連接發送的每個HTTP/1.1 請求都必須具有相同的預期目標和HTTP Host 標頭。由於網絡瀏覽器符合這個假設,所以在有人使用Burp Suite 之前一切都會正常工作。
我發現了兩個不同的場景,這個漏洞均造成了很大的安全後果。
第一個請求驗證反向代理通常使用Host 標頭來識別將每個請求路由到哪個後端服務器,並有一個允許人們訪問的主機白名單:
但是,我發現一些代理只對通過給定連接發送的第一個請求應用此白名單。這意味著攻擊者可以通過向允許的目的地發出一個請求來訪問內部網站,然後通過相同的連接向內部網站發出一個請求:
幸運的是,這種漏洞非常罕見。
第一個請求路由第一個請求路由是一個密切相關的漏洞,發生在前端使用第一個請求的Host 標頭來決定將請求路由到哪個後端,然後將來自同一客戶端連接的所有後續請求路由到同一後端連接。
這本身不是一個漏洞,但它使攻擊者能夠使用任意Host 標頭攻擊任何後端,因此它可以與Host 標頭攻擊鏈接在一起,例如密碼重置攻擊、Web 緩存攻擊以及獲得對其他虛擬主機的訪問權限。
在此示例中,我們希望使用“psres.net”的攻擊主機標頭攻擊example.com 的後端,以進行密碼重置攻擊,但前端不會路由我們的請求:
然而,通過對目標網站的有效請求開始我們的請求序列,我們可以成功到達後端:
希望能給受害者發一封帶有釣魚鏈接的郵件:
你可以使用HTTP Request 走私中的“連接狀態探測”選項掃描這兩個漏洞。
大多數HTTP 請求走私攻擊可以描述如下:
發送一個長度不明確的HTTP 請求,使前端服務器與後端對消息的結束位置產生分歧,從而將惡意前綴應用於下一個請求。此分歧通常是通過混淆的傳輸編碼標頭來實現的。
該漏洞是由以下HTTP/2請求觸發的,該請求沒有使用任何混淆或違反任何RFC。甚至對於長度沒有任何歧義,因為HTTP/2 在幀層中有一個內置的長度字段:
此請求觸發了來自運行AWS Application Load Balancer (ALB) 作為其前端的各種網站的非常可疑的間歇性400 漏洞請求響應。調查顯示,ALB在將請求降級為HTTP/1.1轉發到後端時,添加了一個“Transfer-Encoding: chunked”標頭,而沒有對消息正文進行任何更改:
我只需要提供一個有效的被chunk對象:
這是一個發現漏洞的完美示例,它讓你回溯實際發生的情況和原因。這個請求只有一個不尋常的地方,它沒有Content-Length (CL) 標頭。由於前面提到的內置長度字段,在HTTP/2 中省略CL 是明確可接受的。然而,瀏覽器總是發送一個CL,所以服務器顯然不會期望沒有CL的請求。
檢測連接鎖定的CL.TE有了這兩個經驗教訓,我決定解決我去年在HTTP/2 研究中強調的一個未解決的問題,連接鎖定HTTP/1.1 請求走私漏洞的通用檢測。連接鎖定是指前端為與客戶端建立的每個連接創建一個到後端的新連接的常見行為。這使得直接的跨用戶攻擊幾乎不可能,但仍然留下了其他攻擊途徑。
要識別此漏洞,你需要通過單個連接發送“攻擊者”和“受害者”請求,但這會產生大量誤報,因為服務器行為無法與稱為HTTP管道的常見無害特性區別開來。例如,給定以下CL.TE 攻擊的請求/響應序列,你無法判斷目標是否易受攻擊:
HTTP 管道在Burp Repeater 中也可見,它通常被誤認為是真正的請求走私:
你可以通過將requestsPerConnection 設置從1 增加到自己在Turbo Intruder 中的測試,這只是要做好誤報的準備。
我浪費了很多時間試圖調整請求來解決這個問題。但事實證明,上面的響應不能證明存在漏洞,並且解決方案立刻就出現了:
從上面的響應序列可以看出,由於隨後的404 響應,後端正在使用傳輸編碼標頭解析請求。但是,你無法判斷前端是否使用請求的Content-Length ,並因此易受攻擊,或者是否安全地將其視為許多chunk,並假設橙色數據已通過管道傳輸。
要排除管道的可能性並證明目標確實易受攻擊,你只需在使用0\r\n\r\n 完成chunk處理請求後暫停並嘗試提前讀取。如果服務器在你的讀取嘗試期間做出響應,則表明前端認為該消息還是完整的,因此必須將其安全地分割成很多小塊:
如果你的讀取嘗試被暫停,這表明前端正在等待消息完成,因此必須使用Content-Length,從而使其易受攻擊:
這種技術也可以很容易地適應TE.CL 漏洞。將其集成到HTTP Request 走私中很快發現了一個在Barracuda WAF後面運行IIS 的網站,該網站容易受到傳輸編碼的影響。有趣的是,修復這個漏洞的更新已經出現了,但它是作為一種投機性的修復措施來實現的,所以它沒有被標記為安全版本,攻擊設備也沒有安裝它。
CL.0 瀏覽器兼容的異步雖然原先將另一個網站標記為最初看起來像連接鎖定的TE.CL 漏洞。但是,服務器沒有按預期響應我的手動探測和讀取。當我嘗試簡化請求時,我發現傳輸編碼標頭實際上被前端和後端完全忽略了。這意味著我可以完全利用它,發起攻擊:
前端使用的是Content-Length,但後端顯然完全忽略了它。結果,後端將正文作為第二個請求的方法的開始。忽略CL等同於將其視為值為0,因此這是一個CL.0異步,這是一種已知但較少探索的攻擊類。
關於此漏洞的第二個也是更重要的一點是,它是由一個完全有效的、符合規範的HTTP 請求觸發的。這意味著前端防禦它的機會為零,甚至可以由瀏覽器觸發。
攻擊是可能的,因為後端服務器根本不會接收到POST 請求。
amazon.com 上的H2.0對CL.0/H2.0 異步漏洞實施粗略掃描檢查後發現,它們影響了包括amazon.com 在內的眾多網站,亞馬遜網站忽略了發送到/b/的請求的CL:
我通過創建一個簡單的概念證明(PoC) 來確認此漏洞,該概念將隨機實時用戶的完整請求(包括身份驗證令牌)存儲在我的清單中:
在我向亞馬遜報告此事後,我意識到我還是錯過了一個危害更大的漏洞。攻擊請求非常普通,我可以讓任何人的網絡瀏覽器使用fetch() 發出它。通過在亞馬遜上使用HEAD 技術創建一個XSS 小工具並在受害者的瀏覽器中執行JavaScript,我可以讓每個受攻擊的受害者自己重新發起攻擊,並將其傳播給其他人。這樣就會產生一個異步攻擊,一種自我複制的攻擊,利用受害者在沒有用戶交互的情況下發起的攻擊,迅速利用亞馬遜上的每個活躍用戶。
我不建議在你的工作系統上嘗試此操作,但在暫存環境中嘗試可能會很有趣。
客戶端異步傳統的異步攻擊利用的是前端和後端服務器之間的連接,因此在不使用前端/後端架構的網站上是不可能的。從現在開始,我將把它稱為服務器端異步。大多數服務器端異步只能由發出格式漏洞的請求的自定義HTTP 客戶端觸發,但是,正如我們剛剛在amazon.com 上看到的,有時可以創建由瀏覽器驅動的服務器端異步。
瀏覽器導致異步的能力會引發一類全新的威脅,我將其稱為客戶端異步(client-side desync,CSD),其中異步發生在瀏覽器和前端服務器之間。這使得可以利用獨立的服務器網站,這很有價值,因為它們通常在HTTP 解析方面非常糟糕。
CSD 攻擊始於受害者訪問的感染網站,然後讓他們的瀏覽器向易受攻擊的網站發送兩個跨域請求。第一個請求的目的是使瀏覽器的連接異步,並使第二個請求觸發有害響應,通常使攻擊者控制受害者的帳戶:
攻擊方法在嘗試檢測和利用客戶端異步漏洞時,你可以重用來自服務器端異步攻擊的許多概念。主要區別在於,整個漏洞利用序列都發生在受害者的網絡瀏覽器中,這個環境比專用黑客工具更加複雜和不受控制。這帶來了一些新的挑戰,這給我在研究這項技術時帶來了很大的阻礙。為此,我開發了以下方法:
探測第一步是識別你的CSD 矢量。這個基本原語是漏洞的核心,也是構建漏洞利用的平台。我們已經在HTTP Request 走私和Burp Scanner 中實現了對這些的自動檢測,但是了解如何手動進行檢測仍然很有價值。
CSD 向量是具有兩個關鍵屬性的HTTP 請求。
首先,服務器必須忽略請求的Content-Length (CL)。這種情況通常會發生,因為請求要么觸發了服務器錯誤,要么服務器根本不期望向所選端點發出POST請求。嘗試針對靜態文件和服務器級重定向,並通過超長URL 和/%2e%2e 等半格式錯誤觸發漏洞。
其次,請求必須在web瀏覽器的跨域觸發。瀏覽器嚴重限制了對跨域請求的控制,因此你對標頭的控制有限,如果你的請求有正文,則需要使用HTTP POST 方法。最終,你只控制URL,加上一些零星的結尾,如Referer 標頭、正文和Content-Type 的後半部分:
現在我們已經編寫了攻擊請求,我們需要檢查服務器是否忽略了CL。作為簡單的第一步,使用超長的CL 發出請求並查看服務器是否仍然回复:
這是有希望的,但不幸的是,一些安全服務器無需等待正文即可響應,因此你會遇到一些誤報。其他服務器沒有正確處理CL,而是在響應後立即關閉每個連接,使它們無法被利用。要過濾掉這些,請在同一連接下發送兩個請求,並查找第一個請求的正文影響對第二個的響應:
要在Burp Suite 中對此進行測試,將兩個請求放入Repeater中的一個標籤組,然後使用單連接發送序列。你還可以在Turbo Intruder 中通過禁用管道並將concurrentConnections 和requestsPerConnection 分別設置為1 和100 來實現此目的。
如果可行,請嘗試更改正文並確認第二個響應按預期更改。這個簡單的步驟旨在確認你對正在發生的事情的心理模型與現實相符。我個人在運行Citrix Web VPN 的系統上浪費了很多時間,只是意識到它只是為發送到某個端點的每個請求發出兩個HTTP 響應。
最後,重要的是要注意目標網站是否支持HTTP/2。 CSD 攻擊通常利用HTTP/1.1 連接重用,並且Web 瀏覽器更喜歡盡可能使用HTTP/2,因此如果目標網站支持HTTP/2,你的攻擊不太可能起作用。有一個例外;一些轉發代理不支持HTTP/2,因此你可以利用任何使用它們的人。這包括公司代理、某些VPN 甚至一些安全工具。
確認現在我們已經找到了CSD 向量,我們需要通過在真實瀏覽器中復制行為來排除任何潛在的漏洞。我推薦使用Chrome,因為它擁有創造CSD漏洞的最佳開發工具。
首先,選擇一個網站來發起攻擊。此網站必須通過HTTPS 訪問,並且位於與目標不同的域中。
接下來,確保你沒有配置代理,然後瀏覽到你的攻擊網站。打開開發人員工具並切換到網絡選項卡。為了幫助調試以後可能出現的問題,我建議進行以下調整:
選擇“保留日誌”複選框。
右鍵點擊列標題並啟用“連接ID”列。
切換到開發人員控制台並使用fetch()執行JavaScript來複製攻擊序列。如下所示:
我已將獲取模式設置為“no-cors”以確保Chrome 在“網絡”選項卡中顯示連接ID。我還設置了憑據:“包含”,因為Chrome 有兩個獨立的連接池,一個用於帶有cookie 的請求,一個用於不帶cookie 的請求。你通常會想要利用導航,並且那些使用“with-cookies”池。
執行此操作時,你應該在Network 選項卡中看到兩個具有相同連接ID 的請求,第二個應該觸發404:
如果這如預期的那樣工作,那麼恭喜你,你已經發現自己的客戶端不同步了!
探索過程現在我們已經確認了客戶端異步,下一步就是找到一個小工具來利用它。在Network選項卡中意外觸發404可能會給一些人留下深刻印象,但它不太可能產生任何用戶密碼或獎勵。
至此,我們已經確定我們可以攻擊受害者瀏覽器的連接池,並對我們選擇的HTTP 請求應用任意前綴。這是一個非常強大的原語,它提供了三種廣泛的攻擊途徑。
存儲在檢索位置一種選擇是識別目標網站上允許你存儲文本數據的功能,並編寫前綴,以便受害者的cookie、身份驗證標頭或密碼最終存儲在你可以檢索它們的位置。這種攻擊流程的工作原理與服務器端請求走私幾乎相同,所以我不會詳述。
Chainpivot下一個選項是全新的,由受害者瀏覽器中的新攻擊平台提供。
在正常情況下,很多類型的服務器端攻擊只能由直接訪問目標網站的攻擊者發起,因為它們依賴於瀏覽器拒絕發送的HTTP 請求。這幾乎包括了所有涉及篡改HTTP報頭的攻擊——Web 緩存攻擊、大多數服務器端請求走私、主機標頭攻擊、基於用戶代理的SQLi 以及許多其他攻擊。
例如,不可能讓其他人的瀏覽器在User-Agent 標頭中使用log4shell 有效負載發出以下請求:
CSD 漏洞為這些針對網站的攻擊打開了大門,這些網站由於位於受信任的內部網或隱藏在基於IP 的限制之後而受到保護。例如,如果intranet.example.com 易受CSD 攻擊,你可以使用以下請求達到相同的效果,可以在瀏覽器中使用fetch() 觸發該請求:
Recommended Comments