feat(mitmproxy): Integrate threat detection with CrowdSec for auto-banning
- Change analytics addon to write threats to /data/threats.log (bind-mounted to host) - Add CrowdSec acquisition config to read from /srv/mitmproxy/threats.log - Add parser for mitmproxy JSON threat logs with source_ip in Meta - Add scenarios for web attacks, scanners, SSRF, and CVE exploits - Update RPCD to read alerts from host-visible path without lxc-attach This enables automatic IP banning when mitmproxy detects: - SQL injection, XSS, command injection (capacity: 3, ban: 15m) - Path traversal, XXE, LDAP injection, Log4Shell - Aggressive web scanning (capacity: 10, ban: 10m) - SSRF attempts from external IPs (capacity: 5, ban: 10m) - Known CVE exploits (immediate trigger, ban: 30m) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
88e6d04f4e
commit
7b67b0329a
@ -339,16 +339,16 @@ do_stop() { [ -x /etc/init.d/mitmproxy ] && /etc/init.d/mitmproxy stop >/dev/nul
|
||||
do_restart() { [ -x /etc/init.d/mitmproxy ] && /etc/init.d/mitmproxy restart >/dev/null 2>&1; echo '{"success":true}'; }
|
||||
|
||||
get_alerts() {
|
||||
# Read alerts from container's JSONL log file
|
||||
# The analytics addon writes one JSON object per line to /var/log/crowdsec/secubox-mitm.log
|
||||
local log_file="/var/log/crowdsec/secubox-mitm.log"
|
||||
# Read alerts from host-visible JSONL log file
|
||||
# The analytics addon writes to /data/threats.log inside container
|
||||
# which is bind-mounted to /srv/mitmproxy/threats.log on host
|
||||
local log_file="/srv/mitmproxy/threats.log"
|
||||
local max_alerts=50
|
||||
local alerts_json="[]"
|
||||
|
||||
# Try to get last N alerts from LXC container and convert JSONL to JSON array
|
||||
if command -v lxc-attach >/dev/null 2>&1; then
|
||||
# Read last N lines, wrap in JSON array
|
||||
local lines=$(lxc-attach -n "$LXC_NAME" -- tail -n "$max_alerts" "$log_file" 2>/dev/null)
|
||||
# Read last N lines from the host-accessible log file
|
||||
if [ -f "$log_file" ]; then
|
||||
local lines=$(tail -n "$max_alerts" "$log_file" 2>/dev/null)
|
||||
if [ -n "$lines" ]; then
|
||||
# Convert JSONL to JSON array: join lines with commas, wrap in brackets
|
||||
alerts_json=$(echo "$lines" | awk '
|
||||
@ -401,12 +401,11 @@ EOFJ
|
||||
}
|
||||
|
||||
clear_alerts() {
|
||||
# Clear alerts in container
|
||||
if command -v lxc-attach >/dev/null 2>&1; then
|
||||
lxc-attach -n "$LXC_NAME" -- sh -c 'echo "[]" > /tmp/secubox-mitm-alerts.json' 2>/dev/null
|
||||
fi
|
||||
# Clear the host-visible threats log file
|
||||
local log_file="/srv/mitmproxy/threats.log"
|
||||
> "$log_file" 2>/dev/null
|
||||
|
||||
# Also clear on host
|
||||
# Also clear the legacy alerts file
|
||||
echo "[]" > /tmp/secubox-mitm-alerts.json 2>/dev/null
|
||||
|
||||
echo '{"success":true,"message":"Alerts cleared"}'
|
||||
|
||||
@ -0,0 +1,10 @@
|
||||
# CrowdSec acquisition for mitmproxy threat logs
|
||||
# Monitors threats detected by SecuBox mitmproxy analytics addon
|
||||
# The analytics addon runs inside LXC container and writes to /data/threats.log
|
||||
# which is bind-mounted to /srv/mitmproxy/threats.log on the host
|
||||
|
||||
source: file
|
||||
filenames:
|
||||
- /srv/mitmproxy/threats.log
|
||||
labels:
|
||||
type: mitmproxy
|
||||
@ -0,0 +1,53 @@
|
||||
# CrowdSec parser for SecuBox mitmproxy threat logs
|
||||
# Parses JSON threat events from mitmproxy analytics addon
|
||||
|
||||
onsuccess: next_stage
|
||||
name: secubox/mitmproxy-threats
|
||||
description: "Parse SecuBox mitmproxy threat detection logs (JSON)"
|
||||
filter: "evt.Line.Labels.type == 'mitmproxy'"
|
||||
statics:
|
||||
- parsed: source_ip
|
||||
expression: JsonExtract(evt.Line.Raw, "source_ip")
|
||||
- parsed: timestamp
|
||||
expression: JsonExtract(evt.Line.Raw, "timestamp")
|
||||
- parsed: request
|
||||
expression: JsonExtract(evt.Line.Raw, "request")
|
||||
- parsed: host
|
||||
expression: JsonExtract(evt.Line.Raw, "host")
|
||||
- parsed: user_agent
|
||||
expression: JsonExtract(evt.Line.Raw, "user_agent")
|
||||
- parsed: threat_type
|
||||
expression: JsonExtract(evt.Line.Raw, "type")
|
||||
- parsed: pattern
|
||||
expression: JsonExtract(evt.Line.Raw, "pattern")
|
||||
- parsed: category
|
||||
expression: JsonExtract(evt.Line.Raw, "category")
|
||||
- parsed: severity
|
||||
expression: JsonExtract(evt.Line.Raw, "severity")
|
||||
- parsed: cve
|
||||
expression: JsonExtract(evt.Line.Raw, "cve")
|
||||
- parsed: response_code
|
||||
expression: JsonExtract(evt.Line.Raw, "response_code")
|
||||
- parsed: is_bot
|
||||
expression: JsonExtract(evt.Line.Raw, "is_bot")
|
||||
- parsed: country
|
||||
expression: JsonExtract(evt.Line.Raw, "country")
|
||||
- meta: log_type
|
||||
value: mitmproxy_threat
|
||||
- meta: service
|
||||
value: mitmproxy
|
||||
- meta: source_ip
|
||||
expression: JsonExtract(evt.Line.Raw, "source_ip")
|
||||
---
|
||||
# Filter for critical/high severity threats only (to avoid noise)
|
||||
onsuccess: next_stage
|
||||
name: secubox/mitmproxy-high-severity
|
||||
description: "Filter high severity mitmproxy threats for banning"
|
||||
filter: "evt.Meta.log_type == 'mitmproxy_threat' && evt.Parsed.severity in ['critical', 'high']"
|
||||
statics:
|
||||
- meta: threat_severity
|
||||
expression: evt.Parsed.severity
|
||||
- meta: threat_type
|
||||
expression: evt.Parsed.threat_type
|
||||
- meta: attack_pattern
|
||||
expression: evt.Parsed.pattern
|
||||
@ -0,0 +1,65 @@
|
||||
# CrowdSec scenario for SecuBox mitmproxy threat detection
|
||||
# Triggers bans for detected attacks (SQLi, XSS, command injection, etc.)
|
||||
|
||||
type: leaky
|
||||
name: secubox/mitmproxy-attack
|
||||
description: "Detect web attacks via mitmproxy (SQLi, XSS, command injection, SSRF)"
|
||||
filter: |
|
||||
evt.Meta.log_type == 'mitmproxy_threat' &&
|
||||
evt.Parsed.severity in ['critical', 'high'] &&
|
||||
evt.Parsed.pattern in ['sql_injection', 'xss', 'command_injection', 'path_traversal', 'xxe', 'ldap_injection', 'log4shell']
|
||||
groupby: evt.Meta.source_ip
|
||||
capacity: 3
|
||||
leakspeed: 60s
|
||||
blackhole: 15m
|
||||
labels:
|
||||
service: mitmproxy
|
||||
type: web_attack
|
||||
remediation: true
|
||||
---
|
||||
# Detect aggressive scanning/probing
|
||||
type: leaky
|
||||
name: secubox/mitmproxy-scanner
|
||||
description: "Detect aggressive web scanning via mitmproxy"
|
||||
filter: |
|
||||
evt.Meta.log_type == 'mitmproxy_threat' &&
|
||||
evt.Parsed.pattern in ['admin_scanner', 'config_scan', 'backup_scan', 'env_scan']
|
||||
groupby: evt.Meta.source_ip
|
||||
capacity: 10
|
||||
leakspeed: 30s
|
||||
blackhole: 10m
|
||||
labels:
|
||||
service: mitmproxy
|
||||
type: web_scan
|
||||
remediation: true
|
||||
---
|
||||
# Detect SSRF attempts (more lenient - internal IPs might be legitimate)
|
||||
type: leaky
|
||||
name: secubox/mitmproxy-ssrf
|
||||
description: "Detect SSRF attempts via mitmproxy"
|
||||
filter: |
|
||||
evt.Meta.log_type == 'mitmproxy_threat' &&
|
||||
evt.Parsed.pattern == 'ssrf' &&
|
||||
evt.Parsed.country != 'LOCAL'
|
||||
groupby: evt.Meta.source_ip
|
||||
capacity: 5
|
||||
leakspeed: 60s
|
||||
blackhole: 10m
|
||||
labels:
|
||||
service: mitmproxy
|
||||
type: ssrf
|
||||
remediation: true
|
||||
---
|
||||
# Detect known CVE exploitation attempts (immediate ban)
|
||||
type: trigger
|
||||
name: secubox/mitmproxy-cve
|
||||
description: "Detect CVE exploitation attempts via mitmproxy"
|
||||
filter: |
|
||||
evt.Meta.log_type == 'mitmproxy_threat' &&
|
||||
evt.Parsed.cve != '' &&
|
||||
evt.Parsed.severity == 'critical'
|
||||
blackhole: 30m
|
||||
labels:
|
||||
service: mitmproxy
|
||||
type: cve_exploit
|
||||
remediation: true
|
||||
@ -19,7 +19,9 @@ from pathlib import Path
|
||||
# GeoIP database path (MaxMind GeoLite2)
|
||||
GEOIP_DB = "/srv/mitmproxy/GeoLite2-Country.mmdb"
|
||||
LOG_FILE = "/var/log/secubox-access.log"
|
||||
CROWDSEC_LOG = "/var/log/crowdsec/secubox-mitm.log"
|
||||
# CrowdSec log - uses /data which is bind-mounted to /srv/mitmproxy on host
|
||||
# This allows CrowdSec on the host to read threat logs from the container
|
||||
CROWDSEC_LOG = "/data/threats.log"
|
||||
ALERTS_FILE = "/tmp/secubox-mitm-alerts.json"
|
||||
STATS_FILE = "/tmp/secubox-mitm-stats.json"
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user