Negative balance achieved through TOCTOU attack.
ID | Time | Amount | Status | Account 1 After | Account 2 After |
---|---|---|---|---|---|
{{ op.id }} | {{ op.time.toLocaleTimeString() }} | ${{ op.amount.toFixed(2) }} | {{ op.status }} | ${{ op.account1After.toFixed(2) }} | ${{ op.account2After.toFixed(2) }} |
By performing {{ concurrentRequests }} concurrent transfers of ${{ transferAmount }} each while intentionally delaying operations by {{ operationDelay }}ms, we were able to:
This demo shows a classic Time-of-Check to Time-of-Use (TOCTOU) race condition in banking systems. The vulnerability occurs when funds are transferred between accounts without proper locking.
// UNSAFE - Vulnerable to TOCTOU async function transferVulnerable(amount) { // 1. Check balance (Time-of-Check) if (account1.balance >= amount) { // 2. WINDOW OF VULNERABILITY - Other threads can pass the check // 3. Simulate processing delay await delay(operationDelay); // 4. Transfer funds (Time-of-Use) account1.balance -= amount; account2.balance += amount; return true; } return false; }
// SAFE - Uses locking to prevent race conditions async function transferProtected(amount) { const release = await account1.lock.acquire(); try { if (account1.balance >= amount) { // No window of vulnerability account1.balance -= amount; account2.balance += amount; return true; } return false; } finally { release(); } }