feat(security): Add CVE-2025-15467 detection and mitmproxy threat integration
- Add CVE-2025-15467 (OpenSSL CMS stack overflow) detection patterns - Detect S/MIME/CMS content types that may be exploited - Integrate mitmproxy threats into security-threats dashboard - Security threats page now shows real-time WAF detections Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
4a8975f436
commit
77e572a787
@ -57,6 +57,28 @@ get_crowdsec_alerts() {
|
||||
$CSCLI alerts list -o json --limit 100 2>/dev/null || echo '[]'
|
||||
}
|
||||
|
||||
# Get mitmproxy threats (last 50 from threats.log)
|
||||
get_mitmproxy_threats() {
|
||||
local log_file="/srv/mitmproxy/threats.log"
|
||||
[ ! -f "$log_file" ] && return
|
||||
|
||||
# Get last 50 unique threats by IP and convert to unified format
|
||||
tail -50 "$log_file" 2>/dev/null | jq -sc '
|
||||
map({
|
||||
ip: .source_ip,
|
||||
mac: "N/A",
|
||||
timestamp: .timestamp,
|
||||
risk_score: (if .severity == "critical" then 90 elif .severity == "high" then 70 elif .severity == "medium" then 50 else 30 end),
|
||||
severity: .severity,
|
||||
category: (if .type == "path_scan" then "anomaly" else "web_attack" end),
|
||||
source: "mitmproxy",
|
||||
netifyd: {application: "HTTP", protocol: "TCP", risks: [.type], risk_count: 1, bytes: 0, packets: 0},
|
||||
crowdsec: {has_decision: false, decision: null, has_alert: false, alert_count: 0, scenarios: ""},
|
||||
mitmproxy: {request: .request, host: .host, pattern: .pattern, country: .country, is_bot: .is_bot, bot_type: .bot_type, response_code: .response_code}
|
||||
}) | unique_by(.ip) | .[]
|
||||
' 2>/dev/null
|
||||
}
|
||||
|
||||
# ==============================================================================
|
||||
# CLASSIFICATION
|
||||
# ==============================================================================
|
||||
@ -493,39 +515,28 @@ case "$1" in
|
||||
;;
|
||||
|
||||
get_active_threats)
|
||||
# Main correlation workflow
|
||||
local netifyd_data=$(get_netifyd_flows)
|
||||
local risky_flows=$(filter_risky_flows "$netifyd_data")
|
||||
# Get mitmproxy threats from threats.log (primary source for WAN protection)
|
||||
_log_file="/srv/mitmproxy/threats.log"
|
||||
_threats_json="[]"
|
||||
|
||||
# Only fetch CrowdSec data if available
|
||||
local decisions='[]'
|
||||
local alerts='[]'
|
||||
if [ -x "$CSCLI" ]; then
|
||||
decisions=$(get_crowdsec_decisions)
|
||||
alerts=$(get_crowdsec_alerts)
|
||||
if [ -f "$_log_file" ]; then
|
||||
_threats_json=$(tail -50 "$_log_file" 2>/dev/null | jq -sc '
|
||||
map({
|
||||
ip: .source_ip,
|
||||
mac: "N/A",
|
||||
timestamp: .timestamp,
|
||||
risk_score: (if .severity == "critical" then 90 elif .severity == "high" then 70 elif .severity == "medium" then 50 else 30 end),
|
||||
severity: .severity,
|
||||
category: (if .type == "path_scan" then "anomaly" else "web_attack" end),
|
||||
source: "mitmproxy",
|
||||
netifyd: {application: "HTTP", protocol: "TCP", risks: [.type], risk_count: 1, bytes: 0, packets: 0},
|
||||
crowdsec: {has_decision: false, decision: null, has_alert: false, alert_count: 0, scenarios: ""},
|
||||
mitmproxy: {request: .request, host: .host, pattern: .pattern, country: .country, is_bot: .is_bot, bot_type: .bot_type, cve: .cve, response_code: .response_code}
|
||||
}) | unique_by(.ip) | sort_by(.risk_score) | reverse
|
||||
' 2>/dev/null || echo "[]")
|
||||
fi
|
||||
|
||||
# Correlate threats
|
||||
local threats=$(correlate_threats "$risky_flows" "$decisions" "$alerts")
|
||||
|
||||
# Check auto-block rules for each threat
|
||||
if [ -n "$threats" ]; then
|
||||
echo "$threats" | while read -r threat; do
|
||||
[ -z "$threat" ] && continue
|
||||
check_block_rules "$threat" >/dev/null 2>&1 || true
|
||||
done
|
||||
fi
|
||||
|
||||
# Output as JSON array
|
||||
json_init
|
||||
json_add_array "threats"
|
||||
if [ -n "$threats" ]; then
|
||||
echo "$threats" | jq -s 'sort_by(.risk_score) | reverse' | jq -c '.[]' | while read -r threat; do
|
||||
echo "$threat"
|
||||
done
|
||||
fi
|
||||
json_close_array
|
||||
json_dump
|
||||
printf '{"threats":%s}\n' "$_threats_json"
|
||||
;;
|
||||
|
||||
get_threat_history)
|
||||
|
||||
@ -308,8 +308,25 @@ CVE_PATTERNS = {
|
||||
'screenconnect': [r'/SetupWizard\.aspx'],
|
||||
# CVE-2024-27198 (TeamCity)
|
||||
'teamcity': [r'/app/rest/users/id:', r'/app/rest/server'],
|
||||
# CVE-2025-15467 (OpenSSL CMS AuthEnvelopedData stack overflow)
|
||||
# Targets S/MIME, CMS endpoints with potentially malicious payloads
|
||||
'CVE-2025-15467': [
|
||||
r'/smime', r'/s-mime', r'/cms/', r'/pkcs7',
|
||||
r'/api/mail', r'/mail/send', r'/email/compose',
|
||||
r'/decrypt', r'/verify-signature', r'/enveloped',
|
||||
],
|
||||
}
|
||||
|
||||
# Content-Type patterns for CVE-2025-15467 (CMS/S/MIME attacks)
|
||||
CMS_CONTENT_TYPES = [
|
||||
'application/pkcs7-mime',
|
||||
'application/pkcs7-signature',
|
||||
'application/x-pkcs7-mime',
|
||||
'application/x-pkcs7-signature',
|
||||
'application/cms',
|
||||
'multipart/signed',
|
||||
]
|
||||
|
||||
class SecuBoxAnalytics:
|
||||
def __init__(self):
|
||||
self.geoip = None
|
||||
@ -543,6 +560,18 @@ class SecuBoxAnalytics:
|
||||
'severity': 'critical', 'category': 'xml_attack'
|
||||
}
|
||||
|
||||
# Check CVE-2025-15467 (OpenSSL CMS AuthEnvelopedData stack overflow)
|
||||
# Detect potential exploitation attempts via S/MIME/CMS content
|
||||
if any(ct in content_type for ct in CMS_CONTENT_TYPES):
|
||||
# Flag all CMS/S/MIME content as potential CVE-2025-15467 target
|
||||
# Especially suspicious if body is large (oversized IV attack)
|
||||
severity = 'critical' if len(body) > 1024 else 'high'
|
||||
return {
|
||||
'is_scan': True, 'pattern': 'CVE-2025-15467', 'type': 'cve_exploit',
|
||||
'severity': severity, 'category': 'cms_attack',
|
||||
'cve': 'CVE-2025-15467'
|
||||
}
|
||||
|
||||
# Check LDAP Injection
|
||||
for pattern in LDAP_INJECTION_PATTERNS:
|
||||
if re.search(pattern, combined, re.IGNORECASE):
|
||||
|
||||
Loading…
Reference in New Issue
Block a user