mediumCWE-307A07:2021

No Rate Limit on Login

A login endpoint without rate limiting can be brute-forced thousands of times per second until a valid password is found.

How It Works

Without rate limiting, an attacker can script unlimited login attempts. A 4-digit PIN has only 10,000 combinations — crackable in seconds. Even long passwords from leaked credential lists can be tried en masse in a credential stuffing attack. Rate limiting makes this economically impractical.

Vulnerable Code
// BAD: no rate limiting on login — unlimited attempts allowed
export async function POST(req: Request) {
  const { email, password } = await req.json();
  const user = await validateCredentials(email, password);
  if (!user) return Response.json({ error: 'Invalid credentials' }, { status: 401 });
  return Response.json({ token: createToken(user) });
}
Secure Code
// GOOD: rate limit by IP and by account
import { rateLimit } from '@/lib/rate-limit';

export async function POST(req: Request) {
  await rateLimit(req, { max: 5, window: '15m', key: 'login' }); // 5 attempts per 15 min
  const { email, password } = await req.json();
  const user = await validateCredentials(email, password);
  if (!user) return Response.json({ error: 'Invalid credentials' }, { status: 401 });
  return Response.json({ token: createToken(user) });
}

Real-World Example

The 2022 Uber breach started with credential stuffing against a contractor's account. An attacker made repeated login attempts using credentials from a previous data breach until they found a match, then pivoted to MFA fatigue.

How to Prevent It

  • Rate limit login to 5-10 attempts per 15 minutes per IP address
  • Also rate limit per email address to prevent distributed attacks from multiple IPs
  • Implement exponential backoff after repeated failures (1s, 2s, 4s, 8s...)
  • Lock accounts temporarily after 10 consecutive failures and notify the user

Affected Technologies

Node.js

Data Hogo detects this vulnerability automatically.

Scan Your Repo Free

Related Vulnerabilities