Skip to content
العربية

Rate Limiting Flaws

No limit at all, a limit keyed on a header the client controls, and a limit that counts requests instead of guesses — why brute force keeps working.

Estimated time
20 min
Level
Intermediate
Your progress in this track0%

Before this lesson

A rate limit is what stops an attacker trying a login, an OTP or a reset code thousands of times until one works. When it is missing, keyed on something the attacker controls, or counts the wrong thing, brute force comes straight back — and a short code or a weak password is no protection at all.

What is the vulnerability?

  • No limit. A two-digit OTP with unlimited attempts falls in at most 100 tries.
  • Keyed on a client value. The limiter counts per X-Forwarded-For — a header the client sends — so rotating it gives a fresh bucket every request.
  • Counting the wrong unit. The limiter counts requests, but one request checks a whole list of codes, so a single batched request tries the entire space for one unit.

Why does it happen?

Limiting is bolted on after the feature works, so it is easy to key it on whatever is handy (a header) or to count whatever is easy (requests). The attacker only has to find the key or the unit the limiter got wrong.

How do you stop it?

Limit on something the client cannot forge — the account, or the real peer address the server observes, not a header. Count the real unit: attempts, not requests, and cap how many guesses a single request may carry. Add increasing delay and a temporary lock, and make the counter update atomic so concurrent requests cannot race it.

The three labs below walk this: brute an unlimited OTP, rotate a header to dodge the limit, and batch every guess into one request.

Labs

  • No attempt limit

    EasyBrowser lab

    Guess the code by trying every possibility.

  • A limit keyed on a client header

    MediumBrowser lab

    Bypass the limit by rotating the IP header and guess the code.

  • The limit counts requests

    HardBrowser lab

    Guess the code in one request, past the request limit.