npx skills add mukul975/Anthropic-Cybersecurity-SkillsMITRE ATT&CK
NIST CSF 2.0
MITRE ATLAS
MITRE D3FEND
Overview
AI-powered BEC detection uses machine learning, NLP, and behavioral analytics to identify sophisticated impersonation attacks that contain no malicious links or attachments. Traditional rule-based filters miss these attacks because BEC relies purely on social engineering. Modern AI approaches analyze writing style, tone, vocabulary, grammatical patterns, and behavioral context to determine if an email genuinely comes from the stated sender. BERT-based models achieve 98.65% accuracy in BEC detection, and AI-enhanced platforms show a 25% increase in phishing identification over keyword-based rules.
When to Use
- When investigating security incidents that require detecting business email compromise with ai
- When building detection rules or threat hunting queries for this domain
- When SOC analysts need structured procedures for this analysis type
- When validating security monitoring coverage for related attack techniques
Prerequisites
- AI-powered email security platform (Abnormal Security, Tessian, Microsoft Defender)
- Historical email data for baseline training (minimum 30 days)
- Integration with email platform (Microsoft 365 or Google Workspace)
- SIEM for alert correlation and investigation
- Understanding of BEC attack types (FBI IC3 classification)
Workflow
Step 1: Deploy AI Email Security Platform
- Select API-based solution (Abnormal Security, Tessian, Ironscales) or enhance existing SEG
- Connect to Microsoft Graph API or Google Workspace API
- Allow 48-hour baseline learning period on historical email data
- Configure integration to scan inbound, outbound, and internal email
- Verify API permissions for message access and remediation
Step 2: Configure Behavioral Baselines
- AI learns normal communication patterns: who emails whom, frequency, tone
- Establish writing style profiles for each user (vocabulary, sentence structure)
- Map typical request types per role (finance processes payments, HR handles PII)
- Baseline email metadata: typical sending times, devices, locations
- Flag deviations from established baselines as anomalous
Step 3: Train NLP Models for BEC Detection
- Deploy transformer-based models (BERT, GPT) for email content analysis
- Detect urgency and manipulation language patterns
- Identify mismatches between sender identity and writing style
- Analyze sentiment shifts indicating social engineering pressure
- Classify email intent: information request, payment request, credential request
Step 4: Configure Detection Policies
- VIP impersonation: AI compares new email against known executive communication patterns
- Vendor impersonation: detect payment change requests from vendor lookalike domains
- Account compromise: detect sudden changes in employee email behavior
- Supply chain BEC: monitor for impersonation of trusted partners
- Configure confidence thresholds for auto-block vs. warning banner vs. analyst review
Step 5: Integrate with Response Workflow
- Auto-quarantine high-confidence BEC detections
- Add warning banners for moderate-confidence detections
- Route suspicious emails to SOC analyst queue for review
- Integrate with SOAR for automated response playbooks
- Feed BEC verdicts back into training data for model improvement
Tools & Resources
- Abnormal Security: API-based AI email security with behavioral analysis
- Microsoft Defender for O365: Built-in AI anti-BEC with Impostor Classifier
- Tessian (Proofpoint): AI-powered email security with human layer protection
- Ironscales: AI + human-in-the-loop BEC detection
- Darktrace Email: Self-learning AI for email threat detection
Validation
- AI detects test BEC email with no malicious indicators (pure social engineering)
- Writing style analysis identifies impersonation of known executive
- Behavioral baseline flags unusual payment request from compromised account
- NLP correctly classifies urgency manipulation in test scenario
- False positive rate below 0.05% after baseline training
- Detection rate exceeds traditional rule-based filters by 25%+
References and resources
Everything below is rendered for inspection. Script files are read-only and never run.
References 3
api-reference.md2.2 KB
API Reference: Detecting BEC with AI
NLP Feature Extraction
| Feature | Description | BEC Signal |
|---|---|---|
| urgency_score | Ratio of urgency words to total | High = suspicious |
| pressure_score | Ratio of secrecy/pressure words | High = suspicious |
| financial_score | Ratio of financial terms | High = suspicious |
| authority_score | Ratio of executive title mentions | High = suspicious |
| caps_ratio | Uppercase character ratio | High = aggressive tone |
| unique_word_ratio | Vocabulary diversity metric | Low = template-like |
scikit-learn Classification Pipeline
from sklearn.pipeline import Pipeline
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.ensemble import RandomForestClassifier
pipeline = Pipeline([
("tfidf", TfidfVectorizer(max_features=5000, ngram_range=(1, 2))),
("clf", RandomForestClassifier(n_estimators=100, random_state=42))
])
pipeline.fit(X_train, y_train)
predictions = pipeline.predict(X_test)Writing Style Analysis (Stylometry)
# Sentence length distribution for author verification
import re, math
sentences = re.split(r'[.!?]+', text)
lengths = [len(s.split()) for s in sentences if s.strip()]
mean_len = sum(lengths) / len(lengths)
variance = sum((l - mean_len)**2 for l in lengths) / len(lengths)
std_dev = math.sqrt(variance)Microsoft Graph API - Suspicious Mail Rules
GET https://graph.microsoft.com/v1.0/users/{id}/mailFolders/inbox/messageRules
Authorization: Bearer {token}
# Detect forwarding rules (T1114.003)
GET https://graph.microsoft.com/v1.0/users/{id}/mailFolders/inbox/messageRules?$filter=actions/forwardTo ne nullImpersonation Signal Patterns
# Mobile signature (creates urgency excuse)
r"sent from my (iphone|ipad|android|mobile)"
# Discourages verification
r"(please|kindly).*(do not|don't).*(reply|respond|call)"
# Unavailability excuse
r"(i am|i'm).*(in a meeting|traveling|on a flight)"
# Time pressure
r"(handle|process|complete).*(today|immediately|by end of day)"CLI Usage
python agent.py --file email_body.txt
python agent.py --file email_body.txt --baseline-file sender_style.jsonstandards.md1.3 KB
Standards & References: Detecting BEC with AI
MITRE ATT&CK References
- T1566.001/002: Phishing (Spearphishing Attachment/Link)
- T1534: Internal Spearphishing
- T1656: Impersonation
- T1586.002: Compromise Accounts: Email Accounts
- T1114.003: Email Collection: Email Forwarding Rule
AI/ML Techniques for BEC Detection
| Technique | Application | Accuracy |
|---|---|---|
| BERT embeddings + SVC | Email classification | 98.65% |
| Transformer NLP | Writing style analysis | 96%+ |
| Anomaly detection | Behavioral baseline deviation | 94%+ |
| Graph neural networks | Communication pattern analysis | 93%+ |
| Sentiment analysis | Urgency/manipulation detection | 91%+ |
FBI IC3 BEC Statistics
- $2.9 billion losses reported in 2023
- BEC accounts for 27% of all cybercrime financial losses
- Average loss per BEC incident: $125,000
- 21,832 BEC complaints filed in 2023
Detection Categories
- Impostor Detection: AI identifies display name/domain impersonation
- Account Takeover Detection: Behavioral anomalies from compromised accounts
- Writing Style Analysis: NLP compares email to sender's historical style
- Intent Classification: ML classifies email as payment/credential/data request
- Relationship Analysis: Graph analysis of sender-recipient communication patterns
workflows.md1.4 KB
Workflows: Detecting BEC with AI
Workflow 1: AI-Powered BEC Detection Pipeline
Inbound email arrives
|
v
[Feature extraction]
+-- Sender metadata (domain, IP, authentication)
+-- Email content (subject, body, NLP features)
+-- Behavioral context (communication history, timing)
+-- Relationship graph (sender-recipient pattern)
|
v
[Multi-model analysis (parallel)]
+-- Impostor classifier: Display name/domain impersonation
+-- NLP model: Writing style vs. sender baseline
+-- Behavioral model: Request anomaly detection
+-- Intent classifier: Payment/credential/data request
|
v
[Confidence scoring]
+-- Aggregate model outputs
+-- Weight by model confidence and context
+-- Generate overall BEC probability score
|
v
[Action]
+-- Score >= 90%: Auto-quarantine + SOC alert
+-- Score 70-89%: Warning banner + analyst queue
+-- Score 50-69%: Warning banner only
+-- Score < 50%: Deliver normallyWorkflow 2: Model Feedback Loop
BEC verdict generated
|
v
[User/analyst feedback]
+-- User reports false positive (legitimate email flagged)
+-- Analyst confirms true positive (BEC caught)
+-- User reports missed BEC (false negative)
|
v
[Feedback integration]
+-- Update sender trust score
+-- Retrain model with corrected labels
+-- Adjust confidence thresholds
+-- Update behavioral baselinesScripts 2
agent.py5.3 KB
#!/usr/bin/env python3
"""AI-powered BEC detection agent using NLP features for email classification.
Extracts linguistic features (urgency, sentiment, writing style metrics) and
uses scikit-learn to classify emails as BEC or legitimate.
"""
import argparse
import json
import math
import re
from collections import Counter
URGENCY_WORDS = {"urgent", "immediately", "asap", "deadline", "critical",
"important", "expedite", "priority", "rush", "now"}
PRESSURE_WORDS = {"confidential", "secret", "private", "classified",
"between us", "do not share", "don't discuss", "quiet"}
FINANCIAL_WORDS = {"wire", "transfer", "payment", "invoice", "bank",
"account", "routing", "ach", "swift", "funds"}
AUTHORITY_WORDS = {"ceo", "cfo", "president", "director", "boss",
"chairman", "executive", "management", "vp"}
def extract_features(text):
words = text.lower().split()
word_count = len(words) if words else 1
sentences = re.split(r'[.!?]+', text)
sentence_count = len([s for s in sentences if s.strip()]) or 1
word_freq = Counter(words)
unique_ratio = len(set(words)) / word_count
urgency_score = sum(1 for w in words if w.strip(".,!?") in URGENCY_WORDS) / word_count
pressure_score = sum(1 for w in words if w.strip(".,!?") in PRESSURE_WORDS) / word_count
financial_score = sum(1 for w in words if w.strip(".,!?") in FINANCIAL_WORDS) / word_count
authority_score = sum(1 for w in words if w.strip(".,!?") in AUTHORITY_WORDS) / word_count
exclamation_ratio = text.count("!") / sentence_count
caps_ratio = sum(1 for c in text if c.isupper()) / max(len(text), 1)
avg_word_len = sum(len(w) for w in words) / word_count
avg_sentence_len = word_count / sentence_count
return {
"word_count": word_count,
"sentence_count": sentence_count,
"unique_word_ratio": round(unique_ratio, 4),
"urgency_score": round(urgency_score, 4),
"pressure_score": round(pressure_score, 4),
"financial_score": round(financial_score, 4),
"authority_score": round(authority_score, 4),
"exclamation_ratio": round(exclamation_ratio, 4),
"caps_ratio": round(caps_ratio, 4),
"avg_word_length": round(avg_word_len, 2),
"avg_sentence_length": round(avg_sentence_len, 2),
}
def compute_bec_probability(features):
weights = {
"urgency_score": 3.5, "pressure_score": 3.0, "financial_score": 4.0,
"authority_score": 2.5, "exclamation_ratio": 1.0, "caps_ratio": 1.5,
}
raw = sum(features.get(k, 0) * w for k, w in weights.items())
probability = 1 / (1 + math.exp(-10 * (raw - 0.15)))
return round(probability, 4)
def analyze_writing_style(text):
sentences = [s.strip() for s in re.split(r'[.!?]+', text) if s.strip()]
if not sentences:
return {"style_consistency": 1.0}
lengths = [len(s.split()) for s in sentences]
mean_len = sum(lengths) / len(lengths)
variance = sum((l - mean_len) ** 2 for l in lengths) / len(lengths)
std_dev = math.sqrt(variance)
return {
"mean_sentence_length": round(mean_len, 2),
"sentence_length_std": round(std_dev, 2),
"style_consistency": round(1 - min(std_dev / 20, 1), 4),
}
def detect_impersonation_signals(text, known_sender_style=None):
signals = []
if re.search(r"sent from my (iphone|ipad|android|mobile)", text, re.IGNORECASE):
signals.append("mobile_signature_present")
if re.search(r"(please|kindly).*(do not|don't).*(reply|respond|call)", text, re.IGNORECASE):
signals.append("discourages_verification")
if re.search(r"(i am|i'm).*(in a meeting|traveling|on a flight|busy)", text, re.IGNORECASE):
signals.append("unavailability_excuse")
if re.search(r"(handle|process|complete).*(today|immediately|by end of day)", text, re.IGNORECASE):
signals.append("time_pressure")
if known_sender_style:
current = analyze_writing_style(text)
diff = abs(current["mean_sentence_length"] - known_sender_style.get("mean_sentence_length", 15))
if diff > 8:
signals.append("writing_style_deviation")
return signals
def analyze_email(text, known_style=None):
features = extract_features(text)
probability = compute_bec_probability(features)
style = analyze_writing_style(text)
signals = detect_impersonation_signals(text, known_style)
risk = "CRITICAL" if probability > 0.8 else "HIGH" if probability > 0.6 else \
"MEDIUM" if probability > 0.3 else "LOW"
return {
"features": features,
"writing_style": style,
"impersonation_signals": signals,
"bec_probability": probability,
"risk_level": risk,
}
def main():
parser = argparse.ArgumentParser(description="AI-Powered BEC Detection")
parser.add_argument("--file", required=True, help="Email text file to analyze")
parser.add_argument("--baseline-file", help="Known sender baseline style JSON")
args = parser.parse_args()
with open(args.file, "r", encoding="utf-8") as f:
text = f.read()
known_style = None
if args.baseline_file:
with open(args.baseline_file, "r") as f:
known_style = json.load(f)
result = analyze_email(text, known_style)
print(json.dumps(result, indent=2))
if __name__ == "__main__":
main()
process.py10.8 KB
#!/usr/bin/env python3
"""
AI-Powered BEC Detection Engine
Combines NLP analysis, behavioral scoring, and impersonation
detection to identify Business Email Compromise attacks.
Usage:
python process.py detect --email-json email.json --baseline-file baselines.json
python process.py train-baseline --email-log emails.json --output baselines.json
"""
import argparse
import json
import re
import sys
import math
from dataclasses import dataclass, field, asdict
from collections import defaultdict, Counter
@dataclass
class BECAIResult:
"""AI-powered BEC detection result."""
from_address: str = ""
subject: str = ""
impostor_score: float = 0.0
nlp_score: float = 0.0
behavioral_score: float = 0.0
intent_class: str = ""
overall_score: float = 0.0
is_bec: bool = False
confidence: float = 0.0
action: str = ""
indicators: list = field(default_factory=list)
# NLP feature patterns
URGENCY_PATTERNS = [
(r'\burgent(ly)?\b', 3), (r'\bimmediately\b', 3), (r'\basap\b', 3),
(r'\btime.?sensitive\b', 2), (r'\btoday\b', 1), (r'\bright\s+now\b', 2),
(r'\bdeadline\b', 1), (r'\boverdue\b', 2), (r'\bcritical\b', 2),
]
SECRECY_PATTERNS = [
(r'\bconfidential\b', 2), (r'\bdo\s+not\s+(share|tell|discuss)\b', 3),
(r'\bkeep.*between\s+us\b', 3), (r'\bquietly\b', 2),
(r'\bdon.t\s+mention\b', 2), (r'\bprivate\s+matter\b', 2),
]
FINANCIAL_PATTERNS = [
(r'\bwire\s+transfer\b', 3), (r'\binvoice\b', 2), (r'\bpayment\b', 2),
(r'\bbank\s+(account|details|transfer)\b', 3), (r'\bgift\s+card\b', 4),
(r'\bbitcoin\b', 3), (r'\baccount\s+number\b', 2), (r'\bswift\b', 2),
]
AUTHORITY_PATTERNS = [
(r'\bi\s+need\s+you\s+to\b', 2), (r'\bi.m\s+in\s+a\s+meeting\b', 3),
(r'\bhandle\s+this\b', 2), (r'\bi\s+authorize\b', 2),
(r'\bapproved\s+by\s+me\b', 3), (r'\bdon.t\s+call\b', 2),
]
def compute_nlp_score(text: str) -> tuple:
"""Compute NLP-based BEC score from email text."""
text_lower = text.lower()
scores = {"urgency": 0, "secrecy": 0, "financial": 0, "authority": 0}
indicators = []
for pattern, weight in URGENCY_PATTERNS:
if re.search(pattern, text_lower):
scores["urgency"] += weight
indicators.append(f"Urgency: {pattern}")
for pattern, weight in SECRECY_PATTERNS:
if re.search(pattern, text_lower):
scores["secrecy"] += weight
indicators.append(f"Secrecy: {pattern}")
for pattern, weight in FINANCIAL_PATTERNS:
if re.search(pattern, text_lower):
scores["financial"] += weight
indicators.append(f"Financial: {pattern}")
for pattern, weight in AUTHORITY_PATTERNS:
if re.search(pattern, text_lower):
scores["authority"] += weight
indicators.append(f"Authority: {pattern}")
total = sum(scores.values())
normalized = min(total / 25.0, 1.0) # Normalize to 0-1
# Determine intent
intent = "unknown"
if scores["financial"] > 3:
intent = "payment_request"
elif scores["authority"] > 3 and scores["urgency"] > 2:
intent = "directive"
elif scores["secrecy"] > 2:
intent = "sensitive_request"
return normalized, intent, indicators
def compute_impostor_score(email_data: dict, vip_list: list = None) -> tuple:
"""Check for sender impersonation."""
score = 0.0
indicators = []
from_name = email_data.get("from_display_name", "").lower()
from_email = email_data.get("from", "")
reply_to = email_data.get("reply_to", "")
from_domain = ""
match = re.search(r'@([\w.-]+)', from_email)
if match:
from_domain = match.group(1).lower()
# VIP name match from external domain
if vip_list:
for vip in vip_list:
vip_name = vip.get("name", "").lower()
vip_domain = vip.get("domain", "").lower()
if vip_name and vip_name in from_name:
if from_domain and vip_domain and from_domain != vip_domain:
score += 0.5
indicators.append(
f"Display name '{from_name}' matches VIP from external domain"
)
# Reply-to mismatch
if reply_to:
reply_domain = ""
match = re.search(r'@([\w.-]+)', reply_to)
if match:
reply_domain = match.group(1).lower()
if reply_domain and from_domain and reply_domain != from_domain:
score += 0.3
indicators.append(f"Reply-to domain mismatch: {reply_domain} vs {from_domain}")
return min(score, 1.0), indicators
def compute_behavioral_score(email_data: dict, baseline: dict) -> tuple:
"""Score behavioral anomalies against baseline."""
score = 0.0
indicators = []
sender = email_data.get("from", "")
recipient = email_data.get("to", "")
hour = email_data.get("send_hour", -1)
sender_baseline = baseline.get(sender, {})
# Check if first-time sender to this recipient
known_recipients = sender_baseline.get("recipients", [])
if recipient and known_recipients and recipient not in known_recipients:
score += 0.3
indicators.append("First-time communication with this recipient")
# Check unusual sending time
typical_hours = sender_baseline.get("typical_hours", [])
if hour >= 0 and typical_hours and hour not in typical_hours:
score += 0.2
indicators.append(f"Unusual sending hour: {hour}:00")
# Check if request type is unusual for sender
typical_topics = sender_baseline.get("typical_topics", [])
subject = email_data.get("subject", "").lower()
if typical_topics:
financial = any(w in subject for w in ["payment", "wire", "invoice", "transfer"])
if financial and "financial" not in typical_topics:
score += 0.3
indicators.append("Financial request from sender who doesn't typically discuss finances")
return min(score, 1.0), indicators
def detect_bec_ai(email_data: dict, baseline: dict = None,
vip_list: list = None) -> BECAIResult:
"""Run full AI BEC detection pipeline."""
result = BECAIResult()
result.from_address = email_data.get("from", "")
result.subject = email_data.get("subject", "")
body = email_data.get("body", "")
full_text = f"{result.subject} {body}"
# NLP analysis
result.nlp_score, result.intent_class, nlp_indicators = compute_nlp_score(full_text)
result.indicators.extend(nlp_indicators)
# Impostor detection
result.impostor_score, imp_indicators = compute_impostor_score(email_data, vip_list or [])
result.indicators.extend(imp_indicators)
# Behavioral analysis
if baseline:
result.behavioral_score, beh_indicators = compute_behavioral_score(
email_data, baseline
)
result.indicators.extend(beh_indicators)
# Weighted aggregate score
weights = {"nlp": 0.35, "impostor": 0.40, "behavioral": 0.25}
result.overall_score = (
result.nlp_score * weights["nlp"] +
result.impostor_score * weights["impostor"] +
result.behavioral_score * weights["behavioral"]
)
result.confidence = min(result.overall_score * 1.2, 1.0)
# Classification
if result.overall_score >= 0.7:
result.is_bec = True
result.action = "AUTO-QUARANTINE + SOC alert"
elif result.overall_score >= 0.5:
result.is_bec = True
result.action = "WARNING BANNER + analyst queue"
elif result.overall_score >= 0.3:
result.action = "WARNING BANNER only"
else:
result.action = "DELIVER normally"
return result
def train_baseline(emails: list) -> dict:
"""Build behavioral baselines from historical email data."""
baselines = defaultdict(lambda: {
"recipients": set(),
"typical_hours": [],
"typical_topics": set(),
"email_count": 0,
})
for email in emails:
sender = email.get("from", "")
if not sender:
continue
b = baselines[sender]
b["email_count"] += 1
recipient = email.get("to", "")
if recipient:
b["recipients"].add(recipient)
hour = email.get("send_hour", -1)
if hour >= 0:
b["typical_hours"].append(hour)
subject = email.get("subject", "").lower()
if any(w in subject for w in ["payment", "wire", "invoice"]):
b["typical_topics"].add("financial")
if any(w in subject for w in ["meeting", "schedule", "calendar"]):
b["typical_topics"].add("scheduling")
# Convert sets to lists for JSON serialization
result = {}
for sender, data in baselines.items():
hours = data["typical_hours"]
unique_hours = list(set(hours)) if hours else []
result[sender] = {
"recipients": list(data["recipients"]),
"typical_hours": unique_hours,
"typical_topics": list(data["typical_topics"]),
"email_count": data["email_count"],
}
return result
def main():
parser = argparse.ArgumentParser(description="AI-Powered BEC Detection")
subparsers = parser.add_subparsers(dest="command")
detect_parser = subparsers.add_parser("detect", help="Detect BEC in email")
detect_parser.add_argument("--email-json", required=True)
detect_parser.add_argument("--baseline-file")
detect_parser.add_argument("--vip-file")
train_parser = subparsers.add_parser("train-baseline", help="Train behavioral baseline")
train_parser.add_argument("--email-log", required=True)
train_parser.add_argument("--output", required=True)
parser.add_argument("--json", action="store_true")
args = parser.parse_args()
if args.command == "detect":
with open(args.email_json) as f:
email_data = json.load(f)
baseline = {}
if args.baseline_file:
with open(args.baseline_file) as f:
baseline = json.load(f)
vip_list = []
if args.vip_file:
with open(args.vip_file) as f:
vip_list = json.load(f)
result = detect_bec_ai(email_data, baseline, vip_list)
if args.json:
print(json.dumps(asdict(result), indent=2))
else:
print(f"BEC Score: {result.overall_score:.0%}")
print(f"Is BEC: {'YES' if result.is_bec else 'No'}")
print(f"Intent: {result.intent_class}")
print(f"Action: {result.action}")
if result.indicators:
print("Indicators:")
for ind in result.indicators:
print(f" - {ind}")
elif args.command == "train-baseline":
with open(args.email_log) as f:
emails = json.load(f)
baseline = train_baseline(emails)
with open(args.output, 'w') as f:
json.dump(baseline, f, indent=2)
print(f"Baseline trained for {len(baseline)} senders")
else:
parser.print_help()
if __name__ == "__main__":
main()