SCP-V3 / scp /security /attack_classifier.py
Base44 Superagent
Replace SCP-V3 content with GA-LAB backend (FastAPI + LLM Bridge). Old V3 code/data preserved on GitHub checken1994/V3- (branch main).
d60732b
Raw
History Blame Contribute Delete
5.49 kB
"""
SCP V98 — AttackClassifierEngine
Copyright (c) 2026 Minh. MIT License.
Port từ WHY H6 — tổng hợp tín hiệu từ ThreatDetector → verdict AI/HUMAN + attack type.
Naming convention: <Purpose>Engine (world standard, e.g. ClassificationEngine)
"""
from __future__ import annotations
import logging
from dataclasses import dataclass, field
from typing import Any
from scp.security.threat_detector import ThreatSignal
logger = logging.getLogger("scp.security.attack_classifier")
@dataclass
class Classification:
"""Kết quả classify từ ThreatSignal."""
actor: str = "human" # human | bot_legacy | ai_agent_2026 | anonymizing_proxy | unknown
attack_type: str = "none" # none | scanner | injection | jailbreak | exfil | suspicious
severity: str = "none" # none | low | medium | high | critical
confidence: float = 0.0
strong_signals: list[str] = field(default_factory=list)
weak_signals: list[str] = field(default_factory=list)
def to_dict(self) -> dict[str, Any]:
return {
"actor": self.actor,
"attack_type": self.attack_type,
"severity": self.severity,
"confidence": round(self.confidence, 3),
"strong_signals": self.strong_signals,
"weak_signals": self.weak_signals,
}
# Strong signals (high confidence AI agent)
STRONG_SIGNALS = {
"injection": "injection",
"ua:python-requests": "bot",
"ua:curl": "bot",
"ua:scrapy": "scraper",
"ua:selenium": "automated",
"ua:puppeteer": "automated",
"asn:tor": "anonymizing",
"asn:datacenter": "datacenter",
"bot_timing": "automated",
"rapid_fire": "automated",
}
# Weak signals
WEAK_SIGNALS = {
"missing_headers": "suspicious",
"low_header_count": "suspicious",
"scanner": "suspicious",
"asn:vpn": "anonymizing",
"ua_mismatch": "suspicious",
}
class AttackClassifierEngine:
"""Classify threat signal → actor + attack_type + severity.
Naming convention: <Purpose>Engine (world standard).
"""
def classify(
self,
threat_signal: ThreatSignal,
h2_signatures: list[str] | None = None,
) -> Classification:
"""Fusion logic: strong signals > weak signals.
Rules:
- H2 attack content → actor = ai_agent
- 2+ strong signals → ai_agent_2026
- 1 strong + 1 weak → bot_legacy
- Weak only → monitor
- No signals → human
"""
signals = threat_signal.signals or []
strong = []
weak = []
for sig in signals:
# [V104.34 #55] TẠI SAO: old split(":")[0] gave prefix "ua"/"asn" →
# matched "injection" but missed "ua:python-requests" (full sig).
# Fix: try full sig first, then prefix as fallback.
sig_key = sig # full signal (e.g., "ua:python-requests")
if sig_key in STRONG_SIGNALS:
strong.append(sig)
elif sig_key in WEAK_SIGNALS:
weak.append(sig)
else:
# Fallback: try prefix (e.g., "injection:ignore_previous" → "injection")
prefix = sig.split(":")[0]
if prefix in STRONG_SIGNALS:
strong.append(sig)
elif prefix in WEAK_SIGNALS:
weak.append(sig)
# H2 attack content override
if h2_signatures:
strong.extend([f"h2:{s}" for s in h2_signatures])
# Determine actor
if len(strong) >= 2:
actor = "ai_agent_2026"
elif len(strong) >= 1:
if any("tor" in s for s in strong):
actor = "anonymizing_proxy"
elif any("injection" in s for s in strong):
actor = "ai_agent_2026"
else:
actor = "bot_legacy"
elif len(weak) >= 1:
actor = "unknown"
else:
actor = "human"
# Determine attack_type
if any("injection" in s for s in strong):
attack_type = "injection"
elif any("scanner" in s for s in strong + weak):
attack_type = "scanner"
elif any("rapid_fire" in s for s in strong):
attack_type = "dos"
elif any("tor" in s for s in strong):
attack_type = "anonymizing"
elif weak:
attack_type = "suspicious"
else:
attack_type = "none"
# Determine severity
if "injection" in attack_type:
severity = "critical"
elif actor == "ai_agent_2026" and attack_type in ("scanner", "dos"):
severity = "high"
elif actor == "ai_agent_2026":
severity = "high"
elif actor == "anonymizing_proxy":
severity = "high"
elif actor == "bot_legacy":
severity = "medium"
elif actor == "unknown":
severity = "low"
else:
severity = "none"
# Confidence: based on signal count + strength
conf = threat_signal.confidence
if len(strong) >= 2:
conf = max(conf, 0.9)
elif len(strong) >= 1:
conf = max(conf, 0.7)
return Classification(
actor=actor,
attack_type=attack_type,
severity=severity,
confidence=conf,
strong_signals=strong,
weak_signals=weak,
)
__all__ = ["Classification", "AttackClassifierEngine"]