mirror of
https://github.com/mukul975/Anthropic-Cybersecurity-Skills.git
synced 2026-06-12 06:04: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
122 lines
4.6 KiB
Python
122 lines
4.6 KiB
Python
#!/usr/bin/env python3
|
|
"""Agent for detecting and testing AD CS ESC1 misconfiguration (enrollee supplies SAN)."""
|
|
|
|
import argparse
|
|
import json
|
|
import subprocess
|
|
from datetime import datetime, timezone
|
|
|
|
|
|
def enumerate_certificate_templates():
|
|
"""Enumerate AD CS certificate templates via certutil or Certipy."""
|
|
templates = []
|
|
try:
|
|
result = subprocess.check_output(
|
|
["certutil", "-v", "-template"],
|
|
text=True, errors="replace", timeout=30
|
|
)
|
|
current = {}
|
|
for line in result.splitlines():
|
|
line = line.strip()
|
|
if line.startswith("Template["):
|
|
if current:
|
|
templates.append(current)
|
|
current = {"raw_lines": []}
|
|
if ":" in line:
|
|
key, _, val = line.partition(":")
|
|
current[key.strip()] = val.strip()
|
|
if current:
|
|
current["raw_lines"].append(line)
|
|
if current:
|
|
templates.append(current)
|
|
except (subprocess.SubprocessError, FileNotFoundError):
|
|
pass
|
|
return templates
|
|
|
|
|
|
def check_esc1_vulnerable(template):
|
|
"""Check if a certificate template is vulnerable to ESC1."""
|
|
indicators = []
|
|
raw = "\n".join(template.get("raw_lines", []))
|
|
if "CT_FLAG_ENROLLEE_SUPPLIES_SUBJECT" in raw or "ENROLLEE_SUPPLIES_SUBJECT" in raw:
|
|
indicators.append("Enrollee can supply Subject Alternative Name (SAN)")
|
|
if "Client Authentication" in raw or "1.3.6.1.5.5.7.3.2" in raw:
|
|
indicators.append("Template allows Client Authentication EKU")
|
|
if "Domain Users" in raw or "Authenticated Users" in raw:
|
|
indicators.append("Low-privileged users can enroll")
|
|
if "Manager approval" not in raw and "manager approval" not in raw.lower():
|
|
indicators.append("No manager approval required")
|
|
return indicators
|
|
|
|
|
|
def run_certipy_find(domain, username, password, dc_ip):
|
|
"""Run Certipy to find vulnerable certificate templates."""
|
|
findings = []
|
|
try:
|
|
result = subprocess.check_output(
|
|
["certipy", "find", "-u", f"{username}@{domain}",
|
|
"-p", password, "-dc-ip", dc_ip, "-vulnerable", "-json"],
|
|
text=True, errors="replace", timeout=60
|
|
)
|
|
data = json.loads(result)
|
|
for tmpl in data.get("Certificate Templates", []):
|
|
if "ESC1" in str(tmpl.get("Vulnerabilities", [])):
|
|
findings.append({
|
|
"template": tmpl.get("Template Name", ""),
|
|
"vulnerability": "ESC1",
|
|
"enrollable_by": tmpl.get("Enrollment Rights", []),
|
|
})
|
|
except (subprocess.SubprocessError, json.JSONDecodeError, FileNotFoundError):
|
|
pass
|
|
return findings
|
|
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser(
|
|
description="Detect AD CS ESC1 vulnerability (authorized pentesting only)"
|
|
)
|
|
parser.add_argument("--certutil", action="store_true", help="Use certutil enumeration")
|
|
parser.add_argument("--certipy", action="store_true", help="Use Certipy tool")
|
|
parser.add_argument("--domain", help="AD domain name")
|
|
parser.add_argument("--username", help="Domain username")
|
|
parser.add_argument("--password", help="Domain password")
|
|
parser.add_argument("--dc-ip", help="Domain controller IP")
|
|
parser.add_argument("--output", "-o", help="Output JSON report")
|
|
args = parser.parse_args()
|
|
|
|
print("[*] AD CS ESC1 Vulnerability Detection Agent")
|
|
print("[!] For authorized security testing only")
|
|
report = {"timestamp": datetime.now(timezone.utc).isoformat(), "findings": []}
|
|
|
|
if args.certutil:
|
|
templates = enumerate_certificate_templates()
|
|
for tmpl in templates:
|
|
vulns = check_esc1_vulnerable(tmpl)
|
|
if vulns:
|
|
report["findings"].append({
|
|
"template": tmpl.get("Template", "Unknown"),
|
|
"esc1_indicators": vulns,
|
|
"indicator_count": len(vulns),
|
|
})
|
|
print(f"[*] Templates analyzed: {len(templates)}, ESC1 vulnerable: {len(report['findings'])}")
|
|
|
|
if args.certipy and args.domain:
|
|
certipy_results = run_certipy_find(
|
|
args.domain, args.username or "", args.password or "", args.dc_ip or ""
|
|
)
|
|
report["findings"].extend(certipy_results)
|
|
print(f"[*] Certipy findings: {len(certipy_results)}")
|
|
|
|
report["risk_level"] = "CRITICAL" if report["findings"] else "LOW"
|
|
|
|
if args.output:
|
|
with open(args.output, "w") as f:
|
|
json.dump(report, f, indent=2)
|
|
print(f"[*] Report saved to {args.output}")
|
|
else:
|
|
print(json.dumps(report, indent=2))
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|