Phase 7: Behavioral Detection
Phase 7: Behavioral Detection (Abnormal Simulator)
Objective
Build a Python script that reads delivered mail via IMAP (post-delivery), parses headers, scores behavioral anomalies, auto-remediates suspicious messages, and forwards detection events to Wazuh. This simulates how Abnormal Security operates — API-based, post-delivery, behavioral.
Maps to Work
| Lab | CHLA (Abnormal) |
|---|---|
Python reads IMAP (post-delivery) |
Abnormal reads M365 Graph API (post-delivery) |
Parse Authentication-Results headers |
Abnormal ingests SPF/DKIM/DMARC verdicts from M365 |
Behavioral scoring (domain similarity, urgency, sender history) |
Abnormal behavioral AI (BEC detection, account takeover, invoice fraud) |
Move to quarantine folder via IMAP |
Abnormal auto-remediation (move to junk, delete, banner) |
Forward events to Wazuh API |
Abnormal API → Sentinel integration |
Why Post-Delivery?
This is the fundamental architectural difference between ESA and Abnormal:
-
ESA (inline): sits in the SMTP path. If ESA rejects, the message never arrives. If ESA is down, mail stops.
-
Abnormal (API): reads after M365 delivers. Mail always arrives. Abnormal remediates after the fact. If Abnormal is down, mail still flows — you just lose detection.
Building this in the lab lets you experience that tradeoff firsthand.
Script Architecture
mail-detector.py
├── connect_imap() — Connect to dovecot via IMAPS
├── fetch_new_messages() — Read unprocessed messages from INBOX
├── parse_headers() — Extract Authentication-Results, From, Reply-To, Received chain
├── score_message() — Behavioral scoring engine
│ ├── check_auth_results() — SPF/DKIM/DMARC pass/fail
│ ├── check_domain_similarity() — Levenshtein distance on From domain
│ ├── check_urgency() — Keyword scan (urgent, wire transfer, password, click here)
│ └── check_sender_history() — First-time sender detection
├── remediate() — Move suspicious messages to Quarantine folder
└── report_to_wazuh() — POST detection event to Wazuh API
Detection Signals
| Signal | What It Catches | Score Weight |
|---|---|---|
SPF fail |
Unauthorized sender IP |
+30 |
DKIM fail |
Tampered message content |
+30 |
DMARC fail |
Domain alignment failure |
+20 |
Domain similarity > 0.8 |
Lookalike domains (examp1e.com vs example.com) |
+25 |
Urgency keywords |
Social engineering pressure (BEC indicator) |
+15 |
From != Reply-To domain |
Reply-to hijacking |
+20 |
First-time sender |
No prior communication history |
+10 |
Score >= 50: quarantine. Score >= 30: flag. Score < 30: pass.
Wazuh Integration
Forward detection events via Wazuh API:
import requests
def report_to_wazuh(event: dict) -> None:
"""Send detection event to Wazuh manager API."""
wazuh_url = "https://{k3s-master-ip}:55000"
payload = {
"event": {
"type": "mail-behavioral-detection",
"score": event["score"],
"signals": event["signals"],
"from": event["from"],
"subject": event["subject"],
"action": event["action"], # quarantine | flag | pass
}
}
# POST to Wazuh active response or custom integration
requests.post(f"{wazuh_url}/active-response", json=payload, verify=False)
Deployment
# On mail-01
sudo dnf install -y python3 python3-pip
pip3 install --user imapclient python-Levenshtein requests
# Create service
sudo tee /etc/systemd/system/mail-detector.service <<EOF
[Unit]
Description=Behavioral Mail Detection (Abnormal Simulator)
After=dovecot.service
[Service]
Type=simple
User=evan
ExecStart=/usr/bin/python3 /opt/mail-detector/mail-detector.py
Restart=on-failure
RestartSec=30
[Install]
WantedBy=multi-user.target
EOF
sudo systemctl enable --now mail-detector
Verification Checklist
-
Script connects to dovecot via IMAPS
-
Clean messages score < 30 and pass through
-
SPF-fail messages score >= 30 and get flagged
-
Spoofed/lookalike domain messages score >= 50 and get quarantined
-
Detection events appear in Wazuh
-
Quarantine IMAP folder contains remediated messages