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 siteT1078 on the official MITRE ATT&CK siteT1082 on the official MITRE ATT&CK siteT1083 on the official MITRE ATT&CK siteT1550 on the official MITRE ATT&CK siteT1550.002 on the official MITRE ATT&CK siteT1550.003 on the official MITRE ATT&CK site
NIST CSF 2.0
When to Use
- When proactively hunting for indicators of detecting pass the hash 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 |
|---|---|
| T1550.002 | Pass the Hash |
| T1550.003 | Pass the Ticket |
| T1078 | Valid Accounts |
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: Mimikatz sekurlsa::pth with stolen NTLM hash
- Scenario 2: Impacket psexec.py remote execution with hash
- Scenario 3: CrackMapExec hash spraying across hosts
- Scenario 4: WMI lateral movement via pass-the-hash
Output Format
Hunt ID: TH-DETECT-[DATE]-[SEQ]
Technique: T1550.002
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.5 KB
API Reference: Detecting Pass-the-Hash Attacks
Windows Event ID 4624 Fields
| Field | PtH Signal |
|---|---|
| LogonType | 3 (Network) |
| AuthenticationPackageName | NTLM (not Kerberos) |
| LogonProcessName | NtLmSsp |
| IpAddress | Source of authentication |
| TargetUserName | Account being used |
python-evtx Usage
import Evtx.Evtx as evtx
with evtx.Evtx("Security.evtx") as log:
for record in log.records():
xml = record.xml()
# Filter EventID 4624, LogonType=3, AuthPackage=NTLMPtH Detection Logic
src_targets = defaultdict(set)
for event in ntlm_logons:
src_targets[event["source_ip"]].add(event["computer"])
# Alert when single source authenticates to 3+ targets via NTLMSplunk SPL Detection
index=wineventlog EventCode=4624 Logon_Type=3
| where Authentication_Package="NTLM"
| stats dc(Computer) as targets by Source_Network_Address, Account_Name
| where targets >= 3
| sort -targetsKQL (Microsoft Sentinel)
SecurityEvent
| where EventID == 4624 and LogonType == 3
| where AuthenticationPackageName == "NTLM"
| summarize TargetCount=dcount(Computer) by IpAddress, TargetUserName
| where TargetCount >= 3Mitigation
# Restrict NTLM authentication
Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\Lsa" -Name "RestrictSendingNTLMTraffic" -Value 2CLI Usage
python agent.py --security-log Security.evtx
python agent.py --security-log Security.evtx --target-threshold 5standards.md1.5 KB
Standards and References - Detecting Pass The Hash Attacks
MITRE ATT&CK Mappings
| Technique | Name | Description |
|---|---|---|
| T1550.002 | Pass the Hash | See attack.mitre.org/techniques/T1550/002 |
| T1550.003 | Pass the Ticket | See attack.mitre.org/techniques/T1550/003 |
| T1078 | Valid Accounts | See attack.mitre.org/techniques/T1078 |
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 Pass The Hash Attacks
Phase 1: Data Collection and Querying
Splunk SPL Query
index=wineventlog EventCode=4624 Logon_Type=3 Authentication_Package=NTLM
| where NOT match(Account_Name, "(?i)(ANONYMOUS|\\$|SYSTEM)")
| stats count dc(Computer) as targets by Account_Name Source_Network_Address
| where targets > 3
| sort -targetsKQL Query (Microsoft Defender for Endpoint)
SecurityEvent
| where EventID == 4624 and LogonType == 3
| where AuthenticationPackageName == "NTLM"
| summarize TargetCount=dcount(Computer) by SubjectUserName, IpAddress
| where TargetCount > 3Phase 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.py4.3 KB
Display-only source. This catalog never executes bundled scripts.
#!/usr/bin/env python3
"""Pass-the-Hash attack detection agent.
Detects NTLM hash reuse attacks by analyzing Windows Security Event ID 4624
for Type 3 NTLM logons with anomalous patterns across multiple targets.
"""
import argparse
import json
import re
from collections import defaultdict
from datetime import datetime
try:
import Evtx.Evtx as evtx
except ImportError:
evtx = None
LEGITIMATE_SOURCES = {"127.0.0.1", "::1", "-", ""}
def parse_logon_events(filepath):
if evtx is None:
return {"error": "python-evtx not installed: pip install python-evtx"}
events = []
with evtx.Evtx(filepath) as log:
for record in log.records():
xml = record.xml()
if "<EventID>4624</EventID>" not in xml:
continue
logon_type = re.search(r'<Data Name="LogonType">(\d+)', xml)
auth_pkg = re.search(r'<Data Name="AuthenticationPackageName">([^<]+)', xml)
account = re.search(r'<Data Name="TargetUserName">([^<]+)', xml)
domain = re.search(r'<Data Name="TargetDomainName">([^<]+)', xml)
src_ip = re.search(r'<Data Name="IpAddress">([^<]+)', xml)
computer = re.search(r'<Data Name="Computer">([^<]+)', xml)
time_match = re.search(r'SystemTime="([^"]+)"', xml)
lt = logon_type.group(1) if logon_type else ""
ap = auth_pkg.group(1) if auth_pkg else ""
if lt == "3" and "NTLM" in ap.upper():
events.append({
"timestamp": time_match.group(1) if time_match else "",
"logon_type": int(lt), "auth_package": ap.strip(),
"account": account.group(1) if account else "",
"domain": domain.group(1) if domain else "",
"source_ip": src_ip.group(1) if src_ip else "",
"computer": computer.group(1) if computer else "",
})
return events
def detect_pth_patterns(events, target_threshold=3):
if isinstance(events, dict) and "error" in events:
return [events]
findings = []
src_targets = defaultdict(lambda: {"computers": set(), "count": 0,
"source_ip": "", "account": ""})
for evt in events:
src = evt.get("source_ip", "")
if src in LEGITIMATE_SOURCES:
continue
key = f"{src}|{evt.get('account', '')}"
src_targets[key]["computers"].add(evt.get("computer", ""))
src_targets[key]["count"] += 1
src_targets[key]["source_ip"] = src
src_targets[key]["account"] = evt.get("account", "")
for key, data in src_targets.items():
target_count = len(data["computers"])
if target_count >= target_threshold:
findings.append({
"type": "ntlm_type3_multi_target",
"source_ip": data["source_ip"],
"account": data["account"],
"target_count": target_count,
"targets": list(data["computers"])[:20],
"total_logons": data["count"],
"severity": "CRITICAL" if target_count >= 10 else "HIGH",
"mitre": "T1550.002",
})
admin_sources = defaultdict(int)
for evt in events:
if evt.get("account", "").lower() in ("administrator", "admin"):
admin_sources[evt.get("source_ip", "")] += 1
for src, count in admin_sources.items():
if count >= 2 and src not in LEGITIMATE_SOURCES:
findings.append({
"type": "admin_ntlm", "source_ip": src,
"logon_count": count, "severity": "HIGH", "mitre": "T1550.002",
})
return findings
def main():
parser = argparse.ArgumentParser(description="Pass-the-Hash Detector")
parser.add_argument("--security-log", required=True, help="Windows Security EVTX")
parser.add_argument("--target-threshold", type=int, default=3)
args = parser.parse_args()
events = parse_logon_events(args.security_log)
findings = detect_pth_patterns(events, args.target_threshold)
ntlm_count = len(events) if isinstance(events, list) else 0
results = {
"timestamp": datetime.utcnow().isoformat() + "Z",
"total_ntlm_type3_logons": ntlm_count,
"findings": findings, "total_findings": len(findings),
}
print(json.dumps(results, indent=2))
if __name__ == "__main__":
main()
process.py3.8 KB
Display-only source. This catalog never executes bundled scripts.
#!/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()
Assets 1
template.mdtext/markdown · 2.6 KBKeep exploring