npx skills add mukul975/Anthropic-Cybersecurity-SkillsMITRE ATT&CK
NIST CSF 2.0
MITRE D3FEND
When to Use
- A SIEM or EDR alert fires and requires human classification before escalation
- Multiple concurrent alerts arrive and the SOC must prioritize response order
- An end user reports suspicious activity and the incident needs initial categorization
- A threat intelligence feed matches an IOC observed in the environment
Do not use for routine vulnerability scanning results or compliance audit findings that do not represent active security incidents.
Prerequisites
- Access to SIEM platform (Splunk, Elastic, Microsoft Sentinel) with current alert data
- Incident classification taxonomy aligned to NIST SP 800-61r3 categories
- Predefined severity matrix mapping asset criticality to threat type
- Contact roster for escalation paths (Tier 1 through Tier 3 and CIRT)
- Asset inventory with business criticality ratings
Workflow
Step 1: Collect Initial Alert Data
Gather all available context from the triggering alert before making classification decisions:
- Alert source: Which detection system generated the alert (EDR, SIEM, IDS/IPS, firewall, user report)
- Timestamp: When the event occurred and when it was detected (dwell time gap)
- Affected assets: Hostnames, IP addresses, user accounts involved
- Alert fidelity: Historical true-positive rate for this detection rule
- Raw evidence: Log entries, packet captures, process execution chains
Example SIEM alert context:
Source: CrowdStrike Falcon
Detection: Suspicious PowerShell Execution (T1059.001)
Host: WORKSTATION-FIN-042
User: jsmith@corp.example.com
Timestamp: 2025-11-15T14:23:17Z
Severity: High (detection rule confidence: 92%)
Process: powershell.exe -enc SQBFAFgAIAAoAE4AZQB3AC0ATwBiAGoA...
Parent: outlook.exe (PID 4812)Step 2: Classify the Incident Type
Map the alert to a standard incident category per NIST SP 800-61r3:
| Category | Examples |
|---|---|
| Unauthorized Access | Compromised credentials, privilege escalation, IDOR |
| Denial of Service | Volumetric DDoS, application-layer flood, resource exhaustion |
| Malicious Code | Malware execution, ransomware detonation, cryptominer |
| Improper Usage | Policy violation, insider data exfiltration, shadow IT |
| Reconnaissance | Port scanning, directory enumeration, credential spraying |
| Web Application Attack | SQL injection, XSS, SSRF exploitation |
Step 3: Assign Severity Using Impact Matrix
Calculate severity by combining asset criticality with threat severity:
Severity = f(Asset Criticality, Threat Type, Data Sensitivity, Lateral Movement Potential)
Critical (P1): Crown jewel systems compromised, active data exfiltration, ransomware spreading
High (P2): Production system compromise, confirmed malware execution, privileged account takeover
Medium (P3): Non-production compromise, unsuccessful exploitation attempt, single endpoint malware
Low (P4): Reconnaissance activity, policy violation, benign true positiveResponse SLA targets:
- P1: Acknowledge within 15 minutes, containment within 1 hour
- P2: Acknowledge within 30 minutes, containment within 4 hours
- P3: Acknowledge within 2 hours, investigation within 24 hours
- P4: Acknowledge within 8 hours, investigation within 72 hours
Step 4: Perform Initial Enrichment
Before escalation, enrich the alert with contextual data:
- Threat intelligence: Check IOCs (IP, hash, domain) against TI platforms (VirusTotal, OTX, MISP)
- Asset context: Query CMDB for asset owner, business function, data classification
- User context: Check identity provider for recent authentication anomalies, MFA status
- Historical correlation: Search for related alerts on the same host/user in the past 30 days
- Network context: Verify if source/destination IPs are internal, known partners, or external threat actors
Step 5: Document and Escalate
Create a structured triage record and route to the appropriate response tier:
Incident Triage Record
━━━━━━━━━━━━━━━━━━━━━
Ticket ID: INC-2025-1547
Triage Analyst: [analyst name]
Triage Time: 2025-11-15T14:35:00Z (12 min from alert)
Classification: Malicious Code - Macro-based initial access
Severity: P2 - High
Affected Assets: WORKSTATION-FIN-042 (Finance dept, handles PII)
Affected Users: jsmith@corp.example.com
IOCs Identified: powershell.exe spawned by outlook.exe, encoded command
TI Matches: Base64 payload matches known Qakbot loader pattern
Escalation: Tier 2 - Malware IR team
Recommended: Isolate endpoint, preserve memory dump, block sender domainStep 6: Initiate Containment Hold
If severity is P1 or P2, initiate immediate containment actions while awaiting full investigation:
- Network-isolate the affected endpoint via EDR (CrowdStrike contain, Defender isolate)
- Disable compromised user accounts in Active Directory or identity provider
- Block identified malicious IPs/domains at firewall and DNS sinkhole
- Preserve volatile evidence (memory dump) before any remediation
Key Concepts
| Term | Definition |
|---|---|
| Triage | Rapid assessment process to classify and prioritize security incidents based on severity and business impact |
| PICERL | SANS incident response framework: Preparation, Identification, Containment, Eradication, Recovery, Lessons Learned |
| Dwell Time | Duration between initial compromise and detection; average is 10 days per Mandiant M-Trends 2025 |
| True Positive Rate | Percentage of alerts from a detection rule that represent genuine security incidents |
| Crown Jewel Assets | Systems and data critical to business operations whose compromise would cause severe organizational impact |
| Alert Fatigue | Degraded analyst performance caused by high volumes of low-fidelity or false-positive alerts |
| Mean Time to Acknowledge (MTTA) | Average time from alert generation to analyst acknowledgment; key SOC performance metric |
Tools & Systems
- Splunk Enterprise Security: SIEM platform for alert aggregation, correlation, and triage workflow management
- CrowdStrike Falcon: EDR platform providing endpoint telemetry, detection, and one-click host containment
- TheHive: Open-source incident response platform for case management, task tracking, and team collaboration
- MISP: Threat intelligence sharing platform for IOC enrichment during triage
- Cortex XSOAR: SOAR platform for automating enrichment playbooks and triage decision trees
Common Scenarios
Scenario: Encoded PowerShell from Email Client
Context: SOC analyst receives a P2 alert showing powershell.exe with a Base64-encoded command spawned as a child process of outlook.exe on a finance department workstation.
Approach:
- Decode the Base64 payload to determine the command intent
- Check the parent process chain for anomalies (Outlook spawning PowerShell is abnormal)
- Query VirusTotal for the decoded payload hash
- Correlate with email gateway logs to identify the triggering email and sender
- Check if other recipients in the organization received the same email
- Isolate the endpoint and escalate to Tier 2 with full triage context
Pitfalls:
- Dismissing encoded PowerShell as a false positive without decoding the payload
- Failing to check for lateral spread to other recipients of the same phishing email
- Remediating the endpoint before capturing volatile memory evidence
Output Format
INCIDENT TRIAGE REPORT
======================
Ticket: INC-[YYYY]-[NNNN]
Date/Time: [ISO 8601 timestamp]
Triage Analyst: [Name]
Time to Triage: [minutes from alert to classification]
CLASSIFICATION
Type: [NIST category]
Severity: [P1-P4] - [Critical/High/Medium/Low]
Confidence: [High/Medium/Low]
MITRE ATT&CK: [Technique ID and name]
AFFECTED SCOPE
Assets: [hostname(s), IP(s)]
Users: [account(s)]
Data at Risk: [classification level]
Business Unit: [department]
EVIDENCE SUMMARY
[Bullet list of key observations]
ENRICHMENT RESULTS
TI Matches: [Yes/No - details]
Historical: [Related prior incidents]
Asset Criticality: [rating]
RECOMMENDED ACTIONS
1. [Immediate action]
2. [Investigation step]
3. [Escalation target]
ESCALATION
Routed To: [Team/Individual]
SLA Target: [Containment deadline]References and resources
Everything below is rendered for inspection. Script files are read-only and never run.
References 1
api-reference.md2.3 KB
API Reference: Triaging Security Incidents
requests Library (Threat Intel APIs)
VirusTotal API v3
headers = {"x-apikey": "<API_KEY>"}
# IP lookup
requests.get(f"https://www.virustotal.com/api/v3/ip_addresses/{ip}", headers=headers)
# File hash lookup
requests.get(f"https://www.virustotal.com/api/v3/files/{sha256}", headers=headers)
# Domain lookup
requests.get(f"https://www.virustotal.com/api/v3/domains/{domain}", headers=headers)Response Fields
| Field | Description |
|---|---|
last_analysis_stats.malicious |
Vendors detecting as malicious |
last_analysis_stats.undetected |
Vendors with no detection |
meaningful_name |
File name (for hash lookups) |
reputation |
Community reputation score |
NIST SP 800-61r3 Incident Categories
| Category | Examples |
|---|---|
| Unauthorized Access | Credential compromise, privilege escalation |
| Denial of Service | DDoS, resource exhaustion |
| Malicious Code | Malware, ransomware, cryptominer |
| Improper Usage | Policy violation, insider threat |
| Reconnaissance | Port scan, directory enumeration |
| Web Application Attack | SQLi, XSS, SSRF |
Severity Matrix
| Priority | Label | ACK SLA | Containment SLA |
|---|---|---|---|
| P1 | Critical | 15 min | 1 hour |
| P2 | High | 30 min | 4 hours |
| P3 | Medium | 2 hours | 24 hours |
| P4 | Low | 8 hours | 72 hours |
SANS PICERL Framework
- Preparation - Tools, playbooks, team readiness
- Identification - Detection and triage (this skill)
- Containment - Isolate affected systems
- Eradication - Remove threat from environment
- Recovery - Restore systems to normal operation
- Lessons Learned - Post-incident review
MITRE ATT&CK Mapping
| Technique | ID | Common Alert |
|---|---|---|
| Brute Force | T1110 | Multiple failed logins |
| PowerShell | T1059.001 | Encoded PS execution |
| Valid Accounts | T1078 | Anomalous authentication |
| Phishing | T1566 | Malicious email attachment |
| Exploit Public App | T1190 | Web attack detected |
References
- NIST SP 800-61r3: https://csrc.nist.gov/pubs/sp/800/61/r3/final
- SANS Incident Response: https://www.sans.org/white-papers/33901/
- VirusTotal API: https://docs.virustotal.com/reference/overview
- MITRE ATT&CK: https://attack.mitre.org/
Scripts 1
agent.py10.5 KB
#!/usr/bin/env python3
"""Agent for triaging security incidents using NIST SP 800-61 and SANS PICERL frameworks."""
import requests
import json
import argparse
from datetime import datetime, timezone
NIST_CATEGORIES = {
"unauthorized_access": "Unauthorized Access",
"dos": "Denial of Service",
"malicious_code": "Malicious Code",
"improper_usage": "Improper Usage",
"reconnaissance": "Reconnaissance",
"web_attack": "Web Application Attack",
}
SEVERITY_MATRIX = {
"P1": {"label": "Critical", "ack_sla": "15 min", "contain_sla": "1 hour",
"criteria": "Crown jewel compromise, active exfiltration, ransomware spreading"},
"P2": {"label": "High", "ack_sla": "30 min", "contain_sla": "4 hours",
"criteria": "Production compromise, confirmed malware, privileged account takeover"},
"P3": {"label": "Medium", "ack_sla": "2 hours", "contain_sla": "24 hours",
"criteria": "Non-production compromise, failed exploitation, single endpoint malware"},
"P4": {"label": "Low", "ack_sla": "8 hours", "contain_sla": "72 hours",
"criteria": "Reconnaissance, policy violation, benign true positive"},
}
def classify_incident(alert_data):
"""Classify incident type based on alert indicators."""
print("[*] Classifying incident type...")
alert_name = alert_data.get("alert_name", "").lower()
process = alert_data.get("process", "").lower()
event_code = alert_data.get("event_code", "")
if any(kw in alert_name for kw in ["malware", "ransomware", "trojan", "cryptominer"]):
category = "malicious_code"
elif any(kw in alert_name for kw in ["brute force", "credential", "password spray"]):
category = "unauthorized_access"
elif any(kw in alert_name for kw in ["dos", "flood", "resource exhaustion"]):
category = "dos"
elif any(kw in alert_name for kw in ["sql injection", "xss", "ssrf", "xxe"]):
category = "web_attack"
elif any(kw in alert_name for kw in ["scan", "enum", "recon", "discovery"]):
category = "reconnaissance"
elif "powershell" in process and "encoded" in alert_name.lower():
category = "malicious_code"
else:
category = "unauthorized_access"
classification = NIST_CATEGORIES.get(category, "Unknown")
print(f" [+] Classification: {classification} ({category})")
return category, classification
def assess_severity(alert_data, asset_criticality="medium"):
"""Calculate incident severity based on threat and asset context."""
print("\n[*] Assessing severity...")
threat_score = 0
alert_severity = alert_data.get("severity", "").lower()
if alert_severity in ("critical", "high"):
threat_score += 3
elif alert_severity == "medium":
threat_score += 2
else:
threat_score += 1
confidence = alert_data.get("confidence", 50)
if confidence >= 80:
threat_score += 2
elif confidence >= 50:
threat_score += 1
asset_scores = {"critical": 3, "high": 2, "medium": 1, "low": 0}
asset_score = asset_scores.get(asset_criticality, 1)
total = threat_score + asset_score
if total >= 7:
priority = "P1"
elif total >= 5:
priority = "P2"
elif total >= 3:
priority = "P3"
else:
priority = "P4"
sev_info = SEVERITY_MATRIX[priority]
print(f" [+] Priority: {priority} - {sev_info['label']}")
print(f" [+] ACK SLA: {sev_info['ack_sla']} | Containment SLA: {sev_info['contain_sla']}")
return priority, sev_info
def check_virustotal(api_key, indicator, indicator_type="ip"):
"""Check an indicator against VirusTotal."""
print(f"\n[*] Checking VirusTotal for {indicator_type}: {indicator}...")
base_urls = {
"ip": f"https://www.virustotal.com/api/v3/ip_addresses/{indicator}",
"hash": f"https://www.virustotal.com/api/v3/files/{indicator}",
"domain": f"https://www.virustotal.com/api/v3/domains/{indicator}",
}
url = base_urls.get(indicator_type)
if not url:
return {}
try:
headers = {"x-apikey": api_key}
resp = requests.get(url, headers=headers, timeout=15)
if resp.status_code == 200:
data = resp.json().get("data", {}).get("attributes", {})
if indicator_type in ("ip", "domain"):
malicious = data.get("last_analysis_stats", {}).get("malicious", 0)
total = sum(data.get("last_analysis_stats", {}).values())
print(f" [+] VT Result: {malicious}/{total} vendors flagged as malicious")
return {"malicious": malicious, "total": total}
elif indicator_type == "hash":
malicious = data.get("last_analysis_stats", {}).get("malicious", 0)
name = data.get("meaningful_name", "Unknown")
print(f" [+] VT Result: {name} - {malicious} detections")
return {"name": name, "malicious": malicious}
elif resp.status_code == 404:
print(f" [-] Not found in VirusTotal")
else:
print(f" [-] VT API error: {resp.status_code}")
except requests.RequestException as e:
print(f" [-] VT request failed: {e}")
return {}
def build_mitre_mapping(category, process_info=""):
"""Map incident to MITRE ATT&CK techniques."""
mappings = {
"malicious_code": [
{"technique": "T1059.001", "name": "PowerShell"},
{"technique": "T1204.002", "name": "User Execution: Malicious File"},
],
"unauthorized_access": [
{"technique": "T1110", "name": "Brute Force"},
{"technique": "T1078", "name": "Valid Accounts"},
],
"reconnaissance": [
{"technique": "T1046", "name": "Network Service Discovery"},
{"technique": "T1595", "name": "Active Scanning"},
],
"web_attack": [
{"technique": "T1190", "name": "Exploit Public-Facing Application"},
],
}
techniques = mappings.get(category, [])
if techniques:
print(f"\n[*] MITRE ATT&CK mapping:")
for t in techniques:
print(f" - {t['technique']}: {t['name']}")
return techniques
def generate_triage_record(alert_data, classification, priority, sev_info,
ti_results, mitre, output_path):
"""Generate a structured incident triage report."""
triage_time = datetime.now(timezone.utc)
alert_time = alert_data.get("timestamp", triage_time.isoformat())
record = {
"ticket_id": f"INC-{triage_time.strftime('%Y')}-{hash(str(alert_data)) % 10000:04d}",
"triage_analyst": alert_data.get("analyst", "automated"),
"triage_time": triage_time.isoformat(),
"alert_time": alert_time,
"classification": {
"type": classification[1],
"category": classification[0],
"priority": priority,
"severity_label": sev_info["label"],
"confidence": alert_data.get("confidence", "Unknown"),
},
"affected_scope": {
"assets": alert_data.get("affected_hosts", []),
"users": alert_data.get("affected_users", []),
"business_unit": alert_data.get("business_unit", "Unknown"),
},
"evidence": {
"alert_source": alert_data.get("source", "Unknown"),
"alert_name": alert_data.get("alert_name", "Unknown"),
"raw_indicators": alert_data.get("indicators", {}),
},
"enrichment": {
"threat_intel": ti_results,
"mitre_attack": mitre,
},
"recommended_actions": [],
"sla": {
"acknowledge_by": sev_info["ack_sla"],
"contain_by": sev_info["contain_sla"],
},
}
if priority in ("P1", "P2"):
record["recommended_actions"] = [
"Isolate affected endpoint via EDR",
"Disable compromised user account",
"Preserve volatile evidence (memory dump)",
"Escalate to Tier 2 IR team",
]
else:
record["recommended_actions"] = [
"Monitor for additional indicators",
"Review related alerts for the past 7 days",
"Document findings and close if benign",
]
with open(output_path, "w") as f:
json.dump(record, f, indent=2)
print(f"\n[*] Triage record saved to {output_path}")
print(f"[*] Ticket: {record['ticket_id']} | Priority: {priority} ({sev_info['label']})")
return record
def main():
parser = argparse.ArgumentParser(description="Security Incident Triage Agent")
parser.add_argument("--alert-name", required=True, help="Name of the triggering alert")
parser.add_argument("--source", default="SIEM", help="Alert source system")
parser.add_argument("--severity", default="high", help="Alert severity")
parser.add_argument("--confidence", type=int, default=75, help="Alert confidence (0-100)")
parser.add_argument("--host", help="Affected hostname")
parser.add_argument("--src-ip", help="Source IP address")
parser.add_argument("--user", help="Affected username")
parser.add_argument("--process", default="", help="Suspicious process name")
parser.add_argument("--asset-criticality", default="medium",
choices=["critical", "high", "medium", "low"])
parser.add_argument("--vt-key", help="VirusTotal API key for threat intel")
parser.add_argument("--indicator", help="IOC to check (IP, hash, or domain)")
parser.add_argument("--indicator-type", default="ip", choices=["ip", "hash", "domain"])
parser.add_argument("-o", "--output", default="triage_record.json")
args = parser.parse_args()
alert_data = {
"alert_name": args.alert_name,
"source": args.source,
"severity": args.severity,
"confidence": args.confidence,
"affected_hosts": [args.host] if args.host else [],
"affected_users": [args.user] if args.user else [],
"process": args.process,
"indicators": {"src_ip": args.src_ip},
"timestamp": datetime.now(timezone.utc).isoformat(),
}
print("[*] Security Incident Triage\n")
classification = classify_incident(alert_data)
priority, sev_info = assess_severity(alert_data, args.asset_criticality)
mitre = build_mitre_mapping(classification[0], args.process)
ti_results = {}
if args.vt_key and args.indicator:
ti_results = check_virustotal(args.vt_key, args.indicator, args.indicator_type)
generate_triage_record(alert_data, classification, priority, sev_info,
ti_results, mitre, args.output)
if __name__ == "__main__":
main()