Install this skill
npx skills add mukul975/Anthropic-Cybersecurity-SkillsFramework mappings
MITRE ATT&CK
T1003 on the official MITRE ATT&CK siteT1046 on the official MITRE ATT&CK siteT1057 on the official MITRE ATT&CK siteT1082 on the official MITRE ATT&CK siteT1083 on the official MITRE ATT&CK siteT1558 on the official MITRE ATT&CK siteT1558.001 on the official MITRE ATT&CK siteT1558.003 on the official MITRE ATT&CK siteT1558.004 on the official MITRE ATT&CK site
NIST CSF 2.0
MITRE D3FEND
Application Protocol Command Analysis on the official MITRE D3FEND siteClient-server Payload Profiling on the official MITRE D3FEND siteNetwork Isolation on the official MITRE D3FEND siteNetwork Traffic Analysis on the official MITRE D3FEND siteNetwork Traffic Community Deviation on the official MITRE D3FEND site
When to Use
- When proactively hunting for indicators of detecting kerberoasting attacks in the environment
- After threat intelligence indicates active campaigns using these techniques
- During incident response to scope compromise related to these techniques
- When EDR or SIEM alerts trigger on related indicators
- During periodic security assessments and purple team exercises
Prerequisites
- EDR platform with process and network telemetry (CrowdStrike, MDE, SentinelOne)
- SIEM with relevant log data ingested (Splunk, Elastic, Sentinel)
- Sysmon deployed with comprehensive configuration
- Windows Security Event Log forwarding enabled
- Threat intelligence feeds for IOC correlation
Workflow
- Formulate Hypothesis: Define a testable hypothesis based on threat intelligence or ATT&CK gap analysis.
- Identify Data Sources: Determine which logs and telemetry are needed to validate or refute the hypothesis.
- Execute Queries: Run detection queries against SIEM and EDR platforms to collect relevant events.
- Analyze Results: Examine query results for anomalies, correlating across multiple data sources.
- Validate Findings: Distinguish true positives from false positives through contextual analysis.
- Correlate Activity: Link findings to broader attack chains and threat actor TTPs.
- Document and Report: Record findings, update detection rules, and recommend response actions.
Key Concepts
| Concept | Description |
|---|---|
| T1558.003 | Kerberoasting |
| T1558.004 | AS-REP Roasting |
| T1558.001 | Golden Ticket |
Tools & Systems
| Tool | Purpose |
|---|---|
| CrowdStrike Falcon | EDR telemetry and threat detection |
| Microsoft Defender for Endpoint | Advanced hunting with KQL |
| Splunk Enterprise | SIEM log analysis with SPL queries |
| Elastic Security | Detection rules and investigation timeline |
| Sysmon | Detailed Windows event monitoring |
| Velociraptor | Endpoint artifact collection and hunting |
| Sigma Rules | Cross-platform detection rule format |
Common Scenarios
- Scenario 1: Rubeus kerberoast targeting all SPN accounts
- Scenario 2: GetUserSPNs.py from Impacket requesting RC4 tickets
- Scenario 3: Targeted kerberoast against high-privilege service accounts
- Scenario 4: AS-REP roasting accounts without pre-authentication
Output Format
Hunt ID: TH-DETECT-[DATE]-[SEQ]
Technique: T1558.003
Host: [Hostname]
User: [Account context]
Evidence: [Log entries, process trees, network data]
Risk Level: [Critical/High/Medium/Low]
Confidence: [High/Medium/Low]
Recommended Action: [Containment, investigation, monitoring]Source materials
References and resources
Everything below is rendered for inspection. Script files are read-only and never run.
References 3
api-reference.md1.4 KB
API Reference: Detecting Kerberoasting Attacks
python-evtx Library
from Evtx.Evtx import FileHeader
with open("Security.evtx", "rb") as f:
fh = FileHeader(f)
for record in fh.records():
xml_string = record.xml()Event ID 4769 - Kerberos TGS Request
<EventData>
<Data Name="TargetUserName">svc_sql</Data>
<Data Name="ServiceName">MSSQLSvc/db01.corp.local:1433</Data>
<Data Name="TicketEncryptionType">0x17</Data>
<Data Name="TicketOptions">0x40810000</Data>
<Data Name="IpAddress">::ffff:10.0.0.50</Data>
<Data Name="Status">0x0</Data>
</EventData>Encryption Type Values
| Hex | Type | Risk |
|---|---|---|
| 0x17 | RC4-HMAC | Kerberoasting indicator |
| 0x18 | RC4-HMAC-EXP | Kerberoasting indicator |
| 0x11 | AES128-CTS-HMAC-SHA1 | Normal |
| 0x12 | AES256-CTS-HMAC-SHA1 | Normal |
Detection Logic
- Filter Event 4769 where TicketEncryptionType = 0x17 (RC4)
- Exclude machine accounts (ServiceName ending in
$) - Exclude krbtgt service
- Alert on high-volume TGS from single source (>10 unique SPNs in 5 min)
- Correlate with Event 4624 for source attribution
Event ID 4624 - Logon Event (Correlation)
<Data Name="TargetUserName">attacker_user</Data>
<Data Name="LogonType">3</Data>
<Data Name="IpAddress">10.0.0.50</Data>
<Data Name="WorkstationName">WORKSTATION1</Data>MITRE ATT&CK Mapping
- T1558.003 - Kerberoasting
- T1558 - Steal or Forge Kerberos Tickets
standards.md1.5 KB
Standards and References - Detecting Kerberoasting Attacks
MITRE ATT&CK Mappings
| Technique | Name | Description |
|---|---|---|
| T1558.003 | Kerberoasting | See attack.mitre.org/techniques/T1558/003 |
| T1558.004 | AS-REP Roasting | See attack.mitre.org/techniques/T1558/004 |
| T1558.001 | Golden Ticket | See attack.mitre.org/techniques/T1558/001 |
Detection Data Sources
| Source | Event ID | Purpose |
|---|---|---|
| Sysmon | 1 | Process creation with command line |
| Sysmon | 3 | Network connection initiated |
| Sysmon | 7 | Image loaded (DLL) |
| Sysmon | 10 | Process access (LSASS) |
| Sysmon | 11 | File creation |
| Sysmon | 12/13 | Registry create/set |
| Sysmon | 22 | DNS query |
| Sysmon | 25 | Process tampering |
| Windows Security | 4624 | Successful logon |
| Windows Security | 4625 | Failed logon |
| Windows Security | 4648 | Explicit credential logon |
| Windows Security | 4672 | Special privileges assigned |
| Windows Security | 4688 | Process creation |
| Windows Security | 4697 | Service installed |
| Windows Security | 4698 | Scheduled task created |
| Windows Security | 4769 | Kerberos TGS requested |
| Windows Security | 5140 | Network share accessed |
References
- MITRE ATT&CK Framework: https://attack.mitre.org/
- Sigma Detection Rules: https://github.com/SigmaHQ/sigma
- LOLBAS Project: https://lolbas-project.github.io/
- Atomic Red Team Tests: https://github.com/redcanaryco/atomic-red-team
- Red Canary Threat Detection Report
- SANS Threat Hunting Summit Resources
workflows.md2.9 KB
Detailed Hunting Workflow - Detecting Kerberoasting Attacks
Phase 1: Data Collection and Querying
Splunk SPL Query
index=wineventlog EventCode=4769 Ticket_Encryption_Type=0x17
| where Service_Name!="krbtgt" AND NOT match(Service_Name, "\\$")
| stats count dc(Service_Name) as unique_services by Account_Name Client_Address
| where unique_services > 5
| sort -unique_servicesKQL Query (Microsoft Defender for Endpoint)
SecurityEvent
| where EventID == 4769
| where TicketEncryptionType == "0x17"
| where ServiceName !endswith "$" and ServiceName != "krbtgt"
| summarize ServiceCount=dcount(ServiceName), Services=make_set(ServiceName) by SubjectUserName, IpAddress
| where ServiceCount > 5Phase 2: Baseline and Anomaly Detection
Step 2.1 - Establish Normal Behavior Baseline
- Collect 30 days of historical data for the targeted technique
- Document expected patterns, frequencies, and legitimate use cases
- Identify known false positive sources and document exceptions
- Build statistical baseline (mean, standard deviation) for key metrics
Step 2.2 - Identify Anomalies
- Compare current activity against the 30-day baseline
- Flag events exceeding 3 standard deviations from normal
- Prioritize anomalies by risk score and potential business impact
- Cross-reference with threat intelligence for known IOCs
Phase 3: Investigation and Correlation
Step 3.1 - Deep Dive Analysis
- For each anomaly, collect full process tree context
- Correlate with network activity, file operations, and authentication events
- Check binary signatures, file hashes, and certificate validity
- Review user account context and access patterns
Step 3.2 - Attack Chain Reconstruction
- Map findings to MITRE ATT&CK kill chain stages
- Identify initial access vector if applicable
- Trace lateral movement and privilege escalation paths
- Determine data access and potential exfiltration
Phase 4: Validation and Response
Step 4.1 - True/False Positive Determination
- Verify findings with system owners and IT operations
- Check change management records for authorized activities
- Validate user context (authorized actions vs. compromised account)
- Document determination rationale for each finding
Step 4.2 - Response Actions
- For confirmed threats: initiate incident response procedures
- For detection gaps: create or update detection rules
- For false positives: tune existing rules and update exclusions
- Update threat hunting playbook with lessons learned
Phase 5: Documentation and Reporting
Step 5.1 - Hunt Report
- Summarize hypothesis, methodology, and findings
- Include all queries executed and their results
- Document IOCs discovered and detection rules created
- Provide recommendations for security improvements
Step 5.2 - Knowledge Base Update
- Add findings to threat intelligence platform
- Update MITRE ATT&CK coverage heatmap
- Share detection rules via Sigma format
- Schedule follow-up hunts for related techniques
Scripts 2
agent.py7.6 KB
Display-only source. This catalog never executes bundled scripts.
#!/usr/bin/env python3
"""Kerberoasting Detection Agent - Detects Kerberoasting via Event 4769 TGS-REQ analysis."""
import json
import logging
import argparse
from collections import defaultdict
from datetime import datetime
from Evtx.Evtx import FileHeader
from lxml import etree
logging.basicConfig(level=logging.INFO, format="%(asctime)s [%(levelname)s] %(message)s")
logger = logging.getLogger(__name__)
NS = {"evt": "http://schemas.microsoft.com/win/2004/08/events/event"}
WEAK_ENCRYPTION_TYPES = {"0x17": "RC4-HMAC", "0x18": "RC4-HMAC-EXP"}
STRONG_ENCRYPTION_TYPES = {"0x11": "AES128", "0x12": "AES256"}
def parse_tgs_events(evtx_path):
"""Parse Event ID 4769 (Kerberos TGS requests) from Security EVTX."""
tgs_events = []
with open(evtx_path, "rb") as f:
fh = FileHeader(f)
for record in fh.records():
try:
xml = record.xml()
root = etree.fromstring(xml.encode("utf-8"))
event_id_elem = root.find(".//evt:System/evt:EventID", NS)
if event_id_elem is None or event_id_elem.text != "4769":
continue
data = {}
for elem in root.findall(".//evt:EventData/evt:Data", NS):
data[elem.get("Name", "")] = elem.text or ""
time_elem = root.find(".//evt:System/evt:TimeCreated", NS)
timestamp = time_elem.get("SystemTime", "") if time_elem is not None else ""
tgs_events.append({
"timestamp": timestamp,
"target_name": data.get("TargetUserName", ""),
"service_name": data.get("ServiceName", ""),
"client_address": data.get("IpAddress", ""),
"ticket_encryption": data.get("TicketEncryptionType", ""),
"ticket_options": data.get("TicketOptions", ""),
"status": data.get("Status", ""),
"logon_guid": data.get("LogonGuid", ""),
})
except Exception:
continue
logger.info("Parsed %d TGS-REQ events from %s", len(tgs_events), evtx_path)
return tgs_events
def detect_rc4_tgs_requests(tgs_events):
"""Detect TGS requests using weak RC4-HMAC encryption (Kerberoasting indicator)."""
rc4_requests = []
for event in tgs_events:
enc_type = event["ticket_encryption"]
if enc_type in WEAK_ENCRYPTION_TYPES:
service = event["service_name"]
if service and not service.endswith("$") and "krbtgt" not in service.lower():
event["encryption_name"] = WEAK_ENCRYPTION_TYPES[enc_type]
event["indicator"] = "RC4 TGS for service account (non-machine)"
rc4_requests.append(event)
logger.info("Found %d RC4 TGS requests for service accounts", len(rc4_requests))
return rc4_requests
def detect_high_volume_tgs(tgs_events, threshold=10, window_minutes=5):
"""Detect high-volume TGS requests from a single source (spray pattern)."""
source_buckets = defaultdict(list)
for event in tgs_events:
source_buckets[event["client_address"]].append(event)
alerts = []
for source, events in source_buckets.items():
events.sort(key=lambda e: e["timestamp"])
unique_services = set()
for event in events:
unique_services.add(event["service_name"])
if len(unique_services) >= threshold:
alerts.append({
"source_ip": source,
"unique_services_requested": len(unique_services),
"total_requests": len(events),
"services": list(unique_services)[:20],
"first_seen": events[0]["timestamp"],
"last_seen": events[-1]["timestamp"],
"indicator": "High-volume TGS spray (Kerberoasting)",
})
logger.info("Found %d high-volume TGS sources", len(alerts))
return alerts
def detect_anomalous_spn_requests(tgs_events, known_spns=None):
"""Detect TGS requests for unusual or sensitive SPNs."""
sensitive_spns = {"MSSQLSvc", "HTTP", "MSSQL", "exchangeAB", "CIFS", "HOST"}
anomalous = []
for event in tgs_events:
service = event["service_name"]
service_class = service.split("/")[0] if "/" in service else service
if service_class in sensitive_spns:
enc = event["ticket_encryption"]
if enc in WEAK_ENCRYPTION_TYPES:
event["spn_class"] = service_class
event["risk"] = "Sensitive SPN with RC4 encryption"
anomalous.append(event)
logger.info("Found %d anomalous SPN requests", len(anomalous))
return anomalous
def correlate_with_logon_events(evtx_path, suspicious_sources):
"""Correlate suspicious TGS sources with logon events (4624) for attribution."""
source_ips = {s["source_ip"] for s in suspicious_sources}
logon_map = {}
with open(evtx_path, "rb") as f:
fh = FileHeader(f)
for record in fh.records():
try:
xml = record.xml()
root = etree.fromstring(xml.encode("utf-8"))
event_id_elem = root.find(".//evt:System/evt:EventID", NS)
if event_id_elem is None or event_id_elem.text != "4624":
continue
data = {}
for elem in root.findall(".//evt:EventData/evt:Data", NS):
data[elem.get("Name", "")] = elem.text or ""
source_ip = data.get("IpAddress", "")
if source_ip in source_ips:
logon_map[source_ip] = {
"account": data.get("TargetUserName", ""),
"domain": data.get("TargetDomainName", ""),
"logon_type": data.get("LogonType", ""),
"workstation": data.get("WorkstationName", ""),
}
except Exception:
continue
return logon_map
def generate_report(tgs_events, rc4_findings, spray_findings, spn_findings, logon_correlation):
"""Generate Kerberoasting detection report."""
report = {
"timestamp": datetime.utcnow().isoformat(),
"total_tgs_events": len(tgs_events),
"rc4_service_requests": len(rc4_findings),
"tgs_spray_sources": len(spray_findings),
"anomalous_spn_requests": len(spn_findings),
"rc4_details": rc4_findings[:20],
"spray_details": spray_findings,
"spn_details": spn_findings[:20],
"attacker_attribution": logon_correlation,
}
total_findings = len(rc4_findings) + len(spray_findings) + len(spn_findings)
print(f"KERBEROASTING DETECTION: {total_findings} indicators found")
return report
def main():
parser = argparse.ArgumentParser(description="Kerberoasting Detection Agent")
parser.add_argument("--evtx-file", required=True, help="Path to Security EVTX file")
parser.add_argument("--spray-threshold", type=int, default=10)
parser.add_argument("--output", default="kerberoast_report.json")
args = parser.parse_args()
tgs_events = parse_tgs_events(args.evtx_file)
rc4_findings = detect_rc4_tgs_requests(tgs_events)
spray_findings = detect_high_volume_tgs(tgs_events, args.spray_threshold)
spn_findings = detect_anomalous_spn_requests(tgs_events)
logon_map = correlate_with_logon_events(args.evtx_file, spray_findings)
report = generate_report(tgs_events, rc4_findings, spray_findings, spn_findings, logon_map)
with open(args.output, "w") as f:
json.dump(report, f, indent=2)
logger.info("Report saved to %s", args.output)
if __name__ == "__main__":
main()
process.py3.5 KB
Display-only source. This catalog never executes bundled scripts.
#!/usr/bin/env python3
"""Kerberoasting Detection - Analyzes logs for T1558.003 indicators."""
import json, csv, argparse, datetime, re
from collections import defaultdict
from pathlib import Path
DETECTION_PATTERNS = [
r'Rubeus.*kerberoast',
r'GetUserSPNs',
r'Invoke-Kerberoast',
r'0x17.*Ticket_Encryption_Type',
]
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 analyze_event(event):
cmd = event.get("CommandLine", event.get("command_line", event.get("ProcessCommandLine", "")))
content = event.get("Task_Content", event.get("Parameters", event.get("RawEventData", "")))
search_text = f"{cmd} {content}"
risk = 0
indicators = []
for pattern in DETECTION_PATTERNS:
if re.search(pattern, search_text, re.IGNORECASE):
risk += 25
indicators.append(f"Pattern match: {pattern}")
if not indicators:
return None
risk = min(risk, 100)
return {
"technique": "T1558.003",
"command_line": cmd[:500] if cmd else content[:500],
"hostname": event.get("Computer", event.get("DeviceName", event.get("hostname", "unknown"))),
"user": event.get("User", event.get("AccountName", event.get("UserId", "unknown"))),
"timestamp": event.get("_time", event.get("timestamp", event.get("UtcTime", event.get("Timestamp", "")))),
"risk_score": risk,
"risk_level": "CRITICAL" if risk >= 75 else "HIGH" if risk >= 50 else "MEDIUM" if risk >= 25 else "LOW",
"indicators": indicators,
}
def run_hunt(input_path, output_dir):
print(f"[*] Kerberoasting Hunt - {datetime.datetime.now().isoformat()}")
events = parse_logs(input_path)
findings = [f for f in (analyze_event(e) for e in events) if f]
Path(output_dir).mkdir(parents=True, exist_ok=True)
slug = "detecting_kerberoast"
with open(Path(output_dir) / f"{slug}_findings.json", "w", encoding="utf-8") as f:
json.dump({"hunt_id": f"TH-{datetime.date.today()}", "total_events": len(events), "findings": findings}, f, indent=2)
with open(Path(output_dir) / "hunt_report.md", "w", encoding="utf-8") as f:
f.write(f"# Kerberoasting Hunt Report\n\n")
f.write(f"**Date**: {datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n")
f.write(f"**Findings**: {len(findings)}\n\n")
for finding in sorted(findings, key=lambda x: x["risk_score"], reverse=True)[:20]:
f.write(f"### [{finding['risk_level']}] {finding['technique']}\n")
f.write(f"- **Host**: {finding['hostname']}\n")
f.write(f"- **Indicators**: {', '.join(finding['indicators'])}\n\n")
print(f"[+] {len(findings)} findings written to {output_dir}")
def main():
p = argparse.ArgumentParser(description="Kerberoasting 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="./detecting_kerbe_output")
sp.add_parser("queries")
args = p.parse_args()
if args.cmd == "hunt": run_hunt(args.input, args.output)
elif args.cmd == "queries":
print("=== Detection Queries ===")
print("See references/workflows.md for platform-specific queries")
else: p.print_help()
if __name__ == "__main__": main()
Assets 1
template.mdtext/markdown · 2.6 KBKeep exploring