Back to all questions

How Can You Protect Against a Credential-Stuffing Attack?

Rostyslav Pidgornyi
Cybersecurity
December 22, 2024

To protect against a credential-stuffing attack, you need to implement multi-factor authentication (MFA), use rate limiting on login attempts, monitor for unusual login patterns, and secure passwords with encryption. 

Credential stuffing relies on stolen credentials, so tools like password managers, breach monitoring services, and IP blocking are also critical for prevention.

Here's what I’ve done and what I’d recommend if you’re in charge of securing accounts:

1. Implement Multi-Factor Authentication (MFA)

Relying solely on usernames and passwords isn’t enough. MFA adds an extra layer of security, requiring users to verify their identity through a second factor like a one-time code, biometric data, or an authenticator app.

I use tools like Google Authenticator or Authy for generating codes. For higher security needs, integrating biometric authentication such as fingerprint scanning or facial recognition is effective. Most authentication systems support MFA integration via APIs, which simplifies implementation.

{{cool-component}}

2. Apply Rate Limiting on Login Attempts

Credential stuffing depends on high-speed automated login attempts. To prevent this, I enforce rate limiting on login endpoints, restricting the number of requests allowed within a given timeframe.

I configure my servers with NGINX to limit login attempts per IP address and use AWS WAF for more granular controls. For example:

limit_req_zone $binary_remote_addr zone=login_zone:10m rate=5r/m;

server {
    location /login {
        limit_req zone=login_zone burst=10 nodelay;
        proxy_pass http://backend;
    }
}

Rate limiting makes it impractical for attackers to execute credential stuffing at scale.

3. Monitor and Analyze Login Patterns

Unusual login behavior often signals credential-stuffing attempts. I monitor login trends using tools like Splunk and the ELK Stack, which help identify anomalies such as multiple failed logins from the same IP or logins from unexpected locations.

I ensure that all login attempts, both successful and failed, are logged with details like timestamps, IP addresses, and device information. Alerts are set up to notify me of suspicious patterns, enabling a quick response to potential threats.

4. Strengthen Password Security

Passwords are the primary target in credential-stuffing attacks, so I ensure they are both strong and securely stored.

  • Encourage Strong Passwords: Password policies require a minimum of 12 characters with a mix of letters, numbers, and symbols. I use libraries like zxcvbn to provide real-time feedback to users during password creation.

  • Secure Storage: Passwords are hashed with algorithms like bcrypt, paired with unique salts to protect against rainbow table attacks. For example:

import bcrypt
password = b"securepassword"
salt = bcrypt.gensalt()
hashed = bcrypt.hashpw(password, salt)

5. Utilize Credential-Stuffing Detection Tools

I integrate tools designed to detect and block credential-stuffing attempts. Cloudflare and Okta offer bot mitigation and login behavior analysis, while services like Have I Been Pwned monitor for breaches and flag compromised credentials.

These tools often come with APIs, which I use to incorporate their functionalities seamlessly into existing systems. For instance:

import requests

def check_breach(email):
    response = requests.get(f"https://haveibeenpwned.com/api/v3/breachedaccount/{email}")
    if response.status_code == 200:
        notify_user(email)

6. Implement IP Blocking and Geo-Restrictions

Targeted IP blocking helps reduce the risk without affecting legitimate users. Here's how I approach it:

  • Why Regional Blocking?
    Blocking entire countries can be too restrictive. Instead, focusing on specific regions or even towns known for malicious activity strikes a better balance.
  • My Method: I use geo-IP databases to identify and block IP addresses from regions with a high incidence of attacks. Services like AbuseIPDB provide updated lists that I integrate into my firewall rules.
  • Implementation Steps:
    1. Identify Malicious IPs: Use AbuseIPDB to get a list of suspicious IP addresses.
    2. Update Firewall Rules: Automate the process of adding these IPs to my server’s blocklist.
    3. Dynamic Filtering: Adjust restrictions based on real-time threat intelligence, allowing flexibility as new threats emerge.
  • Example Configuration with AWS WAF:

{
	"Name": "BlockMaliciousRegions",
	"Priority": 1,
	"Action": { "Block": {} },
	"Statement": {
    	"GeoMatchStatement": {
        	"CountryCodes": ["US", "CN"],
        	"ForwardedIPConfig": {
            	"HeaderName": "X-Forwarded-For",
            	"FallbackBehavior": "MATCH"
        	}
    	}
	}
}

7. Educate Users About Account Security

User education is as important as technical defenses. I provide guides and reminders about account security, emphasizing the use of password managers and the dangers of password reuse. During password creation, I implement in-app prompts to encourage stronger passwords.

For example:


“Using the same password across multiple accounts increases your risk of being hacked. Use a password manager to generate and store unique passwords securely.”

8. Employ CAPTCHA to Deter Bots

Automated credential-stuffing tools struggle with CAPTCHA challenges. I use Google’s reCAPTCHA v3, which assesses user interactions to differentiate between humans and bots without introducing excessive friction.

<form action="/login" method="POST">
    <!-- Login fields -->
    <div class="g-recaptcha" data-sitekey="your_site_key"></div>
    <button type="submit">Login</button>
</form>
<script src="https://www.google.com/recaptcha/api.js"></script>

CAPTCHA is selectively applied to suspicious activities, such as repeated failed logins.

9. Utilize Device Fingerprinting

Device fingerprinting helps identify and flag unusual devices attempting to log in. Using tools like FingerprintJS, I collect non-intrusive data points such as browser type, screen resolution, and installed plugins to create a unique identifier for each device.

If an unfamiliar device attempts to access an account, additional verification steps like MFA are triggered. This provides another layer of security against credential-stuffing attacks.

11. Implement Account Lockout Policies

Account lockout policies serve as an additional deterrent against repeated unauthorized login attempts.

By limiting the number of failed login attempts, I can prevent attackers from continuously trying different password combinations.

  • My Policy: I set a threshold of five failed login attempts within 15 minutes. Once exceeded, the account is temporarily locked for 30 minutes.
  • Implementation Steps:
    1. Track Failed Attempts: Monitor and count failed login attempts per account.
    2. Trigger Lockout: Automatically lock the account after the threshold is reached.
    3. Notify Users: Send an email alerting users of the lockout and advising them to secure their accounts.
  • Example Notification:
    “Your account has been locked due to multiple failed login attempts. If this wasn’t you, please reset your password immediately.”
  • Impact on Security:
    This policy not only thwarts attackers but also informs users to take proactive steps if their account is being targeted, enhancing overall account security.