Nuevos labs cada semana — Accede a todos desde 5€/mes

Nivel IntermedioGratis

Rate limit bypasses — IP rotation, headers spoof, casing y endpoints alternativos

X-Forwarded-For, IP rotation con cloudfront IPs, casing de path, encoding tricks, race condition de bucket. Cómo encontrar los gaps en el throttling.

Gorka El Bochi9 de mayo de 202610 min

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:

http
POST /login HTTP/1.1
Host: target.tld
X-Forwarded-For: 1.1.1.1

Cada request con un valor diferente "parece" IP distinta:

bash
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:

scss
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.tld desde otra IP de Cloudfront.

3. Path casing y encoding

Algunos rate limiters indexan por path exacto:

bash
/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/login y /api/v2/login.
  • /login y /auth/login.
  • /api/login y /api/internal/login.
  • /login y /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:

graphql
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:

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

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-For arbitrario 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

  1. Rate limit por IP real (validada por proxy de confianza, no spoofeable por header arbitrario).
  2. Rate limit por user account (no solo IP) cuando hay user identificable.
  3. Bucket compartido entre todos los endpoints equivalentes.
  4. Counting de operations dentro de cada request (importa especialmente en GraphQL).
  5. 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

Resolver

Sigue aprendiendo · cuenta gratis

Guarda tu progreso, desbloquea payloads avanzados y rankea tus flags.

Crear cuenta

Artículos relacionados