Get a Pentest and security assessment of your IT network.

Cyber Security

Password Check Rate Limiting

TL;DR

Too many failed password attempts can be a denial-of-service (DoS) attack. This guide shows you how to limit the number of login tries from each IP address or user account to protect your system.

How to Avoid Password Check DoS Attacks

  1. Understand the Problem: A brute-force attack tries many passwords quickly. Without limits, this can overwhelm your server and lock out legitimate users.
  2. Choose a Limiting Method: You have two main options:
    • IP Address Based: Limit attempts per IP address. This is simpler but less accurate if multiple users share an IP (e.g., behind a NAT).
    • User Account Based: Limit attempts per username/email. More precise, but requires tracking user accounts.
  3. Implement Rate Limiting in Your Application Code: This is the most common approach.

    Most web frameworks have built-in rate limiting features or libraries you can use.

    • Python (Flask Example): Using a library like Flask-Limiter:
      from flask import Flask, request
      from flask_limiter import Limiter
      
      app = Flask(__name__)
      limiter = Limiter(app, key=request.remote_addr, default_limit="10/minute")
      
      @app.route('/login', methods=['POST'])
      @limiter.limit("5 per minute per user") # Limit to 5 attempts per minute per user.
      def login():
          # Your login logic here...
          return "Login successful!"
    • Node.js (Express Example): Using a library like express-rate-limit:
      const express = require('express');
      const rateLimit = require('express-rate-limit');
      
      const app = express();
      
      const limiter = rateLimit({
        windowMs: 60 * 1000, // 1 minute
        max: 5, // Limit each IP to 5 requests per windowMs
        message: 'Too many login attempts. Please try again later.'
      });
      
      app.post('/login', limiter, (req, res) => {
          // Your login logic here...
          res.send('Login successful!');
      });
  4. Implement Rate Limiting at the Web Server Level: Use tools like Nginx or Apache.
    • Nginx Example (using limit_req_zone and limit_conn_zone):
      http {
          ...
          limit_req_zone $binary_remote_addr zone=mylimit:10m rate=5r/m;
          server {
              location /login {
                  limit_req zone=mylimit burst=10 nodelay;
                  # Your login handling here
              }
          }
      }
  5. Store Attempt Data: If you’re implementing user-based rate limiting, store failed attempt timestamps in a database or cache (e.g., Redis).
    • Database Example: Create a table to track username and last attempt time.
    • Redis Example: Use Redis counters for each username.
  6. Lock Accounts After Too Many Failed Attempts: Temporarily disable accounts after exceeding the limit. This adds an extra layer of security.
    • Implement a lockout mechanism in your application code.
    • Consider using exponential backoff (increase the lockout duration with each failed attempt).
  7. Monitor Logs: Regularly check logs for suspicious activity, such as repeated failed login attempts from the same IP address.
  8. Use Strong Passwords and Multi-Factor Authentication: Rate limiting is a defense in depth. Encourage strong passwords and enable MFA whenever possible.
Related posts
Cyber Security

Zip Codes & PII: Are They Personal Data?

Cyber Security

Zero-Day Vulnerabilities: User Defence Guide

Cyber Security

Zero Knowledge Voting with Trusted Server

Cyber Security

ZeroNet: 51% Attack Risks & Mitigation