WebSockFish

Published: April 2, 2025

Description

The chess bot relays evaluation updates over a WebSocket. Instead of playing perfectly, hijack the `sendMessage` helper in the browser console and feed the server ridiculous evaluation scores.

Open the site, inspect the page source, and note the embedded WebSocket client and `sendMessage` helper.

Use your browser's dev tools console to call `sendMessage(...)` directly. No moves required.

Solution

  1. Step 1Trigger the mate branch
    Sending `sendMessage("mate 1")` updates the chat to "drown in 1 moves," proving the server accepts arbitrary client messages.
    Learn more

    WebSockets provide full-duplex communication channels over a single TCP connection. Unlike HTTP where the client always initiates requests, WebSocket connections allow both the client and server to send messages at any time after the initial handshake. They are commonly used in real-time applications: chat systems, live feeds, multiplayer games, and collaborative editing tools.

    The browser's DevTools WebSocket inspector (in the Network tab, filter for "WS") shows all messages exchanged on open WebSocket connections. You can see both sent (green) and received (red) frames in real time. When a function like sendMessage is assigned to a JavaScript global, calling it from the browser console is identical to the application calling it internally - the server has no way to distinguish the source.

    This is a fundamental principle of client-side trust issues: any JavaScript variable, function, or WebSocket connection accessible from the browser console can be manipulated by the user. Security-critical logic (access control, game state, score validation) must always be enforced server-side. Relying on client-side checks is equivalent to asking users to validate their own inputs - a guarantee that cannot be made.

  2. Step 2Force a wild eval
    The flag is awarded when the evaluation dips beyond -50,000. Send any value lower than that to convince the bot you're crushing it.
    sendMessage("eval -1000000000")
    Learn more

    Chess engines express position evaluations in centipawns - hundredths of a pawn value. An evaluation of 0 is a dead-level position; +100 means white is ahead by roughly one pawn; +300 means white is ahead by a minor piece. Evaluations beyond ±500 typically indicate a decisive advantage, and beyond ±1000 (10 pawns equivalent) suggest a near-certain win. Values like -1,000,000,000 are physically impossible in real chess analysis.

    The server's failure to validate that the evaluation falls within a reasonable range is a classic input validation vulnerability. Even for data that "should" only come from a trusted source (like a chess engine), the server should verify constraints before acting on them. If the evaluation comes from the client over WebSocket, any user can forge it - as this challenge demonstrates.

    This vulnerability pattern appears in many real-world gaming cheats and fraud schemes: forging score submissions to leaderboard APIs, sending impossible game state updates to multiplayer servers, or manipulating auction bids or financial calculations sent client-to-server. Server-side validation is the only reliable defense - client-side validation is UX polish, not security.

  3. Step 3Grab the response
    The chat window immediately prints the picoCTF flag once the server sees your impossible evaluation score.
    Learn more

    The speed of this exploit - a single WebSocket message yields the flag instantly - illustrates how quickly server-side trust of client data can be exploited. There is no need to play a single chess move, bypass authentication, or understand the chess engine. The attack requires only the ability to read JavaScript source (which is always possible in a browser) and call a function from the console.

    In a responsible disclosure or bug bounty context, this type of finding (client-side logic bypass via WebSocket manipulation) would be reported as a business logic vulnerability. Depending on the application, it could allow cheating on leaderboards, obtaining items without proper gameplay, or bypassing paywalls. CVSS scoring for such findings considers the impact on confidentiality, integrity, and availability - forging game states typically rates medium to high on integrity impact.

    For developers building WebSocket applications: treat every WebSocket message from a client as untrusted input, validate all fields against expected types and ranges, maintain authoritative state server-side (never trust the client's reported state), and use rate limiting to prevent abuse. The same security principles that apply to REST API endpoints apply equally to WebSocket message handlers.

Flag

picoCTF{c1i3nt_s1d3_w3b_s0ck3t5_e5e7...}

Because the logic runs entirely in the client, you don't need chess knowledge; just forge the WebSocket message.

Want more picoCTF 2025 writeups?

Useful tools for Web Exploitation

Related reading

What to try next