0-click-ATO — Account Takeover via OTP Brute Force + Email Case-Sensitivity Bypass
Exploit a case-sensitive OTP tracking system to brute-force the admin password reset
Aprende a encontrar este bug
Este bug pagó $600 en YesWeHack.
Crea tu cuenta y practica bugs reales que se pagaron. Descarga el entorno, encuéntralo y aprende la técnica exacta — tu camino a tu primer bounty.
hunters entrenando
labs de reportes reales
completaciones
en bounties practicados
Acceso a todos los labs · sin permanencia · cancela cuando quieras
Hunters que lo han resuelto· 8
Objetivos
Logro que recibirás
Cuando resuelvas este lab desbloqueas este logro compartible
0-click-ATO — Account Takeover via OTP Brute Force + Email Case-Sensitivity Bypass
Writeups de la comunidad
Deployment
# Using autodeploy
bash autodeploy.sh
# Or manually
docker compose up --build -d
Access the lab at: http://localhost:1337
Attack Chain
1. Login as user@securecam.io
2. Use "Invite to Camera Group" to discover admin@securecam.io
3. Analyze password reset flow:
- POST /api/auth/forgot-password → generates 4-digit OTP
- POST /api/auth/reset-password → email + new_password + otp
- 4 failed attempts → email blocked
4. Discover: OTP tracking is case-sensitive, password reset is case-insensitive
5. Write Python3 exploit:
- Generate email case variants (admin@, Admin@, aDmin@, etc.)
- For each variant: request OTP → try 4 codes → move to next variant
6. Run exploit → password reset → login as admin → flag
Vulnerability Details
The server stores OTP attempts using the exact email string as the key (case-sensitive).
After 4 failed attempts for a specific email string, it is blocked.
However, the actual user lookup for password reset uses LOWER(email) = LOWER(?),
meaning all case variants of the email update the same user's password.
This means each case variant of the admin email (e.g., Admin@securecam.io, aDmIn@securecam.io)
gets its own 4 fresh OTP attempts, effectively bypassing the rate limit.
With 16 alphabetic characters in admin@securecam.io, there are 2^16 = 65,536 possible case variants,
each with 4 attempts = 262,144 total attempts, far exceeding the 10,000 possible 4-digit OTP codes.
Remediation
- Normalize email before OTP tracking: Convert to lowercase before storing in the OTP rate-limit store
- Global rate limiting: Implement rate limiting based on the normalized email, not the raw input
- Longer OTP codes: Use 6+ digit codes to increase the keyspace
- Account lockout: Lock the actual account after N failed reset attempts (not just the email variant)
- Time-based OTP expiration: Expire OTPs after a short window (e.g., 5 minutes)
Interactive Writeup
Access the step-by-step interactive writeup at: http://localhost:1337/writeup
Attribution
Bug Bounty Labs by @_.gorkaaa.b