If I have understood Cross-Site WebSocket Hijacking (CSWSH) attack correctly [1][2][3][4], the attack relies on two things (examples are from the first reference):
- the browser sending the cookies set by the victim domain (
www.some-trading-application.com
) over a WebSocket handshake request initiated from a JavaScript code running on the attacker domain (https://www.some-evil-attacker-application.com
) - no
Origin
header check being performed on the victim server side
The first happens due to the absence (by design) of cross-origin checks for WebSocket requests. I tested the hypothesis with a demo app that I developed. While the browser (Firefox 102.8.0esr (64-bit)) does permit cross-origin WebSocket requests, it does not send the auth_cookie
cookie alongwith. For my test setup, I did the following:
- Pointed both
victim.com
andattacker.com
to127.0.0.1
by modifying/etc/hosts
on a Ubuntu system - Victim web app (which includes the WebSocket server, too) runs on
victim.com:5000
, and sets anauth_cookie
with the most relaxed restrictions (HttpOnly=False
,Secure=False
,SameSite=None
,Path=/
) - Attacker webpage runs on
attacker.com:10000
, and initiates a WebSocket handshake tovictim.com:5000/logincheck
, the vulnerable WebSocket endpoint. I made sure that theauth_cookie
is set in the browser byvictim.com
before the WebSocket call is made fromattacker.com
.
Unfortunately, I could not see the auth_cookie
being sent either from developer tools in the browser, or Burp proxy. I repeated the test with other Firefox and Chrome versions as well, but had the same result.
Does CSWSH even work on modern browsers?
References
- https://christian-schneider.net/CrossSiteWebSocketHijacking.html
- https://infosecwriteups.com/cross-site-websocket-hijacking-cswsh-ce2a6b0747fc
- https://snyk.io/blog/gitpod-remote-code-execution-vulnerability-websockets
- https://github.com/carlospolop/hacktricks/blob/master/pentesting-web/cross-site-websocket-hijacking-cswsh.md
SameSite=None
(which requires use ofSecure
attribute which then means to use TLS, i.e. HTTPS/WSS)SameSite=None
. See my post above.Secure=False
suggests not and is apart from that not a valid cookie attribute (there is onlySecure
, nothing with true or false). To cite from what I linked to: "Note: A Secure cookie is only sent to the server with an encrypted request over the HTTPS protocol. Note that insecure sites (http:) can't set cookies with the Secure directive, and therefore can't use SameSite=None."Secure=False
wasn't probably the best way to indicate that the cookie is not secure, and therefore can be sent over HTTP, which is what I used throughout the test.