Tuesday, October 6, 2026

WS_RaceCondition_PoC for demonstrating race conditions over WebSockets

WS_RaceCondition_PoC for demonstrating race conditions over WebSockets

A Java-based proof of concept showing how parallel WebSocket connections can trigger server-side race conditions, intended for authorized security research and developer education.

Toolredrays-io/WS_RaceCondition_PoC — Java proof of concept demonstrating race conditions in WebSocket servers
CategoryWeb application security / concurrency vulnerability demonstration
Primary UseReproducing server-side race conditions by firing parallel WebSocket clients against a deliberately vulnerable test server in a lab
Safe UseEducational and documentary analysis for authorized professionals: run only against the bundled local test server (ws://127.0.0.1:8080) in your own lab environment
Telemetry NoteThe vulnerable handler prints the shared counter and echoes messages to console; defenders can detect this testing pattern via bursts of parallel WebSocket connections followed by near-simultaneous first-message processing on the server side

redrays-io/WS_RaceCondition_PoC is a small, deliberately narrow Java project from the redrays-io organization that answers a specific question many web developers get wrong: can race conditions occur over WebSockets? The repository, tagged with the topics poc, race-conditions, and vulnerability and sitting at roughly 54 stars, is not a scanner or an attack framework. It is a self-contained teaching lab — a vulnerable server, two contrasting client harnesses, and a README that walks through the theory before showing the crash. For professionals who teach secure coding, review WebSocket-backed APIs, or want a minimal reproduction case for a defensive briefing, it is a compact and useful artifact.

The README frames the problem class carefully before touching code. Race conditions, it explains, arise in multitasking programs when two or more threads or processes modify shared data or resources simultaneously without synchronization, producing outcomes that depend on which execution wins. The author points to standard references — the Wikipedia entry on the subject and James Kettle's talk "Smashing the State Machine: the True Potential of Web Race Conditions" — positioning the project as a follow-up question to Kettle's HTTP-centric research: does the same class of bug manifest when the transport is a persistent WebSocket rather than repeated HTTP requests.

The server side is where the deliberate flaw lives. The code is a WebSocket server built on the Java-WebSocket library that interacts with a PostgreSQL database. On startup it connects, checks whether an example table exists, creates it if missing, and seeds it with ten rows named RandomName0 through RandomName9. This setup matters because it gives the demo a concrete shared resource — a database query — that the vulnerable handler touches, rather than an abstract counter, making the race feel realistic to anyone who has audited connection-handling code.

The heart of the demonstration is the onMessage handler. A global static integer a is initialized to zero; when a message arrives, the handler checks whether a == 0, and only then executes getCountFromExampleTable(), a SQL count against the example table, before incrementing a and printing its value. The developer's mental model is that the guarded block runs exactly once for the lifetime of the server. The README is explicit that this assumption is what parallel connections violate: the check and the increment are not atomic, so concurrent messages can all observe a == 0 before any of them increments it.

The client harnesses are the experiment's two arms. WebSocketParallel_Success spins up a fixed thread pool of 100 clients using ExecutorService and Executors.newFixedThreadPool, each opening its own WebSocketClient connection to ws://127.0.0.1:8080 and immediately sending a greeting from its onOpen callback. WebSocketParallel_Failed takes the opposite approach: a single connection whose onOpen submits 285 sends through an executor, firing many messages over one socket in parallel from the client's perspective.

The naming encodes the result, and it is the most instructive part of the project. With one hundred parallel connections, the race triggers and the guarded block executes multiple times — the printed counter climbs past one, proving the "run once" invariant broke. With a single connection pushing 285 messages, nothing happens, because WebSockets guarantee sequential, ordered delivery of frames on a single connection. In other words, the transport serializes messages per socket, so a single-client flood cannot race the handler; the vulnerability requires concurrent connections. The README includes screenshots and a demo GIF (WS_RaceCondition_demo.gif) plus a link to an original demo video hosted on the author's site, so the outcome is documented visually for anyone who cannot run the lab.

Architecturally, the project is a clean three-tier illustration of a concurrency smell: a stateful server handler with a check-then-act pattern on shared mutable state, an external datastore as the side-effect sink, and an orchestration layer that varies concurrency along the one axis that matters — connection count versus message count per connection. There is no framework magic, no hidden dependency chain beyond Java-WebSocket and a PostgreSQL driver, which makes it easy to read top to bottom in a single sitting and to reason about exactly where synchronization should be added (synchronized, AtomicInteger.compareAndSet, or a database-level constraint depending on the invariant you actually need).

The README closes with a question about real-world relevance and answers it plainly: yes, a few critical race condition vulnerabilities have been found in cryptocurrency exchanges exposing WS API interfaces, which were reported and subsequently fixed by the affected exchanges. No exchanges are named and no details are given, which keeps the project firmly in the educational register — the claim serves as motivation, not as target intelligence. The author, who publishes under @vah_13 on Twitter and the redrays.io site, clearly intends the repo as companion material to that research background.

For defenders, the project's value is diagnostic rather than operational. It tells you precisely what a WebSocket race looks like from the server's point of view: a burst of near-simultaneous first messages across many fresh connections, all landing inside a check-then-act window on shared state. That pattern is what you look for when reviewing your own WebSocket handlers — global counters, unsynchronized caches, one-time initialization flags, or "first user wins" business logic applied over onMessage. If your server treats the first message of a session as special (token issuance, bonus grants, initialization), the WS_RaceCondition_PoC pattern is the canonical test shape to replicate against a staging copy.

In an authorized workflow — a lab, a CTF, an internal training session, or a code review walkthrough — the repository is most useful as a before-and-after exercise: run the parallel client against the vulnerable server, observe the invariant break, then patch the handler with proper synchronization and re-run to confirm the fix holds. Nothing in the repo automates discovery against third-party targets; it ships a vulnerable server of its own for you to attack locally, which is the right design for a teaching artifact and keeps it squarely on the safe side of the tooling spectrum.

Caveats worth noting: the repository carries no license file, so reuse of the code beyond personal experimentation is legally ambiguous, and the README is the extent of the documentation — there are no build instructions, CI, or tests beyond the two client entry points. The code itself is demonstration-grade, with console System.out.println logging and hard-coded connection parameters. None of that detracts from its purpose; it just means you should treat it as a readable artifact and a lab seed, not as a dependency or a production-quality harness. As a concise, honest answer to "can WebSockets race?" — with runnable proof and the exact preconditions spelled out — it does exactly what it claims.

Official project repository for redrays-io/WS_RaceCondition_PoC.
Download Tool

Educational analysis for authorized security professionals. Use only in controlled, authorized environments.

Share articleFacebookXLinkedIn

Continue exploring

Browse all articles →

0 comentários:

Post a Comment

Note: Only a member of this blog may post a comment.