mirror of
https://github.com/mukul975/Anthropic-Cybersecurity-Skills.git
synced 2026-08-11 12:53:19 +03:00
Initial commit - 611 cybersecurity skills across all subdomains
This commit is contained in:
@@ -0,0 +1,85 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Pass-the-Hash Detection - Analyzes authentication logs for NTLM-based lateral movement patterns."""
|
||||
|
||||
import json, csv, argparse, datetime, re
|
||||
from collections import defaultdict
|
||||
from pathlib import Path
|
||||
|
||||
SYSTEM_ACCOUNTS = {"system", "anonymous logon", "anonymous", "local service", "network service"}
|
||||
|
||||
def parse_logs(path):
|
||||
p = Path(path)
|
||||
if p.suffix == ".json":
|
||||
with open(p, encoding="utf-8") as f:
|
||||
data = json.load(f)
|
||||
return data if isinstance(data, list) else data.get("events", [])
|
||||
elif p.suffix == ".csv":
|
||||
with open(p, encoding="utf-8-sig") as f:
|
||||
return [dict(r) for r in csv.DictReader(f)]
|
||||
return []
|
||||
|
||||
def detect_pth(event):
|
||||
eid = str(event.get("EventCode", event.get("EventID", "")))
|
||||
if eid != "4624": return None
|
||||
logon_type = str(event.get("Logon_Type", event.get("LogonType", "")))
|
||||
if logon_type != "3": return None
|
||||
auth_pkg = event.get("Authentication_Package", event.get("AuthenticationPackageName", "")).lower()
|
||||
if "ntlm" not in auth_pkg: return None
|
||||
account = event.get("Account_Name", event.get("TargetUserName", "")).lower()
|
||||
if account in SYSTEM_ACCOUNTS or account.endswith("$"): return None
|
||||
src_ip = event.get("Source_Network_Address", event.get("IpAddress", ""))
|
||||
if not src_ip or src_ip in ("-", "::1", "127.0.0.1"): return None
|
||||
return {
|
||||
"technique": "T1550.002",
|
||||
"account": event.get("Account_Name", event.get("TargetUserName", "")),
|
||||
"source_ip": src_ip,
|
||||
"dest_host": event.get("Computer", event.get("hostname", "")),
|
||||
"auth_package": auth_pkg,
|
||||
"logon_process": event.get("Logon_Process", event.get("LogonProcessName", "")),
|
||||
"timestamp": event.get("_time", event.get("timestamp", "")),
|
||||
"risk_score": 45,
|
||||
"risk_level": "MEDIUM",
|
||||
"indicators": ["Type 3 NTLM logon - potential Pass-the-Hash"],
|
||||
}
|
||||
|
||||
def analyze_velocity(findings, threshold=3):
|
||||
account_dests = defaultdict(set)
|
||||
for f in findings:
|
||||
account_dests[f["account"]].add(f["dest_host"])
|
||||
alerts = []
|
||||
for acct, dests in account_dests.items():
|
||||
if len(dests) >= threshold:
|
||||
alerts.append({
|
||||
"technique": "T1550.002", "account": acct,
|
||||
"unique_targets": len(dests), "targets": list(dests),
|
||||
"risk_score": 80, "risk_level": "CRITICAL",
|
||||
"indicators": [f"NTLM auth to {len(dests)} hosts - PtH spray pattern"],
|
||||
})
|
||||
return alerts
|
||||
|
||||
def run_hunt(input_path, output_dir):
|
||||
print(f"[*] Pass-the-Hash Hunt - {datetime.datetime.now().isoformat()}")
|
||||
events = parse_logs(input_path)
|
||||
findings = [f for f in (detect_pth(e) for e in events) if f]
|
||||
velocity = analyze_velocity(findings)
|
||||
all_findings = findings + velocity
|
||||
Path(output_dir).mkdir(parents=True, exist_ok=True)
|
||||
with open(Path(output_dir) / "pth_findings.json", "w", encoding="utf-8") as f:
|
||||
json.dump({"hunt_id": f"TH-PTH-{datetime.date.today()}", "findings": all_findings}, f, indent=2)
|
||||
print(f"[+] {len(all_findings)} findings ({len(velocity)} velocity alerts)")
|
||||
|
||||
def main():
|
||||
p = argparse.ArgumentParser(description="Pass-the-Hash Detection")
|
||||
sp = p.add_subparsers(dest="cmd")
|
||||
h = sp.add_parser("hunt"); h.add_argument("--input", "-i", required=True); h.add_argument("--output", "-o", default="./pth_output")
|
||||
sp.add_parser("queries")
|
||||
args = p.parse_args()
|
||||
if args.cmd == "hunt": run_hunt(args.input, args.output)
|
||||
elif args.cmd == "queries":
|
||||
print("=== Splunk PtH Query ===")
|
||||
print('''index=wineventlog EventCode=4624 Logon_Type=3 Authentication_Package=NTLM
|
||||
| stats count dc(Computer) as targets by Account_Name Source_Network_Address
|
||||
| where targets > 3 | sort -targets''')
|
||||
else: p.print_help()
|
||||
|
||||
if __name__ == "__main__": main()
|
||||
Reference in New Issue
Block a user