Event: OliCyber Category: Web Vulnerability: TOCTOU in SQLite-backed session management
The Vulnerable Logic
The app is a key-escalation shop: buy red_key → green_key → blue_key → flag. Each purchase costs 10 coins. You start with 20. You need 40. The math is brutal by design.
The /buy endpoint looks safe:
Sequential. Logical. Fundamentally broken under concurrency.
Why It Breaks
The session store is SQLite via connect-sqlite3. SQLite handles concurrency with file-level locking, but express-session defaults to resave: false. The critical gap: session reads and writes are not atomic.
When two requests hit simultaneously:
- Both read
balance: 20 - Both pass the check
- Both deduct 10
- Both write back — result is
balance: 10instead ofbalance: 0
You spent 10 coins, got two purchases worth of keys.
The Exploit Architecture
The Healer Swarm
40 threads hammering GET /:
Why? The initialization middleware:
Every time a session is reloaded from SQLite in a race window, if the read is corrupted or the session row is locked, the middleware may trigger re-initialization — resetting balance back to 20. The healers keep session state in constant flux, maximizing collision probability.
The Purchase Loop
The exploit treats "Not enough balance" as a transient lock collision, not a hard failure. When balance runs out, pause — let the healers corrupt the session back into a usable state — retry.
The Chain
The economics don't matter when the ledger is lying.
The Fix
Minimum viable patch — still not truly atomic:
Real fix: database-level transaction wrapping the entire check-deduct-respond flow, or move balance to Redis with atomic DECR operations.
Takeaway
SQLite was never meant for high-concurrency session storage. express-session's read-modify-write pattern assumes the store is atomic or single-threaded. Violate that assumption with 40 concurrent threads and the abstraction leaks catastrophically.
The "safe" sequential code becomes theater. The real logic is in the timing — the microseconds between SQLite's BEGIN and COMMIT.
Exploit source: github.com/0xAdham/olicyber
0xAdham
