HTTP請求走私

0x00 前言

請求走私的的環境需要有,1臺cdn緩存服務器,一臺真正處理的業務的web服務器,用戶訪問網站表面上看着是直接訪問該web服務器,其實是從cdn上獲取緩存的數據,並沒有去請求真正web服務器

0x01 預備知識

cdn的作用是爲了緩存靜態頁面,這樣可以讓真正的web服務器的壓力不要太大。另一個作用是爲了隱藏web服務器的真實ip地址。(隨手用QQ截圖畫了個圖

cdn與web服務器之間相當於代理的關係

用戶去請求部署了cdn的web站點,其實請求的資源cdn上有,直接從cdn上發送給用戶,而不會再走到後面的web服務器,這樣就節省了真正服務器的開銷。如果沒有再去請求web服務器,

0x02 HTTP走私原理

HTTP 請求的請求體有2種判定方式

  1. 利用Content-Length字段來判定請求體的內容長度
  2. 利用Transfer-Encoding字段來判定請求體的結束位置

Content-Length

​ 正常post請求,會帶上請求體(body),請求體有多長,Content-Length的值就是多少

Transfer-Encoding

Transfer-Encoding就是分塊傳輸的標誌,它不靠Content-Length來告訴web服務器請求體有多長,而是靠0這個字符來代表分塊結束,之後還要換行2次(重點!!!)

至於分塊傳輸的格式

3
aaa
5
aa
a
0


上面這行代表着分了3段,第一段是3個a,第二段是2個a和一個\r和一個\n再1個a,第三段是空

aaa上面的3是長度,表示第一段有3個字節,同理第二段加上換號就是5個字節,最後一段爲空就0個字節,但最後有2個換行表示結束

再注意,長度是以16進製表示,即如下下面字節長度爲27,則長度爲1b

請求走私的原理是因爲,假如cdn對請求有限制,而web服務器對請求沒有限制,此時cdn和web服務器的對body的處理方式不一致,就會導致繞過cdn的限制,直接去請求web服務器的資源。

說到這裏有點抽象,舉個下面要用到的lab環境的例子

cdn不準請求/admin目錄,web服務器可以請求/admin 目錄,而我們訪問肯定是先請求cdn的,因此就被攔截了。

我們要做的是去請求真正web服務器的/admin目錄,就不會被攔截。如果cdn和web服務器對body檢測機制不同,HTTP請求走私就可以派上用場了。

0x03請求走私的類型

  1. GET請求web服務器不處理請求體,cdn處理請求體(body)
  2. 設置2個 Content-Length, cdn解析第一個,web服務器解析第二個
  3. cdn使用Content-Length,web服務器使用Transfer-Encoding(默認情況下,存在Transfer-Encoding字段時,會優先按分塊傳輸來解析請求體)
  4. cdn使用Transfer-Encoding,web服務器使用Content-Length

0x04例子

環境鏈接:

https://portswigger.net/web-security/request-smuggling/exploiting/lab-bypass-front-end-controls-cl-te

隨便註冊下就可以開始了

實驗要求,訪問 /admin目錄,並以admin的身份去刪除carlos用戶

該實驗室是前面的cdn使用的是Content-Length來檢測body,後面的web服務器使用的是Transfer-Encoding來進行檢測body

直接請求admin,可以看到被403了

接下來使用分塊傳輸,最前面請求的不是/admin,而是去請求可以請求到的/根目錄

利用GET協議發現不被允許,因此改成POST協議

可以看到已經返回的值和只請求/是不同的,提示到需要是本地訪問,或者登陸administrator賬號,登陸administrator賬號不太現實,本地訪問的話只有加上Host: localhost即可

這裏處理的流程大致是這樣的

  • cdn看Content-Length字段來判定請求體信息,它會把下面所以給當成請求體,於是請求合法,發送給後面的web服務器
  • web服務器因爲有Transfer-Encoding字段存在,並且下面是以分塊傳輸的格式,因此以分塊傳輸來劃分body內容
  • 遇到了0,因此此時web服務器認爲該HTTP請求已經結束了,再次往下GET /admin HTTP/1.1,就當成新的HTTP請求,於是返回了/admin目錄的信息

繼續添加Host: localhost的請求頭(有時候請求多次才靈光,可能是緩存問題?

可以看到已經有admin的權限了,並且有刪除carlos賬號的url請求

這裏有個問題爲什麼加localhost得到的結果不是用戶的localhost地址,而是web服務器的地址。我理解的是,該請求發送給後面真正的web服務器時,web服務器是拿到這些HTTP請求,從web服務器端把這些HTTP請求進行發送,最後將結果返回給用戶。

也就是這HTTP的request是web服務器發出的,於是localhost就是web服務器了

最後刪除carlos賬號,就完成了本次實驗

相對的來,下面這個實驗是,cdn使用分塊傳輸,後面web服務器使用的Content-Length進行檢驗

https://portswigger.net/web-security/request-smuggling/exploiting/lab-bypass-front-end-controls-te-cl

要求是一樣的,也是刪除carlos賬號

那麼利用上面的包依然可以訪問到/admin目錄,這裏注意Content-Length長度爲4,因爲後面的web服務器是檢測Content-Length的,因此它讀了4個字節後就結束了,這裏的4個字符是22加上\n\r,共4個

之後後面的web服務器會把內容當成下一個請求包了

這裏有個坑,burpsuit它會自動檢測body長度,然後自動更新Content-Length字段,這裏可以關閉這個功能,取消勾勾即可

接下來就和上面一樣了,添加Host: localhost請求體,之後刪除carlos賬號

完結撒花

0xff參考鏈接

https://xz.aliyun.com/t/6631

https://www.freebuf.com/articles/web/213360.html

https://blog.csdn.net/weixin_44058342/article/details/102503140

https://portswigger.net/web-security/request-smuggling/exploiting/lab-bypass-front-end-controls-cl-te

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章