一. HTTP請求走私攻擊
HTTP(Hyper Text Transfer Protocol,超文字傳輸協議)是全球資訊網伺服器傳輸超文字至本地瀏覽器的傳送協議。HTTP是一個基於TCP/IP通訊協議來傳遞資料(HTML 檔案, 圖片檔案, 查詢結果等)。
簡單的網路環境中,我們直接透過瀏覽器訪問伺服器,但是由於很多靜態資源需要在伺服器提供,這種方式無疑是大大增加了web伺服器的負荷。
在稍微複雜的網路環境中,為了提升使用者的瀏覽速度,提高使用體驗,減輕伺服器的負擔,很多網站都用上了CDN加速服務,即在源站的前加上一個具有快取功能的反向代理伺服器,使用者可直接從代理伺服器獲取靜態資源,而無需從源站所在伺服器中獲取。另一方面,這個反向代理可以隱藏web伺服器的真實IP,所以很多中小型網站都採用類似方案。常見拓撲圖如下:
一般來說,反向代理伺服器與後端的源站伺服器之間,會重用TCP連結。這也很容易理解,使用者的分佈範圍是十分廣泛,建立連線的時間也是不確定的,這樣TCP連結就很難重用,而代理伺服器與後端的源站伺服器的IP地址是相對固定,不同使用者的請求透過代理伺服器與源站伺服器建立連結,這兩者之間的TCP連結進行重用,也就順理成章了。
HTTP走私原理
當我們向代理伺服器傳送一個比較模糊的HTTP請求時,由於兩者伺服器的實現方式不同,可能代理伺服器認為這是一個HTTP請求,然後將其轉發給了後端的源站伺服器,但源站伺服器經過解析處理後,只認為其中的一部分為正常請求,剩下的那一部分被作為走私請求,當該部分對正常使用者的請求造成了影響之後,就實現了HTTP走私攻擊。
HTTP請求走私漏洞是因為前端的反向代理伺服器和後端的Web伺服器,對同一個請求的理解不一致造成的。因此,針對同一個HTTP請求,不同的伺服器可能會產生不同的處理結果,這樣就產生了安全風險。
如上圖,攻擊者惡意構造一個使用者請求。這個請求被前端伺服器理解為兩個完整的請求,而後端伺服器理解為一個請求和一個不完整的請求,於是後端伺服器會等待正常使用者的訪問請求,只有將“不完整”請求與正常請求拼接後才對其響應。
HTTP走私演示
根據破壞請求的方式不同,一般將HTTP走私分為幾種不同的情形(CL:Content-Length, TE:Transfer-Encoding):
Ø CL!=0
Ø CL-CL
Ø CL-TE
Ø TE-CL
Ø TE-TE
下面演示CL-TE的攻擊方式。所謂CL-TE,就是當收到存在兩個請求頭的請求包時,前端代理伺服器只處理Content-Length請求頭,而後端伺服器會遵守RFC2616的規定,忽略掉Content-Length,處理Transfer-Encoding請求頭。
Lab 地址:https://portswigger.net/web-security/request-smuggling/lab-basic-cl-te
連續傳送幾次請求就可以獲得該響應:
由於前端伺服器處理Content-Length,所以這個請求對於它來說是一個完整的請求,請求體的長度為6,如下:
0\r\n
\r\n
G
當請求包經過代理伺服器轉發給後端伺服器時,後端伺服器處理Transfer-Encoding,當它讀取到0\r\n\r\n時,認為已經讀取到結尾了,但是剩下的字母G就被留在了緩衝區中,等待後續請求的到來。
當我們重複傳送請求後,傳送的請求在後端伺服器拼接成了類似如下這種請求:
GPOST / HTTP/1.1\r\n
Host: ......
伺服器在解析時就會產生報錯。
利用http走私攻擊,攻擊者可以進行繞過前端伺服器的安全控制、獲取前端伺服器重寫請求欄位、獲取其他使用者的請求、進行快取投毒等攻擊。
防禦建議
針對http走私攻擊,通用的防禦措施大概有三種:
Ø 禁用代理伺服器與後端伺服器之間的TCP連線重用。
Ø 使用HTTP/2協議。
Ø 前後端使用相同的伺服器。
二. H2C走私攻擊
透過HTTP走私,攻擊者可以訪問內部的伺服器甚至是獲得各種提權的機會。當前HTTP/1.1被廣泛應用,但也暴露出一些問題,比如容易出現請求走私,使用HTTP/2可以解決走私,但是HTTP/2並不能完全防止走私。
下面我們演示透過HTTP/2 without TLS(h2c)將HTTP/1.1連線升級到HTTP/2並且可以Bypass反向代理的訪問控制,並且保持一個TCP長連線,導致HTTP請求不受反向代理的控制直接傳送到後端伺服器。
HTTP/2協議與H2C交換
通常HTTP/2協議在第一個HTTP請求之前,使用h2字串進行標識,h2c是在Web協議從HTTP/1.1升級到HTTP/2的步驟中使用的標頭。根據RFC-7540文件的描述,僅當客戶端和伺服器均支援HTTP/2時,才能使用HTTP / 2協議。
如何檢測服務端是否支援HTTP/2:
1:客戶端發起如下請求:
GET / HTTP/1.1
Host: test.example.com
Connection: Upgrade, HTTP2-Settings
Upgrade: h2c
2:如果支援HTTP/2,則伺服器響應:
HTTP/1.1 101 Switching Protocols
Connection: Upgrade
Upgrade: h2c
[ HTTP/2 connection ...
3:如果不支援HTTP/2,則伺服器響應:
Server ignored
如何將HTTP/1升級為HTTP/2:
當HTTP/1.x要升級到HTTP/2,識別符號、HTTP2-Settings標頭和Upgrade標頭需要出現在http請求中。識別符號的型別包括HTTP的h2c和HTTPS的h2。當Upgrade: h2c時,則以純文字形式傳遞HTTP/2:
GET / HTTP/1.1
Host: test.example.com
Connection: Upgrade, HTTP2-Settings
Upgrade: h2c
HTTP2-Settings: <base64url encoding ofHTTP/2 SETTINGS payload>
在伺服器支援HTTP/2時,它將101 Switching protocol轉發到客戶端並建立TLS連線(HTTP/2)與客戶端進行通訊。在這種情況下,使用TLS-ALPN協議。
在此過程中,使用APLN副檔名,客戶端向伺服器提供版本列表,然後伺服器選擇一個版本。同理,使用https時,HTTP/2選擇h2。當直接使用HTTP/2時,透過TLS-ALPN進行協議協商之後,進行TLS連線。
H2C走私原理
許多Web服務都使用反向代理。在此過程中,當需要進行101 Switching時,代理伺服器將充當中介,無需任何操作。透過閱讀RFC文件和TLS中關於HTTP/2配置文件,裡面宣告只有明文連線才可以使用h2c升級,並且轉發時不應包含HTTP2-Settings頭。
具體走私流程如下圖:
1、客戶端將HTTP/1.1升級請求傳送到反向代理(傳送了錯誤的標頭);
2、代理將請求轉發到後端,後端返回101 Swiching協議的響應,並準備接收HTTP/2通訊;
3 .代理從後端伺服器收到101響應時,將建立TCP隧道;
4 .客戶端從代理接收到101響應時,將重新用現有TCP連線並執行HTTP/2初始化;
5 .客戶端使用HTTP/2多路複用,傳送針對受限資源的違法請求;
6 .由於代理服不監視TCP通訊(HTTP透過策略),因此它將違法請求傳送到受限頁面;
7 .伺服器響應,轉發到TLS隧道,實現走私。
H2C走私演示
這裡使用docker環境試驗H2C走私,伺服器使用nginx,docker-compose將模擬三條代理鏈,如下表所示。
TCP埠 | 描述
|
8000
| HTTP h2c後端 |
8001
| HAProxy->h2c後端(不安全的預設配置) |
8002
| nginx->h2c後端(不安全自定義配置) |
8003
| Nuster->HAProxy->h2c後端(多層代理的不安全配置) |
這些代理鏈將導致啟用h2c的Golang後端,如下圖:
所有代理都拒絕訪問h2c後端上可訪問的/flag節點。我們嘗試透過在埠8001上執行的HAProxy伺服器訪問禁止的端點,如下圖:
使用h2cSmuggler工具來確認代理的不安全配置,如下圖:
使用h2cSmuggler執行h2c升級,透過代理對HTTP/2流量進行隧道傳輸,並從後端請求/flag端點,繞過代理的訪問控制,如下圖:
如上所示,我們成功繞過了代理的訪問控制來訪問內部的HTTP介面!
防禦建議
H2C具有減少頻寬的能力,所以它非常適合用於低延遲的內部網路通訊(微服務),避免了TLS的管理和(有爭議但經常被提及的)效能開銷。因此,流行的web框架通常支援一個配置選項來支援h2c升級,但是支援升級不是預設的,需要手動開啟。如果前端代理配置不安全,在微服務中使用h2c可能會增加被成功攻擊的可能性。
降低代理伺服器上h2c走私的風險方式:
1、需要WebSocket支援:僅允許值WebSocket用於HTTP/1.1升級頭(例如,upgrade:WebSocket)。
2、不需要WebSocket支援:不轉發Upgrade請求頭。
要使h2c走私成功,需要將升級頭(有時是連線頭)從邊緣伺服器成功轉發到支援h2c升級的後端伺服器。此配置可以發生在任何反向代理、WAF或負載平衡器上。
預設情況下,以下服務在代理傳遞過程中會轉發Upgrade和Connection標頭,從而使開箱即用的H2C走私成為可能:
Ø HAProxy
Ø Traefik
Ø Nuster
預設情況下,這些服務在代理通常過程中不轉發Upgrade和Connection標頭,但可以以不安全的方式配置(透過傳遞未過濾的Upgrade和Connection標頭):
Ø AWS ALB/CLB
Ø NGINX
Ø Apache
Ø Squid
Ø Varnish
Ø Kong
Ø Envoy
Ø Apache Traffic Server
參考連結
https://v0w.top/2020/12/20/HTTPsmuggling
https://labs.bishopfox.com/tech-blog/h2c-smuggling-request-smuggling-via-http/2-cleartext-h2c
https://www.anquanke.com/post/id/220996