Install this skill
npx skills add mukul975/Anthropic-Cybersecurity-SkillsFramework mappings
MITRE ATT&CK
When to Use
- When investigating security incidents that require detecting insider data exfiltration via dlp
- 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
- Familiarity with security operations concepts and tools
- Access to a test or lab environment for safe execution
- Python 3.8+ with required dependencies installed
- Appropriate authorization for any testing activities
Instructions
Analyze endpoint activity logs, cloud storage access, and email DLP events to detect data exfiltration patterns using behavioral baselines and statistical anomaly detection.
import pandas as pd
df = pd.read_csv("file_activity.csv", parse_dates=["timestamp"])
# Baseline: average daily upload volume per user
baseline = df.groupby(["user", df["timestamp"].dt.date])["bytes_transferred"].sum()
user_avg = baseline.groupby("user").mean()
# Alert on users exceeding 3x their baseline
today = df[df["timestamp"].dt.date == pd.Timestamp.today().date()]
today_totals = today.groupby("user")["bytes_transferred"].sum()
anomalies = today_totals[today_totals > user_avg * 3]Key indicators:
- Upload volume exceeding 3x daily baseline
- Access to files outside normal scope
- Bulk downloads before resignation
- Off-hours file access patterns
- USB/external device usage spikes
Examples
# Detect off-hours activity
df["hour"] = df["timestamp"].dt.hour
off_hours = df[(df["hour"] < 6) | (df["hour"] > 22)]
suspicious = off_hours.groupby("user").size().sort_values(ascending=False)Source materials
References and resources
Everything below is rendered for inspection. Script files are read-only and never run.
References 1
api-reference.md1.7 KB
API Reference: Detecting Insider Data Exfiltration via DLP
Pandas Behavioral Analytics
import pandas as pd
df = pd.read_csv("activity.csv", parse_dates=["timestamp"])
# Columns: timestamp, user, action, file_path, bytes_transferred, destination
# Daily volume baseline per user
daily = df.groupby(["user", df["timestamp"].dt.date])["bytes_transferred"].sum()
baseline = daily.groupby("user").agg(["mean", "std"])
# Off-hours detection
df["hour"] = df["timestamp"].dt.hour
off_hours = df[(df["hour"] < 6) | (df["hour"] >= 22)]
# Bulk download detection
df.set_index("timestamp").groupby("user").resample("1h").size()Exfiltration Indicators
| Indicator | Threshold | Severity |
|---|---|---|
| Volume > 3x baseline | Per user daily avg | HIGH |
| Volume > 5x baseline | Per user daily avg | CRITICAL |
| Off-hours events | > 10 per user | HIGH |
| Bulk downloads | > 50 files/hour | CRITICAL |
| USB transfers | Any volume | HIGH |
| Sensitive file access | Pattern match | HIGH |
Sensitive File Patterns
patterns = [
r"\.pem$", r"\.key$", r"\.env$",
r"credentials", r"password", r"\.kdbx$",
r"financial", r"payroll", r"customer.*data"
]Microsoft Purview DLP API
import requests
headers = {"Authorization": "Bearer <token>"}
resp = requests.get(
"https://graph.microsoft.com/v1.0/security/alerts_v2",
headers=headers,
params={"$filter": "category eq 'DataLossPrevention'"}
)References
Scripts 1
agent.py7.0 KB
Display-only source. This catalog never executes bundled scripts.
#!/usr/bin/env python3
"""Agent for detecting insider data exfiltration via DLP analysis."""
import json
import argparse
from datetime import datetime
import pandas as pd
def load_activity_logs(log_path):
"""Load file/cloud activity logs."""
if log_path.endswith(".csv"):
return pd.read_csv(log_path, parse_dates=["timestamp"])
return pd.read_json(log_path, lines=True)
def detect_volume_anomalies(df, multiplier=3.0):
"""Detect users with data transfer volume exceeding baseline."""
df["date"] = df["timestamp"].dt.date
daily_volume = df.groupby(["user", "date"])["bytes_transferred"].sum().reset_index()
user_baseline = daily_volume.groupby("user")["bytes_transferred"].agg(
["mean", "std"]).reset_index()
user_baseline.columns = ["user", "avg_bytes", "std_bytes"]
latest_date = df["date"].max()
latest_day = daily_volume[daily_volume["date"] == latest_date]
merged = latest_day.merge(user_baseline, on="user")
threshold = merged["avg_bytes"] + (multiplier * merged["std_bytes"].fillna(0))
anomalies = merged[merged["bytes_transferred"] > threshold]
findings = []
for _, row in anomalies.iterrows():
findings.append({
"user": row["user"],
"today_bytes": int(row["bytes_transferred"]),
"avg_bytes": int(row["avg_bytes"]),
"multiplier": round(row["bytes_transferred"] / max(row["avg_bytes"], 1), 1),
"severity": "CRITICAL" if row["bytes_transferred"] > row["avg_bytes"] * 5 else "HIGH",
})
return sorted(findings, key=lambda x: x["multiplier"], reverse=True)
def detect_off_hours_activity(df, start_hour=6, end_hour=22):
"""Detect file access during off-hours."""
df["hour"] = df["timestamp"].dt.hour
off_hours = df[(df["hour"] < start_hour) | (df["hour"] >= end_hour)]
if off_hours.empty:
return []
user_counts = off_hours.groupby("user").agg(
events=("timestamp", "count"),
bytes_total=("bytes_transferred", "sum"),
unique_files=("file_path", "nunique") if "file_path" in df.columns
else ("filename", "nunique"),
).reset_index()
findings = []
for _, row in user_counts.iterrows():
if row["events"] > 10:
findings.append({
"user": row["user"],
"off_hours_events": int(row["events"]),
"bytes_transferred": int(row["bytes_total"]),
"unique_files": int(row["unique_files"]),
"severity": "HIGH",
})
return sorted(findings, key=lambda x: x["off_hours_events"], reverse=True)
def detect_bulk_downloads(df, file_threshold=50, time_window="1h"):
"""Detect bulk file downloads in short time windows."""
findings = []
df_sorted = df.sort_values("timestamp")
download_actions = ["download", "copy", "export"]
action_col = "action" if "action" in df.columns else "event_type"
downloads = df_sorted[df_sorted[action_col].str.lower().isin(download_actions)]
if downloads.empty:
return findings
downloads = downloads.set_index("timestamp")
for user, group in downloads.groupby("user"):
rolling = group.resample(time_window).size()
bursts = rolling[rolling >= file_threshold]
if len(bursts) > 0:
findings.append({
"user": user,
"max_downloads_per_hour": int(rolling.max()),
"burst_periods": len(bursts),
"total_downloads": len(group),
"severity": "CRITICAL",
})
return findings
def detect_sensitive_file_access(df, sensitive_patterns=None):
"""Detect access to sensitive file types or directories."""
if sensitive_patterns is None:
sensitive_patterns = [
r"\.pem$", r"\.key$", r"\.env$", r"credentials",
r"password", r"\.kdbx$", r"\.pfx$", r"secret",
r"financial", r"payroll", r"customer.*data",
]
file_col = "file_path" if "file_path" in df.columns else "filename"
findings = []
import re
for _, row in df.iterrows():
filepath = str(row.get(file_col, ""))
for pattern in sensitive_patterns:
if re.search(pattern, filepath, re.IGNORECASE):
findings.append({
"user": row.get("user", ""),
"file": filepath,
"pattern_matched": pattern,
"action": row.get("action", row.get("event_type", "")),
"timestamp": str(row.get("timestamp", "")),
"severity": "HIGH",
})
break
return findings[:500]
def detect_usb_activity(df):
"""Detect USB device usage for data transfer."""
usb_indicators = ["removable", "usb", "external"]
dest_col = "destination" if "destination" in df.columns else "target"
usb_events = df[df[dest_col].str.lower().str.contains(
"|".join(usb_indicators), na=False)]
if usb_events.empty:
return []
user_usb = usb_events.groupby("user").agg(
events=("timestamp", "count"),
bytes_total=("bytes_transferred", "sum"),
).reset_index()
findings = []
for _, row in user_usb.iterrows():
findings.append({
"user": row["user"],
"usb_events": int(row["events"]),
"bytes_to_usb": int(row["bytes_total"]),
"severity": "HIGH",
})
return findings
def main():
parser = argparse.ArgumentParser(description="Insider Data Exfiltration Detection Agent")
parser.add_argument("--log-file", required=True, help="Activity log file")
parser.add_argument("--output", default="dlp_exfiltration_report.json")
parser.add_argument("--action", choices=[
"volume", "off_hours", "bulk", "sensitive", "full_analysis"
], default="full_analysis")
args = parser.parse_args()
df = load_activity_logs(args.log_file)
report = {"generated_at": datetime.utcnow().isoformat(), "total_events": len(df),
"findings": {}}
print(f"[+] Loaded {len(df)} activity events")
if args.action in ("volume", "full_analysis"):
findings = detect_volume_anomalies(df)
report["findings"]["volume_anomalies"] = findings
print(f"[+] Volume anomalies: {len(findings)}")
if args.action in ("off_hours", "full_analysis"):
findings = detect_off_hours_activity(df)
report["findings"]["off_hours_activity"] = findings
print(f"[+] Off-hours activity users: {len(findings)}")
if args.action in ("bulk", "full_analysis"):
findings = detect_bulk_downloads(df)
report["findings"]["bulk_downloads"] = findings
print(f"[+] Bulk download users: {len(findings)}")
if args.action in ("sensitive", "full_analysis"):
findings = detect_sensitive_file_access(df)
report["findings"]["sensitive_access"] = findings
print(f"[+] Sensitive file accesses: {len(findings)}")
with open(args.output, "w") as f:
json.dump(report, f, indent=2, default=str)
print(f"[+] Report saved to {args.output}")
if __name__ == "__main__":
main()
Keep exploring