| name | building-attack-pattern-library-from-cti-reports |
| description | Extract and catalog attack patterns from cyber threat intelligence reports into a structured STIX-based library mapped to MITRE ATT&CK for detection engineering and threat-informed defense. |
| domain | cybersecurity |
| subdomain | threat-intelligence |
| tags | ["attack-pattern","cti-reports","mitre-attack","stix","detection-engineering","threat-intelligence","nlp","extraction"] |
| version | 1.0 |
| author | mahipal |
| license | Apache-2.0 |
Building Attack Pattern Library from CTI Reports
Overview
Cyber threat intelligence (CTI) reports from vendors like Mandiant, CrowdStrike, Talos, and Microsoft contain detailed descriptions of adversary behaviors that can be extracted, normalized, and cataloged into a structured attack pattern library. This skill covers parsing CTI reports to extract adversary techniques, mapping behaviors to MITRE ATT&CK technique IDs, creating STIX 2.1 Attack Pattern objects, building a searchable library indexed by tactic, technique, and threat actor, and generating detection rule templates from documented patterns.
Prerequisites
- Python 3.9+ with
stix2, mitreattack-python, spacy, requests libraries
- Collection of CTI reports (PDF, HTML, or text format)
- MITRE ATT&CK STIX data (local or via TAXII)
- Understanding of ATT&CK technique structure and naming conventions
- Familiarity with detection engineering concepts (Sigma, YARA)
Key Concepts
Attack Pattern Extraction
CTI reports describe adversary behaviors in natural language. Extraction involves identifying action verbs and technical terms that map to ATT&CK techniques, recognizing tool names and malware families, identifying infrastructure indicators, and mapping sequences of behaviors to attack chains (kill chain phases).
STIX 2.1 Attack Pattern Objects
STIX defines Attack Pattern as a Structured Domain Object (SDO) that describes ways threat actors attempt to compromise targets. Each pattern links to ATT&CK via external references, includes kill chain phases (tactics), and can be related to Intrusion Sets, Malware, and Tool objects.
Detection Rule Generation
Extracted attack patterns inform detection engineering by providing: specific procedure examples for Sigma rule creation, behavioral sequences for correlation rules, IOC patterns for YARA and Snort rules, and data source requirements for telemetry gaps.
Practical Steps
Step 1: Parse CTI Reports and Extract Behaviors
import re
import json
from collections import defaultdict
class CTIReportParser:
"""Parse CTI reports to extract adversary behaviors."""
BEHAVIOR_INDICATORS = [
"used", "executed", "deployed", "leveraged", "exploited",
"established", "created", "modified", "downloaded", "uploaded",
"exfiltrated", "injected", "enumerated", "spawned", "dropped",
"persisted", "escalated", "moved laterally", "collected",
"encrypted", "compressed", "encoded", "obfuscated",
]
TOOL_PATTERNS = [
r'\b(Cobalt Strike|Mimikatz|PsExec|BloodHound|Rubeus|Impacket)\b',
r'\b(PowerShell|cmd\.exe|WMI|WMIC|certutil|bitsadmin)\b',
r'\b(Metasploit|Empire|Covenant|Sliver|Brute Ratel)\b',
r'\b(Lazagne|SharpHound|ADFind|Sharphound|Invoke-Obfuscation)\b',
]
TECHNIQUE_KEYWORDS = {
"spearphishing": "T1566",
"phishing attachment": "T1566.001",
"phishing link": "T1566.002",
"powershell": "T1059.001",
"command line": "T1059.003",
"scheduled task": ,
: ,
: ,
: ,
: ,
: ,
: ,
: ,
: ,
: ,
: ,
: ,
: ,
: ,
: ,
}
():
sentences = re.split(, text)
behaviors = []
sentence sentences:
sentence_lower = sentence.lower()
indicator .BEHAVIOR_INDICATORS:
indicator sentence_lower:
behavior = {
: sentence.strip(),
: indicator,
: ._extract_tools(sentence),
: ._match_techniques(sentence_lower),
}
behavior[]:
behaviors.append(behavior)
()
behaviors
():
tools = ()
pattern .TOOL_PATTERNS:
matches = re.findall(pattern, text, re.IGNORECASE)
tools.update(matches)
(tools)
():
matches = []
keyword, tech_id .TECHNIQUE_KEYWORDS.items():
keyword text:
matches.append({: keyword, : tech_id})
matches
parser = CTIReportParser()
sample_report =
behaviors = parser.parse_report(sample_report)
Step 2: Map Behaviors to ATT&CK Techniques
from attackcti import attack_client
class ATTACKMapper:
def __init__(self):
self.lift = attack_client()
self.techniques = {}
self._load_techniques()
def _load_techniques(self):
"""Load all ATT&CK techniques for mapping."""
all_techs = self.lift.get_enterprise_techniques()
for tech in all_techs:
tech_id = ""
for ref in tech.get("external_references", []):
if ref.get("source_name") == "mitre-attack":
tech_id = ref.get("external_id", "")
break
if tech_id:
self.techniques[tech_id] = {
"name": tech.get("name", ""),
"description": tech.get("description", "")[:500],
"tactics": [p.get("phase_name") for p in tech.get("kill_chain_phases", [])],
"platforms": tech.get("x_mitre_platforms", []),
"data_sources": tech.get(, []),
}
()
():
mapped = []
behavior behaviors:
hint behavior.get(, []):
tech_id = hint[]
tech_id .techniques:
tech_info = .techniques[tech_id]
mapped.append({
: tech_id,
: tech_info[],
: tech_info[],
: behavior[],
: behavior[],
: hint[],
: tech_info[],
})
()
mapped
mapper = ATTACKMapper()
mapped_behaviors = mapper.map_behaviors(behaviors)
Step 3: Create STIX 2.1 Attack Pattern Library
from stix2 import AttackPattern, Relationship, Bundle, TLP_GREEN
from datetime import datetime
class AttackPatternLibrary:
def __init__(self):
self.patterns = []
self.relationships = []
def add_pattern_from_mapping(self, mapping, report_source="CTI Report"):
"""Create STIX Attack Pattern from mapped behavior."""
pattern = AttackPattern(
name=mapping["technique_name"],
description=f"Observed: {mapping['source_sentence']}\n\n"
f"Tools: {', '.join(mapping['tools_observed']) or 'None identified'}\n"
f"Source: {report_source}",
external_references=[{
"source_name": "mitre-attack",
"external_id": mapping["technique_id"],
"url": f"https://attack.mitre.org/techniques/{mapping['technique_id'].replace('.', '/')}/",
}],
kill_chain_phases=[{
"kill_chain_name": "mitre-attack",
"phase_name": tactic,
} for tactic in mapping["tactics"]],
object_marking_refs=[TLP_GREEN],
)
.patterns.append(pattern)
pattern
():
seen_techniques = ()
mapping mapped_behaviors:
tech_id = mapping[]
tech_id seen_techniques:
.add_pattern_from_mapping(mapping, report_source)
seen_techniques.add(tech_id)
bundle = Bundle(objects=.patterns + .relationships)
()
bundle
():
bundle = Bundle(objects=.patterns + .relationships)
(output_file, ) f:
f.write(bundle.serialize(pretty=))
()
():
templates = []
mapping mapped_behaviors:
template = {
: ,
: ,
: ,
: [
,
],
: [
mapping[] ,
,
],
: mapping.get(, []),
: mapping.get(, []),
: mapping[],
}
templates.append(template)
(, ) f:
json.dump(templates, f, indent=)
()
templates
library = AttackPatternLibrary()
bundle = library.build_library(mapped_behaviors, )
library.export_library()
templates = library.generate_detection_templates(mapped_behaviors)
Validation Criteria
- CTI report parsed and behavioral indicators extracted
- Behaviors mapped to ATT&CK techniques with confidence
- STIX 2.1 Attack Pattern objects created with proper references
- Library searchable by tactic, technique, and threat actor
- Detection templates generated from documented patterns
- Library exportable as STIX bundle for sharing
References