Broken User Authentication

A money app signs users in with a 6-digit email code, and the verify endpoint never limits attempts. An attacker with only the victim's email brute-forces the code, takes over the account, and you ship a per-account attempt limit that returns 429.

What Is Broken User Authentication?

Broken user authentication (OWASP API2:2023, Broken Authentication) covers weaknesses in the mechanisms and workflows that establish who a caller is. A common shape is an authentication endpoint that checks a credential correctly but never defends the check against automation: no limit on attempts, no lockout, no rate limiting. When the credential is a short numeric code, that gap is decisive, because an attacker can walk the entire code space one request at a time. This exercise puts you on both sides. As Bob, an attacker holding only a customer's email address, you start a sign-in on Kelvo, a consumer money app that logs users in with a 6-digit code emailed to them, then probe the POST /v1/auth/otp/verify endpoint and watch it answer a wrong code with a bare 200 and nothing tracking your attempts. You run a script that submits every possible code until one is accepted, hundreds of thousands of requests with none refused, and the endpoint hands back a live session for the victim's account, no password and nothing forged. As Alice, the engineer who owns the sign-in service, you receive the monitoring alert, open the verify handler, and see it look up the account's code, compare it, and answer without ever counting how many times that account has guessed. You ship the durable fix: record every failed attempt in server-side state keyed to the account, refuse further tries with 429 once the limit is reached, consume a matched code on use, and lean on short expiry, so a 6-digit code becomes a real barrier again. The exercise closes with quiz questions on why a correct check is not a safe check, how brute force beats a large code space when attempts are unbounded, where the attempt counter must live, and why a small attempt limit defeats the attack regardless of code length.

What You'll Learn in Broken User Authentication

Broken User Authentication — Training Steps

  1. One code stands guard

    Kelvo is a consumer money app, and it signs people in with a 6-digit code emailed to their address, no password. Enter your email, Kelvo sends a code, you type it back, you are in. Bob does not have a code. What he has, from a breached mailing list, is one customer's email address: renata.voss@gmail.com. He opens the Kelvo sign-in page to see exactly what he is up against.

  2. Trigger the code

    Bob starts a sign-in for the account he is targeting. He types the victim's email and asks Kelvo to send the code. The code lands in Renata's inbox, not his, but Kelvo now shows him the screen that asks for it. That screen, and the request behind it, are what he studies next.

  3. Watch the request

    The code entry screen is in front of Bob now. He does not have Renata's real code, but before he tries to crack it he wants to see how the screen checks a code and where it sends it. He types a wrong code and submits, then watches the request his browser makes in the Network panel.

  4. The endpoint, in plain sight

    Bob's browser sent the code to Kelvo's API, and the Network panel captured the whole request. It hands him the one thing he needs to attack this without the screen: the exact endpoint that checks codes.

  5. The brute-force script

    With the endpoint in hand, Bob does not guess by hand. He opens the short script he will run against it: a loop that submits every possible code to Kelvo's verify endpoint until one comes back accepted.

  6. How the loop works

    The whole attack is a handful of lines. Walk through what each part does, and why nothing on the vulnerable server stops it.

  7. Walk every code

    Bob runs the script against Kelvo's verify endpoint. It fires the same request over and over, incrementing the code each time, and waits for one to come back accepted.

  8. A code that works

    The script ran unopposed and found a code that the server accepts.

  9. Use the code

    Bob takes the code his script found and sends it to the endpoint one more time by hand, to confirm the account is his and see what he now holds.

  10. A live session, from six digits

    The endpoint accepted the guessed code and handed back a real session.