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.
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.