You have built a beautiful e-commerce platform. Customers love the smooth checkout. Your product images load instantly. But there is a silent killer hiding in your login form.
The lack of rate limiting on authentication attempts.
I run a security audit business focused on shopping websites. The number one vulnerability I find is not SQL injection or cross-site scripting. It is the ability to try passwords unlimited times. No blocks. No delays. No CAPTCHA.
This article explains why this matters, how attackers exploit it, and what you need to fix today.
The Problem in Plain English
Rate limiting means restricting how many requests a user or IP address can make in a specific time window.
Without rate limiting on your login endpoint, an attacker can send one thousand password guesses per second. Your server will happily process each one. After a few minutes, the attacker has tried one hundred thousand passwords. After an hour, millions.
Your customer`s account falls to a dictionary attack. Their stored credit card gets drained. Their saved addresses get changed to a drop location. And you get the chargeback nightmare.
How Attackers Exploit This
There are three common attack patterns against shopping sites with no login rate limiting.
Credential stuffing is the most dangerous. Attackers take username and password pairs leaked from other data breaches. They feed these into your login endpoint automatically. Many people reuse passwords across sites. The attacker now owns those accounts on your platform.
Brute force attacks are simpler but still effective. Attackers try common passwords like password123 or winter2024 against many usernames. Without rate limiting, they will eventually succeed on accounts with weak credentials.
Username enumeration is a privacy leak. When the login response differs slightly for valid versus invalid usernames, attackers can discover which email addresses have accounts on your site. This information sells to spammers and phishers.
Real Example From a Recent Audit
I tested a mid-sized fashion retailer last month. Their API login endpoint had zero restrictions. I wrote a simple twenty-line Python script. It tried one thousand passwords per minute from a single IP address.
Within eight minutes, I cracked three customer accounts. Two used their first name as the password. One used welcome123. All three had saved payment methods.
I reported this as critical severity. The fix was trivial to implement. But the client had been vulnerable for over two years.
Why Shopping Sites Are Prime Targets
Shopping sites hold three things attackers want.
Payment card data. Even tokenized cards can be used for fraudulent purchases if the account is compromised.
Shipping addresses. Attackers use these to build identity profiles or send unsolicited packages.
Order history. This reveals spending habits, income indicators, and product preferences used for targeted scams.
A compromised shopping account is a complete identity and payment package. No wonder attackers target these sites relentlessly.
How to Test Your Own Site
Run this simple manual test right now.
Open an incognito window and go to your login page. Enter a valid customer email address. Type a wrong password. Submit the form. Repeat this twenty times as fast as you can click.
Does your site ever stop you? Do you see a CAPTCHA? Does the login button become disabled temporarily? Does the page tell you to wait?
If nothing changes after twenty failed attempts, you are vulnerable.
For a more thorough test, use Burp Suite Intruder or write a short curl loop.
curl -X POST https://yoursite.com/login \
-d "email=customer@example.com&password=wrongguess"
Run that one hundred times. If you still get the same invalid credentials response without any lockout, you have confirmed the vulnerability.
The Technical Fixes That Work
Implementing rate limiting is not difficult. Here are the specific controls that protect your customers.
Per-IP rate limiting blocks an IP address after a certain number of failed attempts. Start with ten attempts per minute. After that, return HTTP 429 Too Many Requests. Do not even process the authentication attempt.
Per-account rate limiting protects a specific customer account from being targeted by many different IP addresses. Allow five failed attempts per hour on a single account. After the fifth failure, lock the account for fifteen minutes or require email verification to unlock.
Progressive delays increase the response time after each failure. After three failures, add a one-second delay. After five failures, add a five-second delay. This does not block the user but makes automated guessing impossibly slow.
CAPTCHA after N failures stops bots while letting legitimate users through. Use reCAPTCHA v3 which runs invisibly in the background. Most real users never see it, but automated scripts get blocked.
Web Application Firewall rules can provide a stopgap if you cannot modify application code. Configure your WAF to block IPs that exceed a threshold of login requests per minute.
Common Bypasses and How to Prevent Them
Attackers will try to circumvent your rate limiting. You must protect against these bypass methods as well.
IP rotation uses a botnet of thousands of residential proxies. Each IP makes only a few attempts. Per-IP limits alone fail against this. You need per-account rate limiting to stop distributed attacks.
Parameter pollution appends debug=true or similar parameters to the request. Some applications apply rate limits only to the clean URL but not the parameterized version. Normalize all request parameters before applying rate limits.
Different endpoints sometimes have separate rate limits. Attackers may target the API login endpoint while you protected only the web login. Apply consistent rate limiting across all authentication endpoints including login, password reset, and API authentication.
Header spoofing sends X-Forwarded-For headers to fake IP addresses. If your rate limiting trusts this header without validation, attackers can bypass it. Extract the real client IP from the lowest trusted layer, typically the connection source address.
Writing This Up in Your Security Report
When you find missing rate limiting on a client site, here is how to document it professionally.
Title: Missing Rate Limiting on Login Endpoint
Severity: High
Endpoint: POST /api/v1/login
Description: The application accepts an unlimited number of failed authentication attempts to the same user account from the same IP address. No CAPTCHA, delay, or account lockout mechanism is present.
Proof of Concept: One hundred consecutive login requests with incorrect passwords were sent over thirty seconds. Each request returned HTTP 200 with a generic Invalid credentials message. The account remained accessible for correct password entry throughout the test.
Impact: An attacker can perform automated brute force or credential stuffing attacks leading to account takeover. Compromised accounts can be used for fraudulent purchases, gift card draining, and personal data theft.
Remediation: Implement per-IP rate limiting of ten attempts per minute returning HTTP 429 after the limit. Implement per-account rate limiting of five failed attempts per hour with a fifteen minute temporary lockout. Add CAPTCHA after three consecutive failures.
References: OWASP ASVS V2.1.2, CWE-307
The Business Case for Fixing This
Your development team might say this is low priority. Here is what to tell them.
One account takeover leads to an average loss of two hundred fifty dollars in fraudulent transactions plus fifty dollars in chargeback fees. If you have one hundred thousand customer accounts and a one percent annual takeover rate, that is two hundred fifty thousand dollars in direct losses.
Payment card networks increase fees for merchants with high fraud rates. Your compliance auditor will flag missing rate limiting during PCI DSS assessment. Insurance providers may deny breach claims if basic controls like rate limiting were missing.
The fix takes a competent developer four hours to implement and test. The cost of not fixing it is orders of magnitude higher.

Top comments (0)