If they can guess infinitely, they will eventually guess correctly.
Rate Limiting is the process of restricting how many requests a user or IP address can make in a given timeframe. When rate limiting is absent on Authentication endpoints (like `/login` or `/forgot-password`), attackers can automate scripts to submit thousands of guesses per second, enabling Brute Force and Credential Stuffing attacks.
Because people reuse passwords, hackers buy massive databases of emails and passwords leaked from other breaches (like Yahoo or LinkedIn). They then write a script to "stuff" those credentials into your login page. If you don't rate limit, they will test 10,000 accounts a minute until they find ones that work.
# VULNERABLE: No Rate Limiting
@app.route("/api/login", methods=["POST"])
def login():
# An attacker can hit this endpoint 500 times a second.
user = authenticate(request.json)
return user
# SECURE: Strict Rate Limiting on Auth
from flask_limiter import Limiter
# Limit to 5 requests per minute, per IP address.
@app.route("/api/login", methods=["POST"])
@limiter.limit("5 per minute")
def login():
user = authenticate(request.json)
return user
A streaming service notices that thousands of legitimate user accounts are being sold on the dark web. They investigate and realize their API `/v1/auth` endpoint has no rate limiting. A hacker network had been quietly testing millions of leaked username/password combinations at a rate of 2,000 requests per second. The server happily responded "Invalid Password" or "Success", allowing the hackers to filter out the valid accounts and sell them.
To defend against a distributed botnet credential stuffing attack, you decide to implement a rule: "Lock the user account for 30 minutes after 5 failed login attempts." What is a major downside to this approach?