您好,登錄后才能下訂單哦!
本篇文章給大家分享的是有關(guān)如何分析并滲透WebSocket和Socket.io,小編覺得挺實用的,因此分享給大家學(xué)習(xí),希望大家閱讀完這篇文章后可以有所收獲,話不多說,跟著小編一起來看看吧。
WebSocket是一種允許瀏覽器和服務(wù)器建立單個TCP連接然后進(jìn)行全雙工異步通信的技術(shù)。由于它允許實時更新,而瀏覽器也無需向后臺發(fā)送數(shù)百個新的HTTP polling請求,所以對于web程序來說,WebSocket非常流行。這對于測試者來說是不好的,因為對WebSocket工具的支持不像HTTP那樣普遍,有時候會更加復(fù)雜。
除了BurpSuite之外,還有一些其他工具可用于處理WebSocket。不過經(jīng)過測試,它們都不怎么理想。
Zed Attack Proxy (ZAP)
Pappy Proxy
Man-in-the-Middle Proxy (mitmproxy)
WebSocket/Socket.io (WSSiP)
在這里主要會講socket.io,它是一個很流行的JavaScript WebSockets庫。在GitHub上它有多流行呢?---已經(jīng)有超過41.4的star了。
在NPM上,它在WebSocket中排行第二和第三。
另外,OWASP Juice-Shop這樣非常棒的項目也使用了socket.io庫,所以本篇文章中將使用websocket.io進(jìn)行演示。
https://github.com/bkimminich/juice-shop/search?utf8=%E2%9C%93&q=socket.io&type=
在本文中,我們假設(shè)你已經(jīng)熟悉使用BurpSuite測試Web應(yīng)用程序,所涵蓋的所有內(nèi)容都可以在其社區(qū)版本中完成。不用多說,現(xiàn)在開始吧。
如果我們在瀏覽器中訪問Juice-Shop,則可以在后臺快速查看WebSocket流量。你也可以在BurpSuite中通過Proxy-> WebSockets歷史記錄找到。
由于協(xié)議的無狀態(tài)特性,HTTP需要始終發(fā)送請求/響應(yīng)對,而WebSocket是一種有狀態(tài)協(xié)議。這意味著你可以從服務(wù)器獲得任意數(shù)量的傳出“請求”和任意數(shù)量的傳入“響應(yīng)”。由于底層連接是保持打開的TCP,因此客戶端和服務(wù)器可以隨時發(fā)送消息而無需等待對方。這就是為什么WebSocket歷史記錄與你習(xí)慣查看的HTTP歷史記錄存在差異。
在此界面中,你可以看到發(fā)送和接收的單字節(jié)消息。但是,當(dāng)應(yīng)用程序執(zhí)行一些有趣的操作時,你就可以看到具有更大負(fù)載的消息。
BurpSuite具有測試WebSockets的能力,你可以實時進(jìn)行攔截和修改,但WebSocket沒有Repeater,Scanner或Intruder功能。默認(rèn)情況下,如果要在BurpSuite中啟用WebSocket攔截,你只需要打開主攔截就好了。
這樣一來,你就可以通過與HTTP相同的方式獲取所截獲的WebSocket消息。同時也可以在攔截窗口中編輯它們。
在WebSockets歷史記錄選項卡中可以查看已編輯的消息。
一個非常奇怪的點(diǎn)是,有時在HTTP歷史記錄中也能看到類似Websocket歷史記錄中的消息,回想一下,這些比較有趣的WebSocket消息需要解決記分板相關(guān)問題,下圖顯示了來自服務(wù)器的相同響應(yīng),但這次是在HTTP歷史記錄中。由此可以看出socket.io能夠通過WebSocket或HTTP發(fā)送消息。
在所觀察的請求中,傳遞的參數(shù)值有些為“websockets”,而有些則是“polling”。那么據(jù)推測,可能為了防止WebSockets在應(yīng)用程序中不受支持或被阻止,才允許使用HTTP。
socket.io文檔中解釋了“polling”和“websockets”如何作為兩個默認(rèn)傳輸選項。它還介紹了如何通過將WebSockets指定為唯一傳輸方式來禁用polling。我認(rèn)為反過來也是如此,我可以指定polling作為唯一的傳輸機(jī)制。
https://socket.io/docs/client-api/#with-WebSocket-transport-only
通過搜索socket.io.js源代碼,我找到了以下內(nèi)容:
this.transports=n.transports||["polling","WebSocket"]
這行代碼會將一個名為transports的內(nèi)部變量設(shè)置為傳入的值,如果傳入的值為false/empty,則為默認(rèn)的[“polling”,“websocket”]。這很符合我們對polling和WebSocket的默認(rèn)傳輸?shù)耐茰y。現(xiàn)在通過Burp中的Proxy->Options下設(shè)置匹配并替換規(guī)則來更改這些默認(rèn)值,看看會發(fā)生什么。
成功了!添加規(guī)則后,刷新頁面(需要啟用Burp的內(nèi)置規(guī)則“Require non-cached response”或執(zhí)行強(qiáng)制刷新),數(shù)據(jù)不再通過WebSockets進(jìn)行通信。進(jìn)展不小,但是如果使用的應(yīng)用程序已經(jīng)提供了優(yōu)先于我們的新默認(rèn)值的傳輸選項呢?在這種情況下,我們可以修改匹配和替換規(guī)則。以下規(guī)則應(yīng)適用于socket.io庫的不同版本,并忽略應(yīng)用程序開發(fā)人員所指定的任何傳輸方式。
以下是要使用的字符串,務(wù)必將其設(shè)置為正則表達(dá)式匹配:
this\.transports=.*?\.transports\|\|\["polling","websocket"]this.transports=["polling"]
方法一只能用于于socket.io,可能會擴(kuò)展到其他客戶端庫。但是,以下方法應(yīng)該更加通用,因為它以WebSockets協(xié)議本身為目標(biāo)。
經(jīng)過分析,我發(fā)現(xiàn)WebSockets首先通過HTTP進(jìn)行通信,以便與服務(wù)器協(xié)商并“升級”為WebSocket。其中重要的部分是:
1)客戶端通過一些WebSocket特定header發(fā)送升級請求。
2)服務(wù)器響應(yīng)狀態(tài)碼為101 Switching Protocols,以及WebSocket header。
3)通信轉(zhuǎn)換到WebSocket,此特定會話不再使用HTTP。
WebSockets RFC文檔第4.1節(jié)提供了有關(guān)如何中斷此工作流的各種信息,以下是https://tools.ietf.org/html/rfc6455#section-4.1的摘錄,并附加了觀點(diǎn)。
1.如果從服務(wù)器收到的狀態(tài)碼不是101,則客戶端響應(yīng)HTTP[RFC2616]。特別情況下,收到401狀態(tài)碼時,客戶端可能會執(zhí)行身份驗證;服務(wù)器也可能會通過3xx狀態(tài)碼重定向客戶端(但客戶不需要遵循)等。否則按以下步驟進(jìn)行。
2.如果響應(yīng)缺少Upgrade header,或Upgrade header包含的值與“WebSocket”的ASCII不匹配,則客戶端必須關(guān)閉WebSocket連接。
3.如果響應(yīng)缺少Connection header,或Connection header包含的值與“WebSocket”的ASCII不匹配,則客戶端必須關(guān)閉WebSocket連接。
4.如果響應(yīng)缺少Sec-WebSocket-Accept header,或Sec-WebSocket-Accept header的值并非是由Sec-WebSocket-Key(作為字符串,未經(jīng)base64解碼)與字符串"258EAFA5-E914-47DA-95CA-C5AB0DC85B11"串聯(lián)起來的字符串(忽略任何前導(dǎo)和尾隨空格)的base64編碼后的SHA-1值的話,則客戶端必須關(guān)閉WebSocket連接。
5.如果響應(yīng)中包括Sec-WebSocket-Extensions header,并且header要求使用的擴(kuò)展并沒有出現(xiàn)在客戶端的握手消息中(服務(wù)器指示的擴(kuò)展并非是客戶端所請求的),則客戶端必須關(guān)閉WebSocket連接。(解析header以確定請求哪些擴(kuò)展的問題,將在第9.1節(jié)中討論)
考慮到這些“連接必定被關(guān)閉”的條件,我想出了以下一套替換規(guī)則,這些規(guī)則應(yīng)該包含了所有五個的失敗條件。
一旦使用這些規(guī)則,所有WebSocket升級請求都會失敗。由于socket.io默認(rèn)情況下無法使用HTTP,因此已經(jīng)達(dá)到所需的效果。其他庫的表現(xiàn)可能不同,并導(dǎo)致你正在測試的應(yīng)用程序出錯。但我們的工作就是讓軟件做一些不應(yīng)該做的事情!
原始響應(yīng)看起來像這樣,并且會使客戶端和服務(wù)器轉(zhuǎn)換到WebSocket進(jìn)行通信。
相反,客戶端從服務(wù)器收到此修改后的響應(yīng),會關(guān)閉WebSocket連接。
我在測試中遇到的一件事是,在將這些匹配和替換規(guī)則加入后,客戶端在重試WebSocket連接時非常持久,并在我的HTTP歷史記錄中引起了大量不必要的流量。如果你正在處理socket.io庫,則最簡單的方法是使用上面的方法1。如果你有不同的庫或其他情況,則可能需要添加更多規(guī)則來使客戶端服務(wù)器不支持WebSocket。
由于我們強(qiáng)制通過HTTP而非WebSockets進(jìn)行通信,所以現(xiàn)在可以添加自定義匹配并替換將應(yīng)用于已經(jīng)通過WebSockets流量的規(guī)則!接下來,可以使用Repeater,Intruder和Scanner等工具,這些更改將特定于socket.io庫。不過現(xiàn)在還有兩個問題:
1.每個請求都有一個會話號,任何無效請求都將導(dǎo)致服務(wù)器終止該會話
2.每個請求的主體都有一個計算字段,表示消息的長度。如果這不正確,服務(wù)器會將其視為無效請求并終止會話。
以下是應(yīng)用程序中使用的幾個示例URL。
/socket.io/?EIO=3&transport=polling&t=MJJR2dr/socket.io/?EIO=3&transport=polling&t=MJJZbUa&sid=iUTykeQQumxFJgEJAABL
URL中的“sid”參數(shù)表示到服務(wù)器的單個連接流。如果發(fā)送了無效消息(在嘗試破解時很常見),那么服務(wù)器將關(guān)閉整個會話,之后必須重新開始新會話。
給定請求的主體中含有一個字段,其中存放有效載荷的字節(jié)數(shù)。這類似于“Content-Length”HTTP header,只不過該字段的值近針對socket.io。例如,如果你要發(fā)送的有效載荷是“hello”,那么,相應(yīng)的主體將是“5:hello”,Content-Length頭部的值是7。其中,5表示字符串“hello”中的字母數(shù)量,而7則表示字符串“hello”中的字母數(shù)量以及socket.io添加到主體內(nèi)的字符串“5:”中的字母數(shù)量之和。與往常一樣,Burp將替我們更新Content-Length頭部,因此,這件事情我們無需擔(dān)心。但是,我還沒有找到能夠自動計算和包含有效載荷長度的好方法。更讓人頭疼的是,我發(fā)現(xiàn)socket.io竟然會在同一個HTTP請求中發(fā)送多條消息。由于每個消息都是一個封裝后的WebSocket有效載荷,并且每個消息都有自己的長度,因此,最終看起來就像這樣:“5:hello,4:john,3:doe”(實際的語法可能有所不同,這里只是便于演示)。計算長度時一旦出錯,服務(wù)器就會將其作為無效消息拒絕,這樣,我們就要重新開始了。
這是body的示例。這是Juice-Shop應(yīng)用程序中的響應(yīng),請求的格式相同。注意,這里的“215”表示“:”之后的有效載荷的長度。
215:42[“challenge solved”,{“key”:”zeroStarsChallenge”,”name”:”Zero Stars”,”challenge”:”Zero Stars (Give a devastating zero-star feedback to the store.)”,”flag”:”e958569c4a12e3b97f38bd05cac3f0e5a1b17142″,”hidden”:false}]
使用Burp宏能解決第一個問題?;旧希看蜝urp在服務(wù)器拒絕消息時匹配,宏將自動建立新會話并用有效的“sid”更新原始請求。通過轉(zhuǎn)到options->Sessions->Macros->Add來創(chuàng)建新宏。
建立新會話的URL只需省略“sid”參數(shù)。例如:
/socket.io/?EIO=3&transport=polling&t=MJJJ4Ku
服務(wù)器響應(yīng)包含一個全新的“sid”值以供使用。
接下來,單擊“Configure item”按鈕,并將參數(shù)名稱命名為“sid”。然后,選擇“Extract from regex group”選項,并使用如下所示的正則表達(dá)式。
"sid"\:"(.*?)"
這時,配置窗口應(yīng)如下所示:
現(xiàn)在有了一個宏,我們需要一種方法來觸發(fā)它。這就是Burp會話處理規(guī)則的用武之地。通過
Project options->Sessions->Session Handling Rules->Add
為“Check session is valid”創(chuàng)建新的規(guī)則動作:
配置新規(guī)則操作如下:
按如下方式配blackhillsinfosec置新規(guī)則操作:最后,在完成新規(guī)則操作后,還需修改規(guī)則的范圍。你可以在此處決定要應(yīng)用此規(guī)則的位置。建議至少將它用于Repeater,這樣就可以手動重復(fù)請求。
以下是我配置范圍規(guī)則的方法。你可以更加具體地了解自己所需范圍,但下面的選項應(yīng)該適用于大多數(shù)情況。
這是在沒有會話處理規(guī)則的情況下發(fā)出的請求:
這里是在會話處理規(guī)則生效后發(fā)出的相同請求:
以上就是如何分析并滲透WebSocket和Socket.io,小編相信有部分知識點(diǎn)可能是我們?nèi)粘9ぷ鲿姷交蛴玫降摹OM隳芡ㄟ^這篇文章學(xué)到更多知識。更多詳情敬請關(guān)注億速云行業(yè)資訊頻道。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。
億速云公眾號
手機(jī)網(wǎng)站二維碼
Copyright ? Yisu Cloud Ltd. All Rights Reserved. 2018 版權(quán)所有
廣州億速云計算有限公司粵ICP備17096448號-1 粵公網(wǎng)安備 44010402001142號增值電信業(yè)務(wù)經(jīng)營許可證編號:B1-20181529