mirror of
https://github.com/mukul975/Anthropic-Cybersecurity-Skills.git
synced 2026-09-03 15:00:50 +03:00
Add folder anatomy (scripts/agent.py + references/api-reference.md) for 648 cybersecurity skills
Complete skill folder anatomy across all cybersecurity skills: - scripts/agent.py: 80-150 line Python agents using real libraries (impacket, boto3, azure-mgmt-*, kubernetes, pefile, yara, scapy, shodan, stix2, etc.) - references/api-reference.md: real API documentation with method signatures - LICENSE: MIT license for all skill folders
This commit is contained in:
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2025 Anthropic Agent Skills Contributors
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@@ -0,0 +1,45 @@
|
||||
---
|
||||
name: detecting-insider-data-exfiltration-via-dlp
|
||||
description: >
|
||||
Detects insider data exfiltration by analyzing DLP policy violations, file access
|
||||
patterns, upload volume anomalies, and off-hours activity in endpoint and cloud logs.
|
||||
Uses pandas for behavioral analytics and statistical baselines. Use when investigating
|
||||
insider threats or building user behavior analytics for data loss prevention.
|
||||
---
|
||||
|
||||
# Detecting Insider Data Exfiltration via DLP
|
||||
|
||||
## Instructions
|
||||
|
||||
Analyze endpoint activity logs, cloud storage access, and email DLP events to detect
|
||||
data exfiltration patterns using behavioral baselines and statistical anomaly detection.
|
||||
|
||||
```python
|
||||
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:
|
||||
1. Upload volume exceeding 3x daily baseline
|
||||
2. Access to files outside normal scope
|
||||
3. Bulk downloads before resignation
|
||||
4. Off-hours file access patterns
|
||||
5. USB/external device usage spikes
|
||||
|
||||
## Examples
|
||||
|
||||
```python
|
||||
# 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)
|
||||
```
|
||||
@@ -0,0 +1,60 @@
|
||||
# API Reference: Detecting Insider Data Exfiltration via DLP
|
||||
|
||||
## Pandas Behavioral Analytics
|
||||
|
||||
```python
|
||||
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
|
||||
|
||||
```python
|
||||
patterns = [
|
||||
r"\.pem$", r"\.key$", r"\.env$",
|
||||
r"credentials", r"password", r"\.kdbx$",
|
||||
r"financial", r"payroll", r"customer.*data"
|
||||
]
|
||||
```
|
||||
|
||||
## Microsoft Purview DLP API
|
||||
|
||||
```python
|
||||
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
|
||||
|
||||
- Microsoft Purview DLP: https://learn.microsoft.com/en-us/purview/dlp-learn-about-dlp
|
||||
- pandas: https://pandas.pydata.org/docs/
|
||||
- UEBA: https://www.gartner.com/en/information-technology/glossary/user-entity-behavior-analytics
|
||||
@@ -0,0 +1,183 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Agent for detecting insider data exfiltration via DLP analysis."""
|
||||
|
||||
import os
|
||||
import json
|
||||
import argparse
|
||||
from datetime import datetime
|
||||
|
||||
import pandas as pd
|
||||
import numpy as np
|
||||
|
||||
|
||||
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()
|
||||
Reference in New Issue
Block a user