Respuesta rápida
Rate limiting suele aplicarse mal: a veces solo en uno de varios endpoints equivalentes, a veces basado en headers spoofeables, a veces solo por IP cuando se acepta X-Forwarded-For. Bypassearlo permite brute force de OTPs, password guessing, enumeración masiva, y suele ser la pieza que falta para escalar findings de bajo impacto a critical.
Patrones de bypass
1. Header X-Forwarded-For spoofeable
Apps detrás de CDN/proxy confían en X-Forwarded-For para identificar IP del cliente. Si el rate limiter usa este header sin validar:
POST /login HTTP/1.1
Host: target.tld
X-Forwarded-For: 1.1.1.1
Cada request con un valor diferente "parece" IP distinta:
for i in $(seq 1 1000); do
curl -H "X-Forwarded-For: $((RANDOM%255)).$((RANDOM%255)).$((RANDOM%255)).$((RANDOM%255))" \
-d 'user=admin&pass=guess' https://target.tld/login
done
Headers comunes a probar:
X-Forwarded-For
X-Real-IP
X-Originating-IP
X-Remote-IP
X-Remote-Addr
X-Client-IP
X-Forwarded
Forwarded-For
True-Client-IP (Cloudflare/Akamai)
CF-Connecting-IP (Cloudflare)
Fastly-Client-IP
X-Cluster-Client-IP
Via
2. IP rotation real (sin headers)
Si el rate limit es por IP real:
- AWS Lambda desde tu propio script: cada invocation puede salir de IP distinta dependiendo del runtime. Free tier basta.
- Cloud functions (GCP, Vercel, Netlify) — tu propia función llamando al target.
- Tor circuits — nuevo circuit cada N requests.
- Lista de proxies públicos (legales, residenciales o datacenter pagados).
- Cloudfront IPs si la app está detrás de Cloudfront — bypass con
Host: target.tlddesde otra IP de Cloudfront.
3. Path casing y encoding
Algunos rate limiters indexan por path exacto:
/login (limited)
/Login (NOT limited)
/LOGIN
/log%69n (URL-encoded letter)
/login/
/login//
/login;a=1 (path parameters ignorados)
/login?x=1 (query string)
/login#a
/login%20 (trailing space)
Si el server normaliza el path antes de procesar pero el rate limiter no, bypass.
4. Endpoints equivalentes
Apps grandes tienen frecuentemente varios endpoints que hacen lo mismo:
/api/v1/loginy/api/v2/login./loginy/auth/login./api/loginy/api/internal/login./loginy/oauth/token(password grant).- Mobile API (
/mobile/api/...) vs web API. - GraphQL endpoint que mapea al mismo backend.
Si solo /login tiene rate limit pero /api/v1/login o el GraphQL mutation login no → bypass.
5. Race condition con buckets de rate limit
Algunos rate limiters reset en ventanas: 5 intentos por 5 minutos.
- Si timestamping es por bucket de hora exacta (60min), prueba justo al cambio de bucket: 50 intentos a las 11:59:30 + 50 a las 12:00:30.
- Algunos resetan al login exitoso → si tienes un account válido, puedes alternarlo con guesses al de la víctima para resetear el contador.
6. HTTP smuggling para evadir el WAF/proxy
CDN/proxy aplica rate limit. Server backend no. Si hay HTTP smuggling, se cuela request al backend sin pasar por el rate limiter del proxy. (Ver artículo dedicado a HTTP request smuggling).
7. WebSocket fallback
Algunos endpoints tienen versión REST y versión WebSocket. Si solo el REST está rate-limitado, el WebSocket procesa miles de mensajes por conexión sin throttling.
8. GraphQL aliasing
Una sola petición GraphQL puede ejecutar el mismo mutation N veces:
mutation {
attempt1: login(user: "victim", pass: "guess1") { token }
attempt2: login(user: "victim", pass: "guess2") { token }
...
attempt100: login(user: "victim", pass: "guess100") { token }
}
Si el rate limit cuenta requests HTTP pero no operations dentro de cada request, 1 request = 100 intentos. Bypass total.
9. Bucket reset por user input
Patrón común: rate limit por (IP, username). Si el atacante varía el username:
victim@email.tld
Victim@email.tld (case → mismo user en algunos backends, distinto bucket en rate limiter)
victim@Email.TLD
victim+x@email.tld
Caso real: el bug 0-click-ato-otp-brute-force documentado en otro artículo de la Academy.
10. Cookie-based identification bypass
Si el rate limit usa cookie/session:
- Limpiar cookies entre requests → bypass directo.
- Crear cuentas anónimas masivas y rotar.
Detección rápida
Burp Repeater + Intruder con 100 requests rápidas. Mide:
- ¿Status code cambia? (200 → 429 → ?).
- ¿Después de cuántas requests?
- ¿Resetea por minuto, por hora, por día?
- ¿Por IP, por user, por session?
Una vez identificado el mecanismo, prueba los bypasses correspondientes.
Casos de impacto frecuentes
- OTP brute force sobre password reset → ATO masivo.
- Login brute force sobre cuentas con passwords débiles.
- Email enumeration sin throttling → lista de cuentas válidas.
- API keys generation flood → DoS / abuso de quota gratuita.
- Coupon code brute → códigos de descuento robados.
- Phone number enumeration vía endpoints de "envío de OTP".
Hunting checklist
- ¿El rate limiter responde 429 después de X requests? Mídelo.
- ¿
X-Forwarded-Forarbitrario lo bypass? - ¿Capitalización del path lo bypass?
- ¿Hay endpoints equivalentes sin rate limit?
- ¿GraphQL permite aliasing del mismo mutation?
- ¿WebSocket version del endpoint?
- ¿Email casing afecta el bucket pero no la auth real?
- ¿Cookies se pueden rotar para resetear?
- ¿API "interna" en otro path procesa el mismo backend?
Mitigación correcta
- Rate limit por IP real (validada por proxy de confianza, no spoofeable por header arbitrario).
- Rate limit por user account (no solo IP) cuando hay user identificable.
- Bucket compartido entre todos los endpoints equivalentes.
- Counting de operations dentro de cada request (importa especialmente en GraphQL).
- Lockout temporal después de N intentos fallidos consecutivos sobre la misma cuenta.
Labs relacionados
Practica IP rotation, header spoof, GraphQL aliasing y race condition de rate limit: labs de Rate Limiting.
La checklist que repaso en cada objetivo nuevo
47 comprobaciones ordenadas por coste: primero lo que te puede meter en un lío, luego lo barato, y al final lo caro — que es donde están los bounties grandes. Te la mando al correo ahora mismo.
Te das de baja en un clic, desde cualquier correo.
Practica esto en un lab
Rate Limiting
Sigue aprendiendo · cuenta gratis
Guarda tu progreso, desbloquea payloads avanzados y rankea tus flags.
Artículos relacionados
0-click Account Takeover — OTP brute force + Email Normalization
Dos fallos por separado parecen menores. Juntos, te dan ATO completo conociendo solo el email. Bounty real: €560 y 12 minutos de explotación.
Mass PII Extraction vía GraphQL — 93 perfiles reales en 1 hora
Un endpoint GraphQL de sincronización de contactos sin rate limiting, sin verificación de propiedad y con batching de 200 números por petición. Resolución teléfono → identidad real.
SSRF — bypasses completos: localhost, IPv6, decimal, DNS y cloud metadata
11 técnicas para bypassear validación SSRF: enclosed alphanumeric, decimal IP, dot bypass, DNS rebinding, parameter pollution. Cloud metadata AWS/GCP/Azure.
