Aventura.003 · Vigía de Amenazas
Bitácora de a bordo · Vigía de Amenazas · MDR

El // que
Burló al WAF

El WAF decía bloqueado; un // decía otra cosa. Cómo el Vigía de Amenazas cazó —en menos de 5 minutos y a través de dos cambios de técnica— a un corsario que esquivaba las restricciones por IP con doble slash y encoding unicode, y automatizó el abordaje en el WAF.
SectorPlataforma SaaS con API pública [dato anonimizado]
IslaVigía de Amenazas · SecMon
Duración de la refriega≈ 12 minutos, extremo a extremo
CapitánAbraham Juárez · 22 jun 2026
Nota de anonimización
Caso de estudio divulgativo basado en un incidente real. Se removieron o sustituyeron nombre del cliente, dominios, IPs, credenciales y endpoints reales. Las IPs se muestran en rangos de documentación (198.51.100.0/24, 203.0.113.0/24) y las rutas son genéricas (/admin, /api/registro).

01El reto: una compuerta que confiaba en las apariencias

Una restricción de acceso que confiaba en el path tal cual llegaba.

El cliente protegía dos superficies sensibles —su API interna y su portal de administración— con reglas de WAF basadas en IP de origen + ruta: /admin y /api/* solo se servían a IPs de la lista permitida. Para todos los demás, el WAF respondía 403.

El supuesto frágil: que la ruta que evalúa el WAF es la misma que finalmente resuelve el servidor de origen. No lo es. El WAF comparaba la cadena literal del path; el origen normalizaba esa cadena antes de enrutarla. Ese desajuste —regla sobre el texto crudo, enrutamiento sobre el texto normalizado— es toda la vulnerabilidad.

↓ El Reto
Una regla de borde que bloquea /admin pero deja pasar //admin no está protegiendo la ruta: está protegiendo una forma de escribirla. El origen colapsa // a / y sirve el recurso —con 200 OK—. El vigía del WAF nunca llegó a verlo como un abordaje a administración.

02La aventura: el abordaje, minuto a minuto

Dos fases, dos técnicas, dos IPs. La misma intención.

Fase 1 · Descubrimiento del bypass por doble slashT+00:00
Desde 198.51.100.0/24, el atacante prueba prefijos de slash sobre rutas bloqueadas. /admin devuelve 403; //admin devuelve 200 OK. El borde evalúa la cadena literal; el origen la normaliza. La restricción por IP queda anulada.
Fase 1 · Creación masiva de cuentas vía APIT+00:40
Con la API interna alcanzable, lanza llamadas automatizadas contra //api/registro: alta de cuentas en lote, a un ritmo y regularidad imposibles para un humano, sin el patrón de navegación previo (login, carga de assets, formularios) que precede a un alta legítima.
SecMon correlaciona y alertaT+04:10
El agente de IA cruza tres señales sobre la misma superficie protegida: IP externa accediendo a rutas de administración + volumen anómalo de creación de cuentas + ausencia del patrón de navegación legítimo. Alerta de severidad alta en WhatsApp y panel, en menos de 5 minutos desde el primer request malicioso.
Respuesta Fase 1T+05:00
Bloqueo inmediato de la IP en el WAF. Y la corrección de raíz: nueva regla que normaliza el path antes de evaluar restricciones// se colapsa a / antes de aplicar la lista de acceso.
Fase 2 · Cambio de IP y de técnica (encoding unicode)T+10:00
Cinco minutos después, desde una IP nueva (203.0.113.0/24), el atacante reintenta con el slash codificado: /%2F%2Fadmin, overlong encoding y variantes de representación del separador, para esquivar la flamante regla de doble slash literal.
SecMon vuelve a alertarT+10:40
No detecta una cadena: detecta el comportamiento. Misma superficie protegida, IP desconocida, mismo acceso anómalo a ritmo no humano. Segunda alerta, sin esperar a una firma nueva.
Respuesta Fase 2 · CierreT+12:00
Bloqueo de la nueva IP y regla reformulada para cubrir los métodos de bypass por encoding: URL-encoding estándar, overlong encoding y variantes del separador, decodificando y normalizando antes de aplicar reglas. El tráfico se tranquiliza; lo que queda es ruido de fondo (escaneos pasivos). Las cuentas creadas durante el ataque se auditaron y eliminaron.

El bypass, en concreto

# Lo que evaluaba la regla (texto crudo)   →   lo que servía el origen (normalizado)
GET /admin            → WAF: 403 Forbidden   # bloqueado correctamente
GET //admin           → WAF: 200 OK          # Fase 1: doble slash colapsado en el origen
GET /%2F%2Fadmin      → WAF: 200 OK          # Fase 2: separador URL-encoded
GET /%c0%afadmin      → WAF: 200 OK          # Fase 2: overlong encoding del '/'

# La corrección: normalizar ANTES de decidir
path = url_decode(raw_path)            # resuelve %2F, overlong, etc.
path = collapse_slashes(path)          # //  ///  →  /
if matches_protected(path) and ip not in allowlist:
    return 403                          # ahora sí, sobre la ruta real
<5 min
Del 1er request a la alerta
2
Técnicas de bypass cubiertas
200
Código que devolvía el //
0
Cuentas fraudulentas vivas

03La ruta: por qué el vigía lo vio (y un WAF de firmas no)

Caza por comportamiento sobre rutas protegidas y vulnerabilidades conocidas.

Un WAF tradicional bloquea lo que reconoce: una firma, un patrón conocido. El bypass por doble slash no dispara ninguna firma —es un GET perfectamente formado que devuelve 200—. El Vigía de Amenazas no pregunta "¿esto coincide con un ataque conocido?", sino "¿este comportamiento tiene sentido sobre esta superficie?".

Ingesta
Logs de WAF / acceso, sin tocar el origen
Normaliza
Path decodificado y colapsado en el evento
Superficie protegida
¿La ruta real cae en admin / API interna?
Agente de IA
Correla path protegido + vuln + ritmo no humano
Alerta
WhatsApp + panel, con IP y acciones
Contén
Bloqueo de IP + regla de normalización
Acceso a superficie protegida
IP externa que resuelve a /admin o API interna, sin estar en la lista permitida.
Ritmo no humano
Altas de cuenta en lote, regulares al milisegundo, sin el patrón de navegación previo.
Conciencia de vulnerabilidades
El agente conoce las debilidades del cliente y prioriza el tráfico que las roza.
Resistente al cambio de técnica
Doble slash o unicode: cambia la cadena, no el comportamiento. La segunda fase también alertó.
+ La Aventura
El corsario cambió de IP y de encoding, pero no pudo cambiar lo que quería: abordar una superficie de administración a la que no debería llegar, a un ritmo que ningún humano sostiene. Esa intención —no la cadena— es lo que el Vigía correlaciona. Por eso la Fase 2 no necesitó una firma nueva para disparar.

04El navío: stack tecnológico

Construido sobre tecnologías cloud-native, serverless y de bajo costo operativo en AWS.

Ingesta & cómputo
AWS Lambda · PythonEventBridgeCloudWatch LogsWAF logs
Almacenamiento
DynamoDBS3 · ParquetAthenaGlue
Detección por IA
Agente de correlaciónClaude / OpenAIMITRE ATT&CKPerfil de vulnerabilidades
Alertamiento
n8nWhatsApp / SlackAmazon SNS
Panel & respuesta
Next.js · ReactFastAPIRedisRegla / bloqueo en WAF
Principio operativo
Solo lectura de logsSin tocar el origenRol de acceso de solo-lectura

05El botín: resultados

Sin el VigíaCon SecMon
El bypass (200 OK) no dispara ninguna firma del WAFDetectado por comportamiento en <5 min del primer request
Cambiar de técnica (unicode) reinicia el reloj del atacanteLa Fase 2 alertó igual: misma intención, sin firma nueva
La regla parchea la cadena de hoy, no la clase de ataqueCorrección de raíz: normalizar el path antes de evaluar
Cuentas fraudulentas descubiertas días después, si acasoAuditadas y eliminadas el mismo día del incidente
Respuesta manual, dependiente de que alguien mire los logsDe la alerta al bloqueo en WAF en minutos

Cartas de navegación para cualquier organización

¿Tu WAF normaliza los paths antes de aplicar reglas?

Lo revisamos sobre tus propios logs: te mostramos si //admin o /%2F%2Fadmin esquivan tus restricciones, y qué comportamiento estás dejando navegar hoy. Sin tocar tu infraestructura — solo lectura.

Pon un vigía en tu mástil →
Cómo citar esta aventura
Juárez, A. (2026). El // que Burló al WAF: bypass por doble slash y unicode. Campelsoft — La Gran Ruta. https://campelsoft.com/casos/waf-bypass.html