mirror of
https://github.com/mukul975/Anthropic-Cybersecurity-Skills.git
synced 2026-06-13 06:34:57 +03:00
c47eed6a64
- Fix 25 shell=True subprocess calls with list-based commands - Fix 49 verify=False in defensive skills (env-var override) - Add timeout to 231 HTTP/subprocess/socket calls - Fix 6 SQL injection patterns with whitelist validation - Replace 8 __import__() with standard imports - Remove 701 unused imports across 442 files - Add authorized-testing disclaimers to all offensive skills - Complete 11 incomplete skill directories - Expand 10 stub SKILL.md files with full content - Fix 2 YAML parse errors in frontmatter - Fix 5 pre-existing syntax errors - Convert 22 hardcoded paths/ports to environment variables - Back up 21 redundant skill pairs to .bak - Fix 2 global declaration errors - 724/724 skills with full folder anatomy (SKILL.md + agent.py + api-reference.md + LICENSE) - 0 compile errors across all 724 agent.py files
261 lines
9.2 KiB
Python
261 lines
9.2 KiB
Python
#!/usr/bin/env python3
|
|
"""Decoy file (canary) deployment agent for ransomware detection.
|
|
|
|
Deploys canary files across file systems and monitors them for modifications
|
|
that indicate ransomware encryption activity. Provides real-time alerting
|
|
when decoy files are modified, renamed, or deleted.
|
|
"""
|
|
|
|
import hashlib
|
|
import json
|
|
import logging
|
|
import os
|
|
import sys
|
|
import time
|
|
from datetime import datetime
|
|
|
|
logging.basicConfig(
|
|
level=logging.INFO,
|
|
format="%(asctime)s [%(levelname)s] %(message)s",
|
|
)
|
|
logger = logging.getLogger("canary_agent")
|
|
|
|
CANARY_EXTENSIONS = [".docx", ".xlsx", ".pdf", ".csv", ".sql", ".txt", ".pptx"]
|
|
|
|
CANARY_NAMES_FIRST = [
|
|
"_AAAA_budget_2024", "_AAAA_financial_report", "_AAAA_payroll_data",
|
|
"_AAA_employee_records", "_AAA_client_contracts",
|
|
]
|
|
|
|
CANARY_NAMES_LAST = [
|
|
"~zzzz_annual_review", "~zzzz_backup_config", "~zzzz_tax_returns",
|
|
"~zzz_insurance_claims", "~zzz_merger_docs",
|
|
]
|
|
|
|
RANSOMWARE_EXTENSIONS = {
|
|
".locked", ".encrypted", ".crypt", ".locky", ".cerber", ".wncry",
|
|
".dharma", ".basta", ".blackcat", ".hive", ".royal", ".akira",
|
|
".lockbit", ".conti", ".ryuk", ".maze", ".revil", ".phobos",
|
|
".makop", ".stop", ".djvu", ".rhysida",
|
|
}
|
|
|
|
RANSOM_NOTE_NAMES = {
|
|
"readme.txt", "readme.html", "decrypt.txt", "decrypt.html",
|
|
"how_to_decrypt.txt", "restore_files.txt", "read_me.txt",
|
|
"how_to_recover.txt", "ransom_note.txt",
|
|
}
|
|
|
|
|
|
def compute_file_hash(filepath):
|
|
"""Compute SHA-256 hash of a file."""
|
|
sha256 = hashlib.sha256()
|
|
with open(filepath, "rb") as f:
|
|
for chunk in iter(lambda: f.read(65536), b""):
|
|
sha256.update(chunk)
|
|
return sha256.hexdigest()
|
|
|
|
|
|
def generate_canary_content(canary_type, name):
|
|
"""Generate realistic content for canary files."""
|
|
timestamp = datetime.now().isoformat()
|
|
content = f"CANARY_TOKEN:{name}\n"
|
|
content += f"Generated: {timestamp}\n"
|
|
content += f"Classification: CONFIDENTIAL\n\n"
|
|
|
|
if "budget" in name or "financial" in name:
|
|
content += "Q4 Financial Summary\n"
|
|
content += "Total Revenue: $12,450,000\n"
|
|
content += "Operating Expenses: $8,230,000\n"
|
|
content += "Net Income: $4,220,000\n"
|
|
elif "payroll" in name or "employee" in name:
|
|
content += "Employee Records - Human Resources\n"
|
|
content += "Total Headcount: 342\n"
|
|
content += "Departments: Engineering, Sales, Marketing, Operations\n"
|
|
elif "client" in name or "contract" in name:
|
|
content += "Client Contract Summary\n"
|
|
content += "Active Contracts: 156\n"
|
|
content += "Pending Renewal: 23\n"
|
|
else:
|
|
content += "Internal Document - Do Not Distribute\n"
|
|
content += "This document contains sensitive business information.\n"
|
|
|
|
return content
|
|
|
|
|
|
def deploy_canaries(target_dirs, canaries_per_dir=4):
|
|
"""Deploy canary files to target directories."""
|
|
deployed = []
|
|
names = CANARY_NAMES_FIRST[:canaries_per_dir // 2] + CANARY_NAMES_LAST[:canaries_per_dir // 2]
|
|
|
|
for target_dir in target_dirs:
|
|
if not os.path.isdir(target_dir):
|
|
logger.warning("Directory does not exist: %s", target_dir)
|
|
continue
|
|
|
|
for i, name in enumerate(names):
|
|
ext = CANARY_EXTENSIONS[i % len(CANARY_EXTENSIONS)]
|
|
filename = f"{name}{ext}"
|
|
filepath = os.path.join(target_dir, filename)
|
|
|
|
content = generate_canary_content(ext, name)
|
|
with open(filepath, "w") as f:
|
|
f.write(content)
|
|
|
|
file_hash = compute_file_hash(filepath)
|
|
record = {
|
|
"path": filepath,
|
|
"hash": file_hash,
|
|
"size": os.path.getsize(filepath),
|
|
"deployed_at": datetime.now().isoformat(),
|
|
"name": filename,
|
|
}
|
|
deployed.append(record)
|
|
logger.info("Deployed canary: %s (hash: %s)", filepath, file_hash[:16])
|
|
|
|
return deployed
|
|
|
|
|
|
def check_canary_integrity(canary_records):
|
|
"""Check all canary files for modifications, deletions, or renames."""
|
|
alerts = []
|
|
|
|
for record in canary_records:
|
|
filepath = record["path"]
|
|
|
|
if not os.path.exists(filepath):
|
|
# Check if file was renamed with ransomware extension
|
|
parent_dir = os.path.dirname(filepath)
|
|
basename = os.path.basename(filepath)
|
|
renamed = False
|
|
if os.path.isdir(parent_dir):
|
|
for f in os.listdir(parent_dir):
|
|
if f.startswith(basename) and any(f.endswith(ext) for ext in RANSOMWARE_EXTENSIONS):
|
|
alerts.append({
|
|
"type": "RANSOMWARE_RENAME",
|
|
"severity": "CRITICAL",
|
|
"original": filepath,
|
|
"renamed_to": os.path.join(parent_dir, f),
|
|
"timestamp": datetime.now().isoformat(),
|
|
})
|
|
renamed = True
|
|
break
|
|
|
|
if not renamed:
|
|
alerts.append({
|
|
"type": "CANARY_DELETED",
|
|
"severity": "HIGH",
|
|
"path": filepath,
|
|
"timestamp": datetime.now().isoformat(),
|
|
})
|
|
continue
|
|
|
|
current_hash = compute_file_hash(filepath)
|
|
if current_hash != record["hash"]:
|
|
alerts.append({
|
|
"type": "CANARY_MODIFIED",
|
|
"severity": "CRITICAL",
|
|
"path": filepath,
|
|
"original_hash": record["hash"],
|
|
"current_hash": current_hash,
|
|
"timestamp": datetime.now().isoformat(),
|
|
})
|
|
|
|
current_size = os.path.getsize(filepath)
|
|
if abs(current_size - record["size"]) > record["size"] * 0.5:
|
|
alerts.append({
|
|
"type": "SIGNIFICANT_SIZE_CHANGE",
|
|
"severity": "HIGH",
|
|
"path": filepath,
|
|
"original_size": record["size"],
|
|
"current_size": current_size,
|
|
"timestamp": datetime.now().isoformat(),
|
|
})
|
|
|
|
# Check for ransom notes in canary directories
|
|
checked_dirs = set()
|
|
for record in canary_records:
|
|
parent_dir = os.path.dirname(record["path"])
|
|
if parent_dir in checked_dirs or not os.path.isdir(parent_dir):
|
|
continue
|
|
checked_dirs.add(parent_dir)
|
|
for f in os.listdir(parent_dir):
|
|
if f.lower() in RANSOM_NOTE_NAMES:
|
|
alerts.append({
|
|
"type": "RANSOM_NOTE_DETECTED",
|
|
"severity": "CRITICAL",
|
|
"path": os.path.join(parent_dir, f),
|
|
"timestamp": datetime.now().isoformat(),
|
|
})
|
|
|
|
return alerts
|
|
|
|
|
|
def monitor_loop(canary_records, interval=10):
|
|
"""Continuously monitor canary files at specified interval."""
|
|
logger.info("Starting canary monitoring loop (interval: %ds)", interval)
|
|
logger.info("Monitoring %d canary files", len(canary_records))
|
|
|
|
while True:
|
|
alerts = check_canary_integrity(canary_records)
|
|
if alerts:
|
|
for alert in alerts:
|
|
logger.critical(
|
|
"ALERT [%s] %s: %s",
|
|
alert["severity"],
|
|
alert["type"],
|
|
alert.get("path", alert.get("original", "unknown")),
|
|
)
|
|
print(json.dumps({"alerts": alerts}, indent=2))
|
|
time.sleep(interval)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
print("=" * 60)
|
|
print("Ransomware Canary File Deployment Agent")
|
|
print("Deploy and monitor decoy files for encryption detection")
|
|
print("=" * 60)
|
|
|
|
if len(sys.argv) < 2:
|
|
print("\nUsage:")
|
|
print(" python agent.py deploy <dir1> [dir2] ... Deploy canaries")
|
|
print(" python agent.py check <registry.json> Check canary integrity")
|
|
print(" python agent.py monitor <registry.json> Continuous monitoring")
|
|
sys.exit(0)
|
|
|
|
command = sys.argv[1]
|
|
|
|
if command == "deploy":
|
|
dirs = sys.argv[2:] if len(sys.argv) > 2 else [os.getcwd()]
|
|
records = deploy_canaries(dirs)
|
|
registry_file = "canary_registry.json"
|
|
with open(registry_file, "w") as f:
|
|
json.dump(records, f, indent=2)
|
|
print(f"\n[+] Deployed {len(records)} canary files across {len(dirs)} directories")
|
|
print(f"[+] Registry saved to: {registry_file}")
|
|
|
|
elif command == "check":
|
|
if len(sys.argv) < 3:
|
|
print("[!] Provide canary registry JSON file")
|
|
sys.exit(1)
|
|
with open(sys.argv[2]) as f:
|
|
records = json.load(f)
|
|
alerts = check_canary_integrity(records)
|
|
if alerts:
|
|
print(f"\n[!] {len(alerts)} ALERTS DETECTED:")
|
|
for a in alerts:
|
|
print(f" [{a['severity']}] {a['type']}: {a.get('path', a.get('original'))}")
|
|
else:
|
|
print(f"\n[+] All {len(records)} canary files intact. No alerts.")
|
|
|
|
elif command == "monitor":
|
|
if len(sys.argv) < 3:
|
|
print("[!] Provide canary registry JSON file")
|
|
sys.exit(1)
|
|
with open(sys.argv[2]) as f:
|
|
records = json.load(f)
|
|
interval = int(sys.argv[3]) if len(sys.argv) > 3 else 10
|
|
monitor_loop(records, interval)
|
|
|
|
else:
|
|
print(f"[!] Unknown command: {command}")
|