中新網安安全實驗室|HTTP請求走私漏洞及靶場復現
2019年8月,hackerone提交了(le)關(guan)于PayPal HTTP請求(qiu)走私+存(cun)儲性XSS (鏈接://hackerone.com/reports/510152) 攻擊可以(yi)直接對PayPal登陸頁面進行(xing)控制,并且能獲(huo)取所有(you)用戶(hu)密碼(ma),危害極大。這是什(shen)么漏洞,我(wo)們今天來揭開它的面紗:HTTP請求走(zou)私(si)(HTTP Request Smuggling) 
圖(tu)片來源(yuan): //portswigger.net/research/http-desync-attacks-request-smuggling-reborn 我們先了解下今年black hat上共享的Paypal漏洞實例(引用://i.blackhat.com/eu-19/Wednesday/eu-19-Kettle-HTTP-Desync-Attacks-Request-Smuggling-Reborn.pdf )代碼如下:由于PayPal登錄頁面有一個CSP規則腳本-SRC,阻止了這個重定向后來,作者登錄頁面在動態生成的iframe中將c.payal.com上的子頁面加載了。此子頁面未使用CSP,還使用了由作者的JS文件!可以控制iframe頁面,但是由于同源策略,無法讀取父頁面的數據。然后,在paypal.com/us/gifts上發現了一個不使用CSP的頁面,并且還導入了污染JS文件。通過使用自己的JS將c.paypal.com iframe重定向到該URL(并第三次觸發自己的JS導入),他終于可以訪問父級并從使用Safari或IE PayPal登錄的每個人那里竊取純文本的PayPal密碼。看著是挺繞的,但是慢慢想一下很簡單,PayPal主站是有同源策略,旁站存在HTTP請求走私直接加載自己的JS,PayPal.com/us/gifts可以繞過主站可以加載自己的JS,然后成功竊取每個登陸PayPal賬號密碼。好,我們來了解下什么是HTTP走私。首先我們要了解下HTTP簡介和概念。
HTTP請求走私是一種干擾網站(zhan)處理從一個或多(duo)個用戶接收的HTTP請求序列的方(fang)式(shi)的技術,它(ta)可以繞過(guo)安全控制,未(wei)經授權訪問敏感(gan)數據(ju)并且直接危害其他應(ying)用(yong)程序用(yong)戶。
我們知道(dao)HTTP協議是(shi)Hyper Text Transfer Protocol(超文本傳輸協議)的縮寫(xie),是(shi)用于(yu)從(cong)萬維網(wang)(WWW:World Wide Web)服務器傳(chuan)輸超(chao)文本(ben)到本(ben)地(di)瀏覽器的傳(chuan)送協議,HTTP是一個基于TCP/IP通信協議(yi)來傳(chuan)遞數據(ju)。
自HTTP/1.1開始,支(zhi)持通過單個基礎TCP或者SSL/TLS套接字發送多個HTTP請求(qiu),該協(xie)議將HTTP請求(qiu)背靠(kao)背放置(zhi),服務器(qi)解析(xi)標頭(tou)以計(ji)算出(chu)每個結束的(de)位置(zhi)及下(xia)個開始位置(zhi)。1. Persistent Connection(持(chi)久連接)HTTP運行(xing)在TCP連接之上,存在TCP三(san)次握手,慢啟動等特點,為(wei)了盡可能提高HTTP的(de)(de)性能,引用了長連接的(de)(de)概念,目的(de)(de)解決(jue)HTTP傳輸(shu),多次(ci)建立連接信息(xi)的情(qing)況,通(tong)過(guo)Connection: keep-alive 頭部來實(shi)現,服(fu)務器和(he)客戶端使用它告訴對方(fang)在(zai)發(fa)送完數據之后(hou)不斷開TCP連接,那么問(wen)題(ti)來了,我們該如何判斷信息是否(fou)傳輸完成(cheng)呢。為了解決這(zhe)個問(wen)題(ti),于是引入下面(mian)的請(qing)求頭Content-length。2. Content-length(實體長度)Content-Length實(shi)體標頭字段發送給接收方(fang)的實(shi)體的大小(xiao)(以OCTET的(de)十(shi)進制數為單位(wei))通過判斷Content-lenget長(chang)度相等,服務器便知道這個時(shi)候(hou)可以斷(duan)開連接,如果Content-length和實體的實際(ji)長度短會造成內(nei)(nei)容(rong)截斷,如(ru)果比實際(ji)內(nei)(nei)容(rong)長,會為缺(que)少的內(nei)(nei)容(rong)進(jin)行自動(dong)填充,看似(si)完美了(le),但(dan)是服(fu)務器為了(le)計算信息內(nei)(nei)容(rong),將所有內(nei)(nei)容(rong)緩(huan)存下載,并(bing)沒有解(jie)決web應用優(you)化。3. Transfer-Encoding: chunked(分塊編碼(ma))為(wei)了解決Web優化,引入一個新的請(qing)求(qiu)頭Transfer-Encoding: chunked 也就是分(fen)塊(kuai)編碼,加入(ru)請求頭(tou)后,報(bao)文會(hui)使用分(fen)塊(kuai)的形式進行(xing)傳(chuan)輸,不(bu)在需要緩存所有實例內容,只需要緩存分(fen)塊(kuai)即可(ke),分(fen)塊(kuai)要求,每塊(kuai)必(bi)須包含16進制的長度和數據,長度值獨立占據一行,不包括CRLF(\r\n),也不包括結(jie)尾的(de)CRLF,當分(fen)塊(kuai)的長度為(wei)0,且沒有數據,連接結束大多數網站(zhan)為了提高(gao)瀏覽速度,用(yong)戶體(ti)驗,減少服務(wu)器負(fu)擔(dan),使(shi)用(yong)CDN加速服(fu)務,原理(li)(li)就(jiu)是在源(yuan)(yuan)(yuan)站前面加入(ru)具有緩存功能(neng)的(de)反(fan)向(xiang)代(dai)(dai)理(li)(li),當用戶請(qing)求靜態(tai)資(zi)源(yuan)(yuan)(yuan),可以直接(jie)到代(dai)(dai)理(li)(li)服(fu)務器(qi)中(zhong)獲取,不在從源(yuan)(yuan)(yuan)站服(fu)務器(qi)獲取,反(fan)向(xiang)代(dai)(dai)理(li)(li)與后端源(yuan)(yuan)(yuan)站服(fu)務器(qi)之(zhi)間(jian),會(hui)重用TCP鏈接,因(yin)為(wei)不同的用戶請(qing)求將通過(guo)代(dai)理服(fu)務(wu)器與(yu)源站服(fu)務(wu)器連接,代(dai)理服(fu)務(wu)器與(yu)后端的源站服(fu)務(wu)器的IP是相對固定。但是(shi)(shi)由于兩者(zhe)服務器的實現方(fang)法(fa)不同(tong),如果用戶提供模糊的請求(qiu)可能代理(li)服務器認為是(shi)(shi)一個HTTP請(qing)求,然(ran)后(hou)轉發給后(hou)端源站服(fu)務器,源站服(fu)務器經(jing)過解(jie)析處理后(hou),只(zhi)認為其中(zhong)一部分請(qing)求,剩下的另(ling)外一部分就是(shi)走私請(qing)求,形成(cheng)這個原因,是(shi)由于(yu)HTTP規范提供(gong)了兩種不同方式來指定請(qing)求的結束位置,它們是Content-Length標頭和Transfer-Encoding標頭。
我這(zhe)里用的(de)是//portswigger.net演示(shi)環境,工具:burp suite,首(shou)先關閉(bi)Update content-length。
我們(men)來看下常見HTTP走私有三種(zhong)情況。(1) CL.TE漏洞CT-TE: 前端使用Content-length,后端使用Transfer-Encoding前端服務器使用(yong)Content-Length頭,而(er)后端服務器使用Transfer-Encoding頭。//portswigger.net/web-security/request-smuggling/lab-basic-cl-te第一次請(qing)求(qiu),返回正常頁(ye)面:第二次請求,惡意請求被(bei)執行(xing):前端服務器處(chu)理Content-Length標頭(tou),并(bing)確定請求正文的長(chang)度(du)為9個字節,直(zhi)到的結尾(wei)test該請求被轉(zhuan)發到后(hou)端服務器。后端服務器處(chu)理Transfer-Encoding標頭(tou),因(yin)此(ci)將消息正文視(shi)為(wei)使用(yong)分塊編(bian)碼。它處理第一個塊,該塊被(bei)聲(sheng)明為(wei)零長(chang)度,因(yin)此(ci)被(bei)視(shi)為(wei)終止請求。接下(xia)來(lai)的字節test保(bao)留(liu)未(wei)處理,后端服(fu)務器會(hui)將其視為序列中(zhong)下一(yi)個請求的開(kai)始。(2) TE.CL漏洞前(qian)端服務器(qi)使用Transfer-Encoding頭(tou),而后端(duan)服務(wu)器使用Content-Length頭。//portswigger.net/web-security/request-smuggling/exploiting/lab-bypass-front-end-controls-te-cl,當我們(men)直接訪問(wen)/admin直接顯示403,無(wu)法訪問。該怎么辦(ban)呢,如果我們使用下面請(qing)求是不是就繞過了(le)呢?  是的,但是提示必須host是localhost才能訪問,那我們直接加入HOST: localhost 可(ke)見加入(ru)HOST:localhost 發送請(qing)求,直接進(jin)入管理頁面。

因為前端服(fu)務器處理Transfer-Encoding標頭(tou),使用分塊編碼。一直(zhi)讀到為(wei)0,認(ren)為(wei)讀取完(wan)畢,此(ci)時這個請(qing)求(qiu)對代理服務器(qi)來說(shuo)是一個完(wan)整的請(qing)求(qiu),然后轉發(fa)給后端(duan)服務器(qi),后端(duan)服務器(qi)對Content-Length標頭進行(xing)處理,當它讀完(wan)71后認(ren)為請求(qiu)結(jie)束,后面的數據(ju)就認(ren)為另(ling)一個請求(qiu),也就是成功執行(xing)。71是文件字節數(shu)十六進制轉換出來的十進制數(shu)。 文件字節數(shu)為十六進(jin)制(zhi)數(shu):113轉換為十進(jin)制(zhi)數(shu):71 TE-TE行為很容(rong)易理解,當前端服務(wu)(wu)器和后(hou)端服務(wu)(wu)器都支(zhi)持Transfer-Encoding標頭,我(wo)們可以通過(guo)某種方式混(hun)淆標頭來(lai)誘導其中一(yi)臺服務(wu)器不對其進行處理。可以說還(huan)是CL-TE TE-CL。 //portswigger.net/web-security/request-smuggling/exploiting/lab-bypass-front-end-controls-te-cl使用下(xia)面數據(ju)包進行發送: 當我們第(di)二次發包,直接執(zhi)行(xing)后面的(de)GPOST:
六、如何防(fang)止HTTP請求(qiu)走私漏洞1.不要(yao)重復使用后端連接,HTTP走(zou)私(si)依賴多個后端(duan)多路復(fu)用,后端(duan)服務器將走(zou)私(si)數(shu)據(ju)包與(yu)合法數(shu)據(ju)包一起處理,產生危(wei)害行為。如果每個請求(qiu)單(dan)獨聯系發送,惡意(yi)的走(zou)私(si)請求(qiu)不在有效(xiao)。
2.使用HTTP / 2進(jin)行后端連接(jie),因為此協議禁止使(shi)用分塊傳輸編(bian)碼。3.前端服務器和后端服務器確保使(shi)用完全相同的Web服(fu)務器(qi)軟(ruan)件,以便它們就(jiu)請求之間的界限達成一致(zhi)。//portswigger.net/research/http-desync-attacks-request-smuggling-reborn//portswigger.net/web-security/request-smuggling
|