Weak Randomness

An attacker samples a few reset tokens, recovers the generator state behind Math.random(), and predicts the token that takes over a real account, then you ship the crypto.randomBytes fix.

What Is Weak Randomness?

Weak randomness is using a non-cryptographic pseudo-random number generator (PRNG) to mint a security-sensitive value. The output looks indistinguishable from random in a histogram, that is what 'statistically uniform' means, but the PRNG's internal state is small enough that an attacker who observes a few consecutive outputs can recover the state and predict every output that comes after. Math.random() in V8 (the engine behind Node.js and Chrome) implements xorshift128+: 128 bits of state, a deterministic transition function, reconstructable from four observed outputs in milliseconds with off-the-shelf solvers. This exercise puts you on both sides. As Bob, a financially motivated attacker, you request resets on a throwaway account you control, collect the tokens the app mails you, and feed them to a state solver that prints the exact token the app will issue next. You trigger a reset on a real customer's savings account and redeem the predicted token to take it over, without ever reading the victim's email. As Alice, the application security engineer who owns account recovery, you trace a takeover in which the reset email was never opened, open the handler, find Math.random().toString(36) , and ship the fix with a click: crypto.randomBytes(32).toString('hex') . Re-running the exact attack against the patched endpoint now fails. The exercise closes with quiz questions on why statistical uniformity is not unpredictability, why adding more Math.random outputs or hashing them does not help, and where else in the codebase the same bug shape lives.

What You'll Learn in Weak Randomness

Weak Randomness — Training Steps

  1. Size up the target

    Bob makes his living getting into other people's accounts and taking the money inside. Today his target is Nestward, a savings app where a single account can hold real balances. He starts on the password-reset page, the front door he plans to walk through, to see how recovery works before he touches it.

  2. How recovery works

    One detail on that page is the whole reason Bob is interested.

  3. Request a reset for himself

    Bob starts with codes he is allowed to see. He owns the throwaway account bob.reeve@proton.me, so he requests a reset for it and opens the email Nestward sends back. The reset link in that email carries the code, in full.

  4. Collect a second code

    One code is not enough to see a pattern, so Bob requests another reset for the same account and reads the second email.

  5. One more code

    A third reset gives Bob the three codes his solver needs. He reads the last email and lines the codes up.

  6. Predict the next code

    Nestward mints these codes with a fast, non-cryptographic generator that has a small internal state. Bob feeds the three codes he read out of his inbox into a solver that reconstructs that state and runs it forward. The tool prints the exact code the app will put in the very next reset link it sends, for whichever account that reset is for.

  7. Trigger the victim's reset

    The predicted code is the next one the generator will issue, so Bob has to make it issue that code now. He requests a reset for a real customer, renata.voss@gmail.com. Nestward mints the next code, drops it into a link, and emails it to Renata, an inbox Bob cannot read.

  8. Redeem the predicted code

    Now Bob spends the code he predicted. He sends it straight to the reset endpoint with a new password, and because it matches the code Nestward just mailed to Renata, the server accepts it and sets his password on her account.

  9. The account is his

    The endpoint accepted the code and changed the password. Bob is now signed in to a savings account that is not his.

  10. Knowledge check

    You just watched an attacker predict a reset code he was never shown. Lock in why that was possible.