mirror of
https://github.com/mukul975/Anthropic-Cybersecurity-Skills.git
synced 2026-06-11 21:54:56 +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
143 lines
5.5 KiB
Python
143 lines
5.5 KiB
Python
#!/usr/bin/env python3
|
|
# For authorized penetration testing and educational environments only.
|
|
# Usage against targets without prior mutual consent is illegal.
|
|
# It is the end user's responsibility to obey all applicable local, state and federal laws.
|
|
"""Pass-the-Ticket attack detection agent using Windows event log analysis."""
|
|
|
|
import json
|
|
import argparse
|
|
from datetime import datetime
|
|
|
|
|
|
def detect_ptt_events(log_file):
|
|
"""Analyze Windows Security logs for Pass-the-Ticket indicators."""
|
|
detections = []
|
|
try:
|
|
with open(log_file, "r") as f:
|
|
events = json.load(f)
|
|
except (FileNotFoundError, json.JSONDecodeError) as e:
|
|
return [{"error": str(e)}]
|
|
|
|
for event in events:
|
|
eid = str(event.get("EventID", ""))
|
|
if eid == "4768":
|
|
if event.get("TicketEncryptionType") == "0x17":
|
|
detections.append({
|
|
"event_id": eid,
|
|
"type": "TGT_request_rc4",
|
|
"account": event.get("TargetUserName", ""),
|
|
"source_ip": event.get("IpAddress", ""),
|
|
"severity": "HIGH",
|
|
"note": "RC4 TGT request may indicate golden ticket",
|
|
})
|
|
elif eid == "4769":
|
|
if event.get("TicketEncryptionType") == "0x17":
|
|
detections.append({
|
|
"event_id": eid,
|
|
"type": "service_ticket_rc4",
|
|
"account": event.get("TargetUserName", ""),
|
|
"service": event.get("ServiceName", ""),
|
|
"severity": "MEDIUM",
|
|
"note": "RC4 service ticket — potential Kerberoasting or PTT",
|
|
})
|
|
elif eid == "4624":
|
|
if event.get("LogonType") == "3" and event.get("AuthenticationPackageName") == "Kerberos":
|
|
source = event.get("IpAddress", "")
|
|
detections.append({
|
|
"event_id": eid,
|
|
"type": "network_logon_kerberos",
|
|
"account": event.get("TargetUserName", ""),
|
|
"source_ip": source,
|
|
"severity": "INFO",
|
|
"note": "Kerberos network logon — correlate with TGT anomalies",
|
|
})
|
|
return detections
|
|
|
|
|
|
def generate_sigma_rules():
|
|
"""Generate Sigma detection rules for Pass-the-Ticket."""
|
|
rules = [
|
|
{
|
|
"title": "Pass-the-Ticket via RC4 Encryption Downgrade",
|
|
"logsource": {"product": "windows", "service": "security"},
|
|
"detection": {
|
|
"selection": {"EventID": [4768, 4769], "TicketEncryptionType": "0x17"},
|
|
"condition": "selection",
|
|
},
|
|
"level": "high",
|
|
"tags": ["attack.lateral_movement", "attack.t1550.003"],
|
|
},
|
|
{
|
|
"title": "Anomalous Kerberos TGT Request from Non-Domain Controller",
|
|
"logsource": {"product": "windows", "service": "security"},
|
|
"detection": {
|
|
"selection": {"EventID": 4768},
|
|
"filter": {"IpAddress|startswith": ["::1", "127."]},
|
|
"condition": "selection and not filter",
|
|
},
|
|
"level": "medium",
|
|
"tags": ["attack.credential_access", "attack.t1558"],
|
|
},
|
|
]
|
|
return rules
|
|
|
|
|
|
def generate_hunt_queries():
|
|
"""Generate threat hunting queries for PTT detection."""
|
|
return {
|
|
"splunk": [
|
|
'index=wineventlog EventCode=4768 TicketEncryptionType=0x17 | stats count by Account_Name, src_ip',
|
|
'index=wineventlog EventCode=4769 ServiceName!="krbtgt" TicketEncryptionType=0x17 | table _time Account_Name ServiceName',
|
|
],
|
|
"kql": [
|
|
'SecurityEvent | where EventID == 4768 | where TicketEncryptionType == "0x17" | summarize count() by TargetAccount, IpAddress',
|
|
'SecurityEvent | where EventID == 4769 | where TicketEncryptionType == "0x17" | project TimeGenerated, TargetAccount, ServiceName',
|
|
],
|
|
}
|
|
|
|
|
|
def run_detection(log_file=None):
|
|
"""Execute Pass-the-Ticket detection analysis."""
|
|
print(f"\n{'='*60}")
|
|
print(f" PASS-THE-TICKET DETECTION ANALYSIS")
|
|
print(f" Generated: {datetime.utcnow().isoformat()} UTC")
|
|
print(f"{'='*60}\n")
|
|
|
|
if log_file:
|
|
events = detect_ptt_events(log_file)
|
|
print(f"--- EVENT ANALYSIS ({len(events)} detections) ---")
|
|
for e in events[:15]:
|
|
if "error" not in e:
|
|
print(f" [{e['severity']}] {e['type']}: {e.get('account', 'N/A')} from {e.get('source_ip', 'N/A')}")
|
|
|
|
rules = generate_sigma_rules()
|
|
print(f"\n--- SIGMA RULES ({len(rules)}) ---")
|
|
for r in rules:
|
|
print(f" [{r['level'].upper()}] {r['title']}")
|
|
|
|
queries = generate_hunt_queries()
|
|
print(f"\n--- HUNT QUERIES ---")
|
|
for platform, qlist in queries.items():
|
|
print(f" {platform.upper()}:")
|
|
for q in qlist:
|
|
print(f" {q[:80]}...")
|
|
|
|
return {"detections": events if log_file else [], "sigma_rules": rules, "hunt_queries": queries}
|
|
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser(description="Pass-the-Ticket Detection Agent")
|
|
parser.add_argument("--log-file", help="Windows event log JSON export")
|
|
parser.add_argument("--output", help="Save report to JSON file")
|
|
args = parser.parse_args()
|
|
|
|
report = run_detection(args.log_file)
|
|
if args.output:
|
|
with open(args.output, "w") as f:
|
|
json.dump(report, f, indent=2, default=str)
|
|
print(f"\n[+] Report saved to {args.output}")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|