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種判定方式
- 利用Content-Length字段來判定請求體的內容長度
- 利用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請求走私的類型
- GET請求web服務器不處理請求體,cdn處理請求體(body)
- 設置2個
Content-Length
, cdn解析第一個,web服務器解析第二個 - cdn使用
Content-Length
,web服務器使用Transfer-Encoding
(默認情況下,存在Transfer-Encoding
字段時,會優先按分塊傳輸來解析請求體) - cdn使用
Transfer-Encoding
,web服務器使用Content-Length
0x04例子
環境鏈接:
隨便注冊下就可以開始了
實驗要求,訪問 /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進行檢驗
要求是一樣的,也是刪除carlos賬號
那么利用上面的包依然可以訪問到/admin
目錄,這里注意Content-Length
長度為4,因為后面的web服務器是檢測Content-Length
的,因此它讀了4個字節后就結束了,這里的4個字符是22
加上\n\r
,共4個
之后后面的web服務器會把內容當成下一個請求包了
這里有個坑,burpsuit它會自動檢測body長度,然后自動更新Content-Length
字段,這里可以關閉這個功能,取消勾勾即可
接下來就和上面一樣了,添加Host: localhost請求體,之后刪除carlos賬號
完結撒花
0xff參考鏈接
https://www.freebuf.com/articles/web/213360.html
https://blog.csdn.net/weixin_44058342/article/details/102503140