Threat Intelligence and Attribution
Threat intelligence transforms raw IOCs and TTPs into actionable defensive context. The intelligence lifecycle — collection, processing, analysis, dissemination, feedback — drives detection rule priority, threat hunting hypotheses, and security roadmap decisions. Attribution is an analytical process with probabilistic confidence, not binary certainty; the same evidence supports multiple plausible actors.
After containing an incident, your IR team has a PCAP, memory dump, and malware sample. Your task: extract IOCs, map them to ATT&CK techniques, assess actor confidence (is this APT28 or a copycat using leaked tools?), and convert the analysis into detection rules and a structured intelligence report for the security team.
Intelligence Lifecycle
IOC Types and Confidence Decay
| IOC type | Pyramid of Pain level | TTL | Confidence decay |
|---|---|---|---|
| File hash (MD5/SHA256) | Trivial | Hours–days | Immediately stale after recompile/packer |
| IP address | Easy | Days–weeks | Bullet-proof hosting rotates weekly; shared infra causes FP |
| Domain name | Simple | Weeks | DGA or fast-flux; TLD change; free subdomain abuse |
| Network artefact (JA3, User-Agent) | Annoying | Weeks–months | Trivially changed by configuring C2 profile |
| Host artefact (mutex, registry key, file path) | Annoying | Months | Harder to change; often left in by developers |
| TTP (ATT&CK technique) | Challenging | Months–years | Core attack methods rarely change; most durable indicator |
ATT&CK Mapping Workflow
# Python: auto-map technique IDs from IOC report to ATT&CK descriptions
import requests, json
ATT_ENTERPRISE = "https://raw.githubusercontent.com/mitre/cti/master/enterprise-attack/enterprise-attack.json"
def load_attack():
data = requests.get(ATT_ENTERPRISE).json()
techniques = {}
for obj in data['objects']:
if obj['type'] == 'attack-pattern':
for ref in obj.get('external_references', []):
if ref.get('source_name') == 'mitre-attack':
tid = ref['external_id']
techniques[tid] = {
'name': obj['name'],
'tactic': [p['phase_name'] for p in obj.get('kill_chain_phases',[])],
'description': obj.get('description','')[:200]
}
return techniques
techniques = load_attack()
observed_ttps = ['T1003.001', 'T1055.001', 'T1071.001', 'T1021.002']
for tid in observed_ttps:
t = techniques.get(tid, {})
print(f"{tid}: {t.get('name')} — tactics: {', '.join(t.get('tactic',[]))}")
# STIX 2.1 bundle — machine-readable intelligence sharing:
from stix2 import Indicator, Malware, Relationship, Bundle, IPv4Address
# Create threat actor indicator
c2_ip = IPv4Address(value="185.220.101.55")
indicator = Indicator(
name="APT29 C2 IP",
description="Observed C2 IP from SUNBURST campaign",
pattern_type="stix",
pattern="[ipv4-addr:value = '185.220.101.55']",
valid_from="2024-01-01T00:00:00Z",
labels=["malicious-activity"]
)
malware_obj = Malware(name="SUNBURST", is_family=False)
rel = Relationship(relationship_type="indicates",
source_ref=indicator.id,
target_ref=malware_obj.id)
bundle = Bundle(objects=[indicator, malware_obj, rel])
print(bundle.serialize(pretty=True))
Attribution Methodology
TI-Ops Integration — Feeds, MISP, and Detection
# MISP API: query for all C2 IPs from a specific threat actor tag:
from pymisp import PyMISP
misp = PyMISP('https://misp.internal', 'YOUR_API_KEY', ssl=False)
# Search for attributes tagged APT28 of type ip-dst:
results = misp.search(
controller='attributes',
type_attribute='ip-dst',
tags=['misp-galaxy:threat-actor="APT28"'],
to_ids=True
)
ips = [a['value'] for a in results['Attribute']]
print(f"Found {len(ips)} APT28 C2 IPs")
# Export to Sigma detection rule dynamically:
print("detection:")
print(" selection:")
print(" dst_ip|contains:")
for ip in ips[:20]:
print(f" - '{ip}'")
Detection Engineering
title: Known Threat Actor C2 Domain — TI Feed Match
logsource:
product: windows
service: dns-client
detection:
selection:
QueryName|contains:
- 'avsvmcloud.com' # SUNBURST
- 'stage.lostserver.com' # example APT28 domain
condition: selection
level: critical
tags: [attack.command_and_control, T1071.004]
-- MDE KQL: Threat intel IOC matching against DNS logs (STIX feed import)
let ti_domains = dynamic([
"avsvmcloud.com",
"megatoolkit.com",
"panhardware.com"
]);
DeviceNetworkEvents
| where RemoteUrl has_any (ti_domains)
or DnsQueryAnswerIpAddress has_any (ti_domains)
| project Timestamp, DeviceName, RemoteUrl, RemoteIP, InitiatingProcessFileName
-- MDE KQL: Detect imphash matches from known malware families
DeviceFileCertificateInfo
| where Timestamp > ago(7d)
| join kind=inner (
ExternalData(["imphash"],["string"]) // custom watchlist of known-bad imphashes
with (h@'https://...watchlist.csv', format="csv")
) on $left.SHA256 == $right.hash
| project Timestamp, DeviceName, FileName, FolderPath
Q&A
IOC-based detection (IP, domain, hash) degrades rapidly as threat actors rotate infrastructure. What is the MITRE ATT&CK-aligned approach to writing detections that remain valid even as specific IOCs change, and what is the practical tradeoff with this approach?
The ATT&CK-aligned approach is to write behavioral detections against techniques rather than specific artifacts. A technique-level detection asks "did this process load LSASS memory?" rather than "is this the specific mimikatz.exe hash?". The Pyramid of Pain formalizes why this works: attackers must change their fundamental TTPs to evade technique-based detection, whereas rotating an IP or recompiling a binary takes minutes. Technique-based Sigma/KQL rules focus on behaviors — a process opening LSASS with PROCESS_VM_READ access (T1003.001), a service created and started within 60 seconds (PsExec pattern), DNS queries with high-entropy subdomains (T1071.004 DNS tunneling) — none of which require any knowledge of what the specific malware family is.
The practical tradeoff is false-positive rate and analytical workload. An IOC-based detection (block this specific IP) is highly precise — every hit is a likely true positive, and almost no investigation is needed. A technique-based detection (alert on any process that reads LSASS memory) is much broader — legitimate security tools, crash reporters, and AV products do this too, requiring baseline suppression, process allowlists, and analyst triage. The operational model for mature SOCs is layered: IOC matches at the perimeter for immediate block/alert, technique-based behavioral rules in the SIEM/EDR for deeper investigation, and ATT&CK coverage mapping via DeTT&CT to identify gaps. Neither alone is sufficient — IOCs provide speed (no analysis needed on known-bad indicators) while TTPs provide resilience (detects novel tools using known tradecraft).