chore: fix bug

This commit is contained in:
Nuxgrid
2026-07-19 17:56:59 +02:00
parent f1c4f18931
commit 224fa9c3cb
7 changed files with 11 additions and 360 deletions
@@ -102,7 +102,6 @@ services:
- ./wazuh/certs/root-ca-manager.pem:/etc/ssl/root-ca.pem - ./wazuh/certs/root-ca-manager.pem:/etc/ssl/root-ca.pem
- ./wazuh/certs/wazuh.manager.pem:/etc/ssl/filebeat.pem - ./wazuh/certs/wazuh.manager.pem:/etc/ssl/filebeat.pem
- ./wazuh/certs/wazuh.manager-key.pem:/etc/ssl/filebeat.key - ./wazuh/certs/wazuh.manager-key.pem:/etc/ssl/filebeat.key
- crowdsec_logs:/var/log/crowdsec:ro
- /var/run/docker.sock:/var/run/docker.sock - /var/run/docker.sock:/var/run/docker.sock
- /usr/bin/docker:/usr/local/bin/docker:ro - /usr/bin/docker:/usr/local/bin/docker:ro
- ./wazuh/config/wazuh_manager/active-response:/wazuh-custom/active-response:ro - ./wazuh/config/wazuh_manager/active-response:/wazuh-custom/active-response:ro
@@ -171,40 +170,6 @@ services:
networks: networks:
- monitoring_net - monitoring_net
# ─── CrowdSec LAPI ────────────────────────────────────────
crowdsec:
image: crowdsecurity/crowdsec:latest
container_name: crowdsec
restart: unless-stopped
environment:
COLLECTIONS: "crowdsecurity/linux crowdsecurity/nginx crowdsecurity/sshd"
GID: "0"
volumes:
- /var/log:/var/log/host:ro
- nginx_logs:/var/log/nginx:ro
- crowdsec_data:/var/lib/crowdsec/data
- crowdsec_config:/etc/crowdsec
- crowdsec_logs:/var/log/crowdsec
ports:
- "127.0.0.1:7777:8080"
- "10.0.0.2:8081:8080"
networks:
- monitoring_net
# ─── CrowdSec Firewall Bouncer ────────────────────────────
crowdsec-bouncer:
image: ghcr.io/crowdsecurity/cs-firewall-bouncer:latest
container_name: crowdsec-bouncer
restart: unless-stopped
network_mode: host
cap_add:
- NET_ADMIN
- NET_RAW
volumes:
- ./crowdsec/bouncer-monitoring.yaml:/etc/crowdsec/bouncers/crowdsec-firewall-bouncer.yaml:ro
depends_on:
- crowdsec
networks: networks:
monitoring_net: monitoring_net:
driver: bridge driver: bridge
@@ -226,7 +191,4 @@ volumes:
beszel_data: beszel_data:
clamav_data: clamav_data:
clamav_logs: clamav_logs:
crowdsec_data:
crowdsec_config:
crowdsec_logs:
uptime_kuma_data: uptime_kuma_data:
@@ -1,57 +0,0 @@
#!/bin/bash
# Wazuh Active Response -> CrowdSec ban
read INPUT
SRC_IP=$(echo "$INPUT" | python3 -c "
import sys, json, re
try:
d = json.load(sys.stdin)
alert = d.get('parameters', {}).get('alert', {})
data = alert.get('data', {})
# 1. Try standard srcip field
ip = data.get('srcip') or data.get('src_ip') or ''
# 2. Fallback: extract first public IP from full_log
if not ip:
full_log = alert.get('full_log', '')
ips = re.findall(r'\b(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})\b', full_log)
private = re.compile(r'^(10\.|192\.168\.|172\.(1[6-9]|2[0-9]|3[01])\.|127\.)')
for candidate in ips:
if not private.match(candidate):
ip = candidate
break
print(ip)
except:
print('')
" 2>/dev/null)
ACTION=$(echo "$INPUT" | python3 -c "
import sys, json
try:
d = json.load(sys.stdin)
print(d.get('command', 'add'))
except:
print('add')
" 2>/dev/null)
LOG=/var/ossec/logs/active-responses.log
if [ -z "$SRC_IP" ] || [ "$SRC_IP" = "null" ]; then
echo "$(date) crowdsec-ban: no IP found" >> "$LOG"
exit 0
fi
# Ne pas bannir les IPs privees / VPN
if echo "$SRC_IP" | grep -qE '^10\.|^192\.168\.|^172\.(1[6-9]|2[0-9]|3[01])\.|^127\.'; then
echo "$(date) crowdsec-ban: skip private IP $SRC_IP" >> "$LOG"
exit 0
fi
if [ "$ACTION" = "delete" ]; then
/usr/local/bin/docker exec crowdsec cscli decisions delete --ip "$SRC_IP" 2>/dev/null
echo "$(date) crowdsec-ban: UNBAN $SRC_IP" >> "$LOG"
else
/usr/local/bin/docker exec crowdsec cscli decisions add --ip "$SRC_IP" \
--duration 24h --reason Wazuh-ActiveResponse --type ban 2>&1 >> "$LOG"
echo "$(date) crowdsec-ban: BAN $SRC_IP" >> "$LOG"
fi
@@ -1,57 +0,0 @@
#!/bin/bash
# Wazuh Active Response -> CrowdSec ban
read INPUT
SRC_IP=$(echo "$INPUT" | python3 -c "
import sys, json, re
try:
d = json.load(sys.stdin)
alert = d.get('parameters', {}).get('alert', {})
data = alert.get('data', {})
# 1. Try standard srcip field
ip = data.get('srcip') or data.get('src_ip') or ''
# 2. Fallback: extract first public IP from full_log
if not ip:
full_log = alert.get('full_log', '')
ips = re.findall(r'\b(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})\b', full_log)
private = re.compile(r'^(10\.|192\.168\.|172\.(1[6-9]|2[0-9]|3[01])\.|127\.)')
for candidate in ips:
if not private.match(candidate):
ip = candidate
break
print(ip)
except:
print('')
" 2>/dev/null)
ACTION=$(echo "$INPUT" | python3 -c "
import sys, json
try:
d = json.load(sys.stdin)
print(d.get('command', 'add'))
except:
print('add')
" 2>/dev/null)
LOG=/var/ossec/logs/active-responses.log
if [ -z "$SRC_IP" ] || [ "$SRC_IP" = "null" ]; then
echo "$(date) crowdsec-ban: no IP found" >> "$LOG"
exit 0
fi
# Ne pas bannir les IPs privees / VPN
if echo "$SRC_IP" | grep -qE '^10\.|^192\.168\.|^172\.(1[6-9]|2[0-9]|3[01])\.|^127\.'; then
echo "$(date) crowdsec-ban: skip private IP $SRC_IP" >> "$LOG"
exit 0
fi
if [ "$ACTION" = "delete" ]; then
/usr/local/bin/docker exec crowdsec cscli decisions delete --ip "$SRC_IP" 2>/dev/null
echo "$(date) crowdsec-ban: UNBAN $SRC_IP" >> "$LOG"
else
/usr/local/bin/docker exec crowdsec cscli decisions add --ip "$SRC_IP" \
--duration 24h --reason Wazuh-ActiveResponse --type ban 2>&1 >> "$LOG"
echo "$(date) crowdsec-ban: BAN $SRC_IP" >> "$LOG"
fi
@@ -1,38 +0,0 @@
<!-- CrowdSec Decoders — format logrus key=value
Le decoder natif aws-eks-authenticator est exclu dans ossec.conf
(<decoder_exclude>) car son prematch pcre2 capture aussi ce format.
Ce decoder root "crowdsec" prend donc la main. -->
<decoder name="crowdsec">
<prematch type="pcre2">^time="\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}</prematch>
</decoder>
<!-- Ban CrowdSec : format "... : Xh ban on Ip A.B.C.D" (module db) -->
<decoder name="crowdsec-ban">
<parent>crowdsec</parent>
<prematch>ban on Ip </prematch>
<regex type="pcre2">ban on Ip ([\d.]+)</regex>
<order>srcip</order>
</decoder>
<!-- Ban CrowdSec : variante minuscule "ban on ip A.B.C.D" -->
<decoder name="crowdsec-ban-lc">
<parent>crowdsec</parent>
<prematch>ban on ip </prematch>
<regex type="pcre2">ban on ip ([\d.]+)</regex>
<order>srcip</order>
</decoder>
<!-- Overflow CrowdSec -->
<decoder name="crowdsec-overflow">
<parent>crowdsec</parent>
<prematch>overflow from </prematch>
<regex type="pcre2">overflow from ([\d.]+)</regex>
<order>srcip</order>
</decoder>
<!-- Champs generaux level/msg pour les logs non-ban -->
<decoder name="crowdsec-fields">
<parent>crowdsec</parent>
<regex type="pcre2">level=(\S+) msg="(.+?)"</regex>
<order>status,extra_data</order>
</decoder>
@@ -761,119 +761,6 @@
<timeout>21600</timeout> <timeout>21600</timeout>
</active-response> </active-response>
<!-- ════════════════════════════════════════════════════════════
CROWDSEC ACTIVE RESPONSE
════════════════════════════════════════════════════════════ -->
<command>
<name>crowdsec-ban</name>
<executable>crowdsec-ban.sh</executable>
<timeout_allowed>yes</timeout_allowed>
</command>
<!-- SSH Brute Force → CrowdSec ban 24h -->
<active-response>
<command>crowdsec-ban</command>
<location>local</location>
<rules_id>5710,5711,5712,5716,5720,5760,5763</rules_id>
<timeout>86400</timeout>
</active-response>
<!-- SSH brute-force custom (100300) + scan comptes (100301) → CrowdSec ban 24h -->
<active-response>
<command>crowdsec-ban</command>
<location>local</location>
<rules_id>100300,100301</rules_id>
<timeout>86400</timeout>
</active-response>
<!-- OWASP SQLi (100220,100290) → CrowdSec ban 24h -->
<active-response>
<command>crowdsec-ban</command>
<location>local</location>
<rules_id>100220,100290</rules_id>
<timeout>86400</timeout>
</active-response>
<!-- OWASP Command Injection (100222,100292) → CrowdSec ban permanent -->
<active-response>
<command>crowdsec-ban</command>
<location>local</location>
<rules_id>100222,100292</rules_id>
<timeout>0</timeout>
</active-response>
<!-- OWASP RCE/Exploit (100230) → CrowdSec ban 24h -->
<active-response>
<command>crowdsec-ban</command>
<location>local</location>
<rules_id>100230</rules_id>
<timeout>86400</timeout>
</active-response>
<!-- OWASP XSS (100240,100241,100291) → CrowdSec ban 12h -->
<active-response>
<command>crowdsec-ban</command>
<location>local</location>
<rules_id>100240,100241,100291</rules_id>
<timeout>43200</timeout>
</active-response>
<!-- OWASP LFI/RFI/Path Traversal (100250,100251,100252,100293) → CrowdSec ban 12h -->
<active-response>
<command>crowdsec-ban</command>
<location>local</location>
<rules_id>100250,100251,100252,100293</rules_id>
<timeout>43200</timeout>
</active-response>
<!-- OWASP XXE (100260) → CrowdSec ban 12h -->
<active-response>
<command>crowdsec-ban</command>
<location>local</location>
<rules_id>100260</rules_id>
<timeout>43200</timeout>
</active-response>
<!-- OWASP Scanner/SSRF/Upload (100270,100280,100281) → CrowdSec ban 12h -->
<active-response>
<command>crowdsec-ban</command>
<location>local</location>
<rules_id>100270,100280,100281</rules_id>
<timeout>43200</timeout>
</active-response>
<!-- ModSec attaque soutenue (100210) → CrowdSec ban 24h -->
<active-response>
<command>crowdsec-ban</command>
<location>local</location>
<rules_id>100202,100203,100204,100205,100206,100210</rules_id>
<timeout>86400</timeout>
</active-response>
<!-- API brute-force login (100610,100611,100612,100613) → CrowdSec ban 24h -->
<active-response>
<command>crowdsec-ban</command>
<location>local</location>
<rules_id>100610,100611,100612,100613</rules_id>
<timeout>86400</timeout>
</active-response>
<!-- CrowdSec ban détecté dans ses propres logs → renforcer le ban 24h -->
<active-response>
<command>crowdsec-ban</command>
<location>local</location>
<rules_id>100501,100502</rules_id>
<timeout>86400</timeout>
</active-response>
<!-- ════════════════════════════════════════════════════════════
CROWDSEC LOG MONITORING
════════════════════════════════════════════════════════════ -->
<localfile>
<log_format>syslog</log_format>
<location>/var/log/crowdsec/crowdsec.log</location>
</localfile>
<!-- ═══════════════════════════════════════════════════════════ <!-- ═══════════════════════════════════════════════════════════
LOG ANALYSIS (commandes système) LOG ANALYSIS (commandes système)
@@ -1013,10 +900,6 @@
<list>etc/lists/malicious-ioc/malicious-domains</list> <list>etc/lists/malicious-ioc/malicious-domains</list>
<list>etc/lists/malicious-ioc/malware-hashes</list> <list>etc/lists/malicious-ioc/malware-hashes</list>
<list>etc/lists/wireguard-trusted-ips</list> <list>etc/lists/wireguard-trusted-ips</list>
<!-- Exclusion du decoder natif aws-eks-authenticator : son prematch pcre2
time="\d{4}-\d{2}-\d{2}T..." capture aussi les logs logrus CrowdSec,
empechant notre decoder crowdsec-ban d'extraire data.srcip. -->
<decoder_exclude>0565-aws-eks-authenticator_decoders.xml</decoder_exclude>
<!-- Decoders et règles custom ModSecurity --> <!-- Decoders et règles custom ModSecurity -->
<decoder_dir>etc/decoders</decoder_dir> <decoder_dir>etc/decoders</decoder_dir>
<rule_dir>etc/rules</rule_dir> <rule_dir>etc/rules</rule_dir>
@@ -1,42 +0,0 @@
<!-- CrowdSec Rules — IDs 100500-100509 -->
<group name="crowdsec,">
<!-- Base: logs CrowdSec/logrus (pattern simple, sans \d) -->
<rule id="100500" level="3">
<location>/var/log/crowdsec/crowdsec.log</location>
<description>CrowdSec: event logged</description>
</rule>
<!-- IP bannie par CrowdSec -->
<rule id="100501" level="10">
<if_sid>100500</if_sid>
<match>ban Ip |ban ip | ban on Ip |Ip ban</match>
<description>CrowdSec: IP banned by decision engine</description>
<group>crowdsec_ban,pci_dss_10.6.1,gdpr_IV_35.7.d,</group>
</rule>
<!-- Nouvelle attaque detectee -->
<rule id="100502" level="8">
<if_sid>100500</if_sid>
<match>overflow from |triggered |New overflow|crowdsecurity/</match>
<description>CrowdSec: Attack scenario detected</description>
<group>crowdsec_alert,pci_dss_11.4,gdpr_IV_35.7.d,</group>
</rule>
<!-- Erreur CrowdSec -->
<rule id="100503" level="7">
<if_sid>100500</if_sid>
<match>level=error</match>
<description>CrowdSec: Error logged</description>
<group>crowdsec_error,</group>
</rule>
<!-- Erreur critique CrowdSec -->
<rule id="100504" level="12">
<if_sid>100500</if_sid>
<match>level=fatal|level=panic</match>
<description>CrowdSec: Critical error — service may be down</description>
<group>crowdsec_error,</group>
</rule>
</group>
+11 -11
View File
@@ -1,6 +1,6 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
""" """
Crée le dashboard "Securite - Alertes Web et CrowdSec" dans OpenSearch Dashboards (Wazuh). Crée le dashboard "Securite - Alertes Web et Firewall" dans OpenSearch Dashboards (Wazuh).
Usage: Usage:
python3 create-dashboard.py python3 create-dashboard.py
@@ -28,8 +28,8 @@ INDEX_PATTERN = "wazuh-alerts-*"
# ── Queries de filtre ───────────────────────────────────────────────────────── # ── Queries de filtre ─────────────────────────────────────────────────────────
Q_WEB = "rule.groups: web OR rule.groups: attack OR rule.groups: modsecurity OR rule.groups: api_brute_force" Q_WEB = "rule.groups: web OR rule.groups: attack OR rule.groups: modsecurity OR rule.groups: api_brute_force"
Q_CS = "rule.groups: crowdsec OR rule.groups: crowdsec_ban" Q_FW = "rule.id: 651"
Q_ALL = Q_WEB + " OR " + Q_CS Q_ALL = Q_WEB + " OR " + Q_FW
# ── Client HTTP ─────────────────────────────────────────────────────────────── # ── Client HTTP ───────────────────────────────────────────────────────────────
ctx = ssl.create_default_context() ctx = ssl.create_default_context()
@@ -85,9 +85,9 @@ VISUALIZATIONS = [
}, },
{ {
"id": "sec-cs-count", "id": "sec-cs-count",
"title": "[Securite] CrowdSec - Total Bans", "title": "[Securite] Firewall - Total Bans",
"type": "metric", "type": "metric",
"query": Q_CS, "query": Q_FW,
"visState": { "visState": {
"type": "metric", "type": "metric",
"params": { "params": {
@@ -99,7 +99,7 @@ VISUALIZATIONS = [
"colorsRange": [{"from": 0, "to": 5}, {"from": 5, "to": 50}, {"from": 50, "to": 9999}], "colorsRange": [{"from": 0, "to": 5}, {"from": 5, "to": 50}, {"from": 50, "to": 9999}],
"labels": {"show": True}, "labels": {"show": True},
"invertColors": False, "invertColors": False,
"style": {"bgFill": "#000", "bgColor": False, "labelColor": False, "subText": "bans crowdsec", "fontSize": 60}, "style": {"bgFill": "#000", "bgColor": False, "labelColor": False, "subText": "bans firewall", "fontSize": 60},
} }
}, },
"aggs": [{"id": "1", "enabled": True, "type": "count", "schema": "metric", "params": {}}], "aggs": [{"id": "1", "enabled": True, "type": "count", "schema": "metric", "params": {}}],
@@ -163,9 +163,9 @@ VISUALIZATIONS = [
}, },
{ {
"id": "sec-cs-bans-table", "id": "sec-cs-bans-table",
"title": "[Securite] CrowdSec - IPs Bannies", "title": "[Securite] Firewall - IPs Bannies",
"type": "table", "type": "table",
"query": Q_CS, "query": Q_FW,
"visState": { "visState": {
"type": "table", "type": "table",
"params": {"perPage": 20, "showPartialRows": False, "showMetricsAtAllLevels": False, "sort": {"columnIndex": None, "direction": None}, "showTotal": False, "totalFunc": "sum"}, "params": {"perPage": 20, "showPartialRows": False, "showMetricsAtAllLevels": False, "sort": {"columnIndex": None, "direction": None}, "showTotal": False, "totalFunc": "sum"},
@@ -206,7 +206,7 @@ PANELS = [
# ── Main ────────────────────────────────────────────────────────────────────── # ── Main ──────────────────────────────────────────────────────────────────────
def main(): def main():
print("=== Création du dashboard Securite - Alertes Web et CrowdSec ===\n") print("=== Création du dashboard Securite - Alertes Web et Firewall ===\n")
# Visualisations # Visualisations
for viz in VISUALIZATIONS: for viz in VISUALIZATIONS:
@@ -231,8 +231,8 @@ def main():
# Dashboard # Dashboard
dashboard_body = { dashboard_body = {
"attributes": { "attributes": {
"title": "Securite - Alertes Web et CrowdSec", "title": "Securite - Alertes Web et Firewall",
"description": "Alertes OWASP ModSecurity brute-force API et bans CrowdSec", "description": "Alertes OWASP ModSecurity brute-force API et bans Firewall",
"panelsJSON": json.dumps(PANELS), "panelsJSON": json.dumps(PANELS),
"optionsJSON": json.dumps({"useMargins": True, "hidePanelTitles": False}), "optionsJSON": json.dumps({"useMargins": True, "hidePanelTitles": False}),
"timeRestore": False, "timeRestore": False,