Learn Ethical Hacking (#52) - Threat Intelligence - Knowing Your Enemy

avatar
(Edited)

Learn Ethical Hacking (#52) - Threat Intelligence - Knowing Your Enemy

leh-banner.jpg

What will I learn

  • What threat intelligence is and how it transforms reactive security into proactive defense;
  • Strategic, operational, and tactical intelligence -- the three levels and who consumes each;
  • IOCs (Indicators of Compromise) -- hashes, IPs, domains, and why they expire fast;
  • TTPs (Tactics, Techniques, and Procedures) -- the behavioral patterns that outlast IOCs;
  • The Pyramid of Pain -- why detecting TTPs hurts attackers more than detecting hashes;
  • Threat intelligence platforms -- MISP, OpenCTI, and commercial feeds;
  • STIX and TAXII -- the standardized formats for sharing threat intelligence;
  • Building a threat intelligence program -- from ad-hoc Googling to structured collection and analysis;
  • Defense: threat-informed prioritization, intelligence-driven detection, and the intelligence cycle.

Requirements

  • A working modern computer running macOS, Windows or Ubuntu;
  • Understanding of incident response from Episode 51;
  • Familiarity with MITRE ATT&CK from Episode 50;
  • The ambition to learn ethical hacking and security research.

Difficulty

  • Intermediate

Curriculum (of the Learn Ethical Hacking Series):

Learn Ethical Hacking (#52) - Threat Intelligence - Knowing Your Enemy

Solutions to Episode 51 Exercises

Exercise 1: Ransomware IR playbook (abbreviated).

First 15 minutes:
  - Isolate affected systems from network (VLAN quarantine)
  - DO NOT power off (preserve memory evidence)
  - Identify ransomware variant from ransom note / file extension
  - Activate IR team, notify CISO and legal
  - Determine scope: how many systems, which segments

Containment:
  - Block C2 IPs/domains at firewall
  - Disable affected accounts
  - Isolate backup systems (verify they are not encrypted)
  - Deploy EDR to unaffected systems for monitoring

Investigation:
  - Initial access vector? (phishing email, RDP brute force, VPN vuln)
  - How long was the attacker in before detonation?
  - What data was accessed/exfiltrated before encryption?
  - Are there other persistence mechanisms beyond ransomware?

Recovery:
  - Validate backup integrity before restoration
  - Rebuild from known-good images where possible
  - Patch the initial access vector before reconnecting
  - Enhanced monitoring for 90 days post-recovery

The key thing to notice here is the order of operations. Memory preservation first (as we stressed in episode 51), then network isolation, then scoping. The biggest mistake I see in ransomware playbooks is jumping straight to "restore from backup" without understanding how the attacker got in. If you restore without patching the initial access vector, you're just giving the attacker a clean target to encrypt again next week.

Exercise 2: Cobalt Strike beacon tabletop (abbreviated).

Triage:
  - Which workstation? Who is the user? Are they in the office?
  - Pull EDR timeline for that host (last 24 hours)
  - Check if user received phishing emails recently
  - Look for lateral movement from that host

SIEM queries:
  - All network connections from the host (last 7 days)
  - Authentication events FROM that host to other systems
  - Process creation events on the host (look for LOLBins)
  - DNS queries from the host (look for beaconing patterns)

Containment decision:
  - If active C2: isolate immediately, attacker has real-time control
  - If beacon is sleeping: may have time to scope before containing
  - Disable the user's account, revoke all sessions

Notification:
  - CISO immediately (SEV-2 minimum: confirmed intrusion)
  - Legal if data access is suspected
  - IR retainer firm if scope exceeds internal capability

The "is this our red team or a real attacker?" question from episode 50 is critical here. If your organization has authorized a red team engagement and a Cobalt Strike beacon shows up, you still need to treat it as potentially real until confirmed otherwise. As we discussed in episode 50, real threat actors (APT29, FIN7, Conti) use pirated Cobalt Strike extensively. The safe assumption is always "real attacker" until the red team lead confirms it's theirs ;-)

Exercise 3: Evidence collection (abbreviated).

Memory: LiME module loaded, dump to external USB drive
  SHA-256: a4f3e2d1c0b9a8... (verified immediately after acquisition)
  Collected by: [analyst name], 2026-05-18 14:30 UTC
  System: ubuntu-lab-01 (192.168.1.100)

Disk: dc3dd full disk image to external drive
  SHA-256: b5c4d3e2f1a0... (hash verified by dc3dd log)
  Write blocker: Tableau T35u used during acquisition

Logs: tar archive of /var/log/ directory
  SHA-256: c6d5e4f3a2b1...
  Collected immediately after memory acquisition

Chain of custody is everything. Without it, your evidence is worthless in court and unreliable for analysis. The SHA-256 hash proves the evidence hasn't been tampered with after collection. The timestamp proves when it was collected. The analyst name proves who collected it. The write blocker proves the original disk wasn't modified during imaging. Every piece of that chain exists for a reason, and every missing piece is a hole a defense attorney will drive a truck through.


Episode 51 covered incident response -- the discipline of answering "what do we do RIGHT NOW?" when the phone rings at 3 AM with bad news. We walked through the NIST SP 800-61 six-phase lifecycle (preparation, identification, containment, eradication, recovery, lessons learned), severity classification under pressure, the containment dilemma (observe vs isolate), evidence collection with proper chain of custody, eradication checklists for persistence mechanisms on both Windows and Linux, recovery priority ordering (authentication infrastructure first, business applications second, everything else third), the critically important KRBTGT double-reset for Golden Ticket invalidation after a DCSync attack (episode 33), IR playbooks for ransomware, BEC, and data breaches, and the Phase 6 blameless post-incident review that everyone skips but is arguably the most valuable phase of all. The core takeaway: you do not rise to the level of your expectations, you fall to the level of your preparation.

Today we flip the entire model on its head.

Incident response is reactive by definition. Something bad happened, you respond. You're always behind. The attacker chose the time, the method, and the target. You're playing catch-up from the first second, and the best you can hope for is to contain the damage before it gets catastrophic. For 51 episodes that has been the underlying dynamic: the attacker has the initiative, the defender reacts.

Threat intelligence changes that equation. Instead of waiting for the attack and then scrambling, you study who is likely to attack you, what tools they use, what techniques they prefer, and what their objectives are -- BEFORE they breach your perimeter. You build detection rules for their specific playbook. You harden the specific systems they target. You train your SOC to recognize their specific patterns. When the attack finally comes (and it will), your SIEM catches it on day one instead of day 72.

That is a structural advantage. And it's the first time in this series the defender genuinely has one.

Here we go.

From Reactive to Proactive -- The Fundamental Shift

#!/usr/bin/env python3
"""ti_maturity_model.py -- where does your organization fall?"""

MATURITY_LEVELS = {
    0: {
        'name': 'None',
        'description': 'No threat intelligence capability',
        'behavior': [
            'Respond to incidents as they occur',
            'No structured collection of threat data',
            'Security team reads vendor blogs occasionally',
            'Detection relies entirely on vendor-supplied signatures',
        ],
        'analogy': 'Driving with no mirrors and no GPS. You only '
                  'learn about obstacles when you hit them.',
    },
    1: {
        'name': 'Reactive',
        'description': 'IOC feeds imported, basic correlation',
        'behavior': [
            'Subscribe to open-source IOC feeds (AlienVault OTX, '
            'Abuse.ch)',
            'Import IOCs into SIEM/EDR automatically',
            'React to published vendor advisories',
            'No proactive analysis or original research',
        ],
        'analogy': 'Driving with mirrors but no GPS. You can see '
                  'what is behind you, not what is ahead.',
    },
    2: {
        'name': 'Proactive',
        'description': 'Dedicated TI function, structured analysis',
        'behavior': [
            'Dedicated threat intel analyst(s) on staff',
            'MISP or OpenCTI deployed for IOC management',
            'STIX/TAXII integration with SIEM and EDR',
            'Threat landscape reports for leadership',
            'Detection rules driven by intelligence',
            'Proactive threat hunting based on new intel',
        ],
        'analogy': 'Driving with mirrors, GPS, and weather alerts. '
                  'You know where you are going, what is behind you, '
                  'and what storm is approaching.',
    },
    3: {
        'name': 'Predictive',
        'description': 'Original research, industry leadership',
        'behavior': [
            'Original threat research and analysis',
            'Dark web monitoring for targeting indicators',
            'Active participation in ISACs (industry sharing)',
            'Attribution capability for incidents',
            'Intelligence drives security investment decisions',
            'Red team adversary emulation based on intel (ep 50)',
        ],
        'analogy': 'Driving with a full self-driving system that '
                  'has already mapped every pothole and knows which '
                  'intersections have the most accidents.',
    },
}

print("=== Threat Intelligence Maturity Model ===\n")
for level, data in MATURITY_LEVELS.items():
    print(f"Level {level}: {data['name']}")
    print(f"  {data['description']}")
    for b in data['behavior']:
        print(f"  - {b}")
    print(f"  Analogy: {data['analogy']}")
    print()

# Most organizations are at Level 0 or 1.
# Getting to Level 2 is the goal for this episode.

Most organizations sit at Level 0 or Level 1. They have no dedicated TI function, they import some IOC feeds into their SIEM, and they call it a day. The problem with Level 1 is that IOC feeds are the LEAST valuable form of threat intelligence (we'll see why in a moment), and without analysis capability you're essentially relying on other people's conclusions about what threatens YOUR organization. Which is a bit like reading someone else's medical diagnosis and applying their prescription to yourself.

The Three Levels of Threat Intelligence

Not all intelligence is created equal, and not all consumers need the same thing. The three levels map directly to three different audiences in an organization:

#!/usr/bin/env python3
"""ti_levels.py -- strategic, operational, tactical"""

TI_LEVELS = {
    'strategic': {
        'audience': 'Executives, board, CISO',
        'questions_answered': [
            'Who is targeting our industry?',
            'What are their motivations? (financial gain, espionage, '
            'disruption, hacktivism)',
            'What is the broader threat landscape trend?',
            'How should we allocate security budget?',
            'What risk do we accept vs mitigate?',
        ],
        'format': 'Briefings, risk assessments, quarterly reports',
        'shelf_life': 'Months to years',
        'example': 'Russian state actors are increasing operations '
                  'against energy sector organizations in Western '
                  'Europe. Recommend increased monitoring of OT '
                  'networks and accelerated ICS segmentation project.',
        'source': 'Government advisories (CISA, NCSC), industry '
                 'reports (Mandiant, CrowdStrike), ISAC briefings',
    },
    'operational': {
        'audience': 'Security managers, SOC leads, IR team leads',
        'questions_answered': [
            'What campaigns are currently active against our sector?',
            'What infrastructure are threat actors using this month?',
            'What are the current attack patterns and trends?',
            'Which vulnerabilities are being actively exploited?',
        ],
        'format': 'Campaign reports, threat advisories, weekly briefs',
        'shelf_life': 'Weeks to months',
        'example': 'APT29 is actively targeting OAuth consent phishing '
                  'against Microsoft 365 tenants in government sector. '
                  'Campaign uses Azure-themed landing pages hosted on '
                  'compromised WordPress sites. See IOCs below.',
        'source': 'Vendor threat reports, ISAC alerts, government '
                 'advisories, peer organization sharing',
    },
    'tactical': {
        'audience': 'SOC analysts, detection engineers, IR analysts',
        'questions_answered': [
            'What specific IOCs should we look for right now?',
            'What detection rules should we deploy this week?',
            'What does this malware sample do?',
            'Is this IP/domain/hash associated with known threats?',
        ],
        'format': 'IOC feeds, YARA rules, Snort/Suricata signatures, '
                 'Sigma rules',
        'shelf_life': 'Hours to days (IOCs expire FAST)',
        'example': 'Block IP 203.0.113.42 -- confirmed APT29 C2 '
                  'server active since 2026-05-15. Associated domain: '
                  'login-microsoftonline[.]com. SHA256 of dropper: '
                  'a4f3e2d1...',
        'source': 'IOC feeds (OTX, Abuse.ch, ThreatFox), malware '
                 'analysis, IR findings, community sharing',
    },
}

for level, data in TI_LEVELS.items():
    print(f"=== {level.upper()} Intelligence ===")
    print(f"  Audience: {data['audience']}")
    print(f"  Shelf life: {data['shelf_life']}")
    print(f"  Format: {data['format']}")
    print(f"  Example: {data['example']}")
    print(f"  Questions:")
    for q in data['questions_answered']:
        print(f"    - {q}")
    print()

The critical insight: most organizations only consume tactical intelligence (IOC feeds) because it's the easiest to operationalize -- you dump a list of bad IPs into your firewall and call it threat intelligence. But tactical intelligence has the shortest shelf life. An IP address is useful for hours or days before the attacker spins up a new one. Strategic intelligence has a shelf life of years ("nation-state actors target energy companies for geopolitical leverage") and directly informs how you spend your security budget. The irony is that the least perishable, most valuable intelligence is the hardest to produce and the most neglected.

IOCs vs TTPs -- The Pyramid of Pain

David Bianco's Pyramid of Pain is one of the most important mental models in threat intelligence. It shows how much pain you inflict on the attacker when you detect at each level of the pyramid:

#!/usr/bin/env python3
"""pyramid_of_pain.py -- what hurts attackers most?"""

PYRAMID = [
    {
        'level': 'Hash Values',
        'position': 'Bottom (trivial)',
        'attacker_effort_to_change': 'Seconds',
        'detection_value': 'MINIMAL',
        'example': 'SHA256 of a malware sample. The attacker '
                  'recompiles with one character changed and '
                  'the hash is completely different.',
        'shelf_life': 'Hours',
    },
    {
        'level': 'IP Addresses',
        'position': 'Low',
        'attacker_effort_to_change': 'Minutes',
        'detection_value': 'LOW',
        'example': 'C2 server IP. The attacker spins up a new '
                  'VPS on a different provider for $5/month.',
        'shelf_life': 'Days',
    },
    {
        'level': 'Domain Names',
        'position': 'Low-Medium',
        'attacker_effort_to_change': 'Hours',
        'detection_value': 'LOW-MEDIUM',
        'example': 'C2 domain. The attacker registers a new one '
                  'for $10. If they were smart, they registered '
                  '20 backup domains before the operation started.',
        'shelf_life': 'Days to weeks',
    },
    {
        'level': 'Network/Host Artifacts',
        'position': 'Medium',
        'attacker_effort_to_change': 'Hours to days',
        'detection_value': 'MEDIUM',
        'example': 'Specific HTTP headers in C2 traffic, unique '
                  'mutex names, registry key patterns. Changing '
                  'these requires modifying the toolset.',
        'shelf_life': 'Weeks',
    },
    {
        'level': 'Tools',
        'position': 'Medium-High',
        'attacker_effort_to_change': 'Days to weeks',
        'detection_value': 'HIGH',
        'example': 'Detecting Cobalt Strike, Mimikatz, or a '
                  'specific custom malware family. The attacker '
                  'must switch to a different tool entirely.',
        'shelf_life': 'Weeks to months',
    },
    {
        'level': 'TTPs (Tactics, Techniques, Procedures)',
        'position': 'Top (most painful)',
        'attacker_effort_to_change': 'Weeks to months',
        'detection_value': 'MAXIMUM',
        'example': 'Detecting the BEHAVIOR: PowerShell download '
                  'cradle -> LSASS dump -> Kerberoasting -> '
                  'lateral movement via WinRM. The attacker must '
                  'fundamentally redesign their methodology.',
        'shelf_life': 'Months to years',
    },
]

print("=== Pyramid of Pain ===\n")
print("         /\\")
print("        /TTP\\          <- HARDEST to change (behavior)")
print("       /------\\")
print("      / Tools  \\       <- medium effort")
print("     /----------\\")
print("    / Artifacts  \\     <- moderate effort")
print("   /--------------\\")
print("  / Domains / IPs  \\   <- trivial to change")
print(" /------------------\\")
print("/ Hash Values        \\  <- trivial to change")
print("/--------------------\\\n")

for item in reversed(PYRAMID):
    print(f"[{item['position']}] {item['level']}")
    print(f"  Effort to change: {item['attacker_effort_to_change']}")
    print(f"  Detection value: {item['detection_value']}")
    print(f"  Example: {item['example']}")
    print()

This is why IOC-only threat intelligence is necessary but fundamentally insufficient. If your entire detection strategy is "block these IPs and alert on these hashes," a competent attacker defeats you by changing their infrastructure -- which costs them minutes and dollars. If your detection strategy includes behavioral analytics ("alert when any process accesses LSASS memory and then makes network connections to other workstations within the same hour"), you're detecting at the TTP level. The attacker now needs to completely redesign their post-exploitation methodology to avoid your detections. That takes weeks of development, testing, and operational refinement. THAT is where detection actually hurts.

Having said that, you still need IOC-level detection. The pyramid is not "only detect at the top" -- it's "detect at ALL levels, but understand that the top is where the real value lives." IOCs catch the lazy and the automated. TTPs catch the skilled.

Threat Intelligence Sources

Where does this intelligence actually come from? There's a surprisingly rich ecosystem of both open-source and commercial intelligence:

# Open source threat intelligence feeds and tools:

# AlienVault OTX (Open Threat Exchange)
# https://otx.alienvault.com/
# Community-contributed IOCs, pulses (grouped indicators for
# specific campaigns), free API access
curl -s -H "X-OTX-API-KEY: YOUR_KEY" \
    "https://otx.alienvault.com/api/v1/indicators/IPv4/203.0.113.42/general"

# Abuse.ch -- three separate services:
# URLhaus: malicious URLs reported by the community
curl -s "https://urlhaus-api.abuse.ch/v1/host/" -d "host=evil.com"

# MalwareBazaar: malware sample sharing
curl -s "https://mb-api.abuse.ch/api/v1/" \
    -d "query=get_info&hash=SHA256_HASH"

# ThreatFox: IOC sharing (IPs, domains, URLs mapped to malware)
curl -s "https://threatfox-api.abuse.ch/api/v1/" \
    -d '{"query":"search_ioc","search_term":"203.0.113.42"}'

# VirusTotal -- the Swiss army knife of file/URL/IP analysis
curl -s -H "x-apikey: YOUR_KEY" \
    "https://www.virustotal.com/api/v3/files/SHA256_HASH"

# CISA Known Exploited Vulnerabilities (KEV) catalog
# https://www.cisa.gov/known-exploited-vulnerabilities-catalog
# THE authoritative list of vulns being actively exploited in the wild
# If a vuln is on this list, patch it TODAY, not next quarter

# Shodan -- the search engine for internet-connected devices
# https://www.shodan.io/
# We used this in episode 5 for reconnaissance. Same tool,
# different perspective: now we are looking for OUR exposed assets
# that match known-vulnerable configurations.

# YARA rules -- pattern-matching for malware detection
# https://github.com/Yara-Rules/rules
yara -r /path/to/rules/ /path/to/scan/

The CISA KEV catalog deserves special attention. This is the US government's curated list of vulnerabilities that are actively being exploited in the wild RIGHT NOW. Not theoretically exploitable, not proof-of-concept-exists -- actually being used by real attackers against real organizations. If a vulnerability appears on this list and it exists in your environment, your patch priority just went from "next maintenance window" to "tonight." Many organizations use KEV as a forcing function: anything on KEV gets patched within 48 hours, no exceptions, no waiting for change advisory board approval.

STIX and TAXII -- The Common Language

For threat intelligence to be useful at scale, it needs to be machine-readable and shareable. That's where STIX and TAXII come in:

#!/usr/bin/env python3
"""stix_taxii_overview.py -- the standards for sharing intel"""

import json

# STIX = Structured Threat Information eXpression
# The FORMAT for representing threat intelligence
# Think of it as JSON with a standardized schema for
# threat data: indicators, malware, threat actors,
# attack patterns, campaigns, etc.

stix_indicator = {
    "type": "indicator",
    "spec_version": "2.1",
    "id": "indicator--a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "created": "2026-06-01T00:00:00Z",
    "modified": "2026-06-01T00:00:00Z",
    "name": "APT29 C2 IP - June 2026 campaign",
    "description": "IP address used for HTTPS C2 in APT29 "
                   "campaign targeting government organizations",
    "pattern": "[ipv4-addr:value = '203.0.113.42']",
    "pattern_type": "stix",
    "valid_from": "2026-05-15T00:00:00Z",
    "valid_until": "2026-07-15T00:00:00Z",
    "kill_chain_phases": [{
        "kill_chain_name": "mitre-attack",
        "phase_name": "command-and-control"
    }],
    "confidence": 85,
    "labels": ["malicious-activity", "attribution-confirmed"],
}

# Notice the valid_from and valid_until fields.
# IOCs have an EXPIRATION DATE. An IP that was a C2 server
# in May might be a legitimate website by August. Using stale
# IOCs generates false positives and wastes analyst time.

print("=== STIX Indicator Example ===")
print(json.dumps(stix_indicator, indent=2))

# TAXII = Trusted Automated eXchange of Intelligence Information
# The TRANSPORT PROTOCOL for moving STIX data between systems
# Think of it as the delivery truck for STIX packages.
#
# STIX = the language (what you say)
# TAXII = the transport (how you deliver it)
#
# TAXII servers expose "collections" of STIX objects.
# Your SIEM/TIP polls the TAXII server periodically to
# fetch new indicators. Fully automated, no human needed.

print("\n=== TAXII Architecture ===")
print("""
  [Threat Intel Provider]
         |
    TAXII Server
    (collections of STIX objects)
         |
    TAXII Client (your SIEM/TIP polls for new data)
         |
    [Your Detection Stack]
    (SIEM rules, EDR policies, firewall blocks)
""")

# Common TAXII feeds you can connect to:
taxii_sources = [
    "CISA: https://taxii.cisa.gov/taxii2/",
    "AlienVault OTX: STIX export via API",
    "MISP: built-in TAXII server capability",
    "OpenCTI: native STIX/TAXII support",
]

print("Publicly available TAXII/STIX sources:")
for src in taxii_sources:
    print(f"  - {src}")

The valid_until field in that STIX indicator is critically important and almost universally ignored. IOCs expire. An IP address that was a C2 server last month might have been reassigned to a legitimate cloud customer this month. If you're still blocking that IP six months later, you're denying your users access to a real website and generating false positive alerts that drown out real threats. Good threat intelligence has lifecycle management -- indicators get created, get consumed, and get retired. Most organizations do the first two and completely neglect the third.

Threat Intelligence Platforms

Raw IOCs and STIX objects are useless without a platform to manage, correlate, and distribute them. Two open-source platforms dominate this space:

#!/usr/bin/env python3
"""ti_platforms.py -- MISP and OpenCTI compared"""

PLATFORMS = {
    'misp': {
        'full_name': 'Malware Information Sharing Platform',
        'type': 'Open source (Luxembourg CIRCL)',
        'primary_function': 'IOC sharing and correlation',
        'key_features': [
            'Event-based IOC organization (group indicators by incident)',
            'Automatic correlation (link related indicators across events)',
            'Feeds from dozens of organizations (CIRCL, CERT-EU, etc.)',
            'Export to SIEM formats (Splunk, QRadar, Suricata, Snort)',
            'STIX/TAXII native support',
            'Sighting system (confirm or deny IOC relevance)',
            'Galaxy clusters (attach context: threat actor, malware family)',
            'Warning lists (filter false positives from common CDN IPs, '
            'Google DNS, etc.)',
        ],
        'deployment': 'Docker or VM. Moderate complexity to set up.',
        'best_for': 'Organizations that need IOC sharing and '
                   'automated SIEM integration. The workhorse '
                   'of the threat intel community.',
    },
    'opencti': {
        'full_name': 'Open Cyber Threat Intelligence',
        'type': 'Open source (Filigran)',
        'primary_function': 'Knowledge graph of threat intelligence',
        'key_features': [
            'STIX-native data model (everything is a STIX object)',
            'Knowledge graph visualization (relationships between '
            'threat actors, campaigns, malware, infrastructure)',
            'Integrates with MISP, VirusTotal, Shodan, MITRE ATT&CK',
            'Connectors for 100+ data sources',
            'Role-based access control (share intel selectively)',
            'Automated enrichment (IP -> geolocation, ASN, reputation)',
            'Decay scoring (IOCs automatically lose confidence over time)',
        ],
        'deployment': 'Docker Compose. Resource-hungry (needs Elasticsearch, '
                     'Redis, MinIO, RabbitMQ). Minimum 16GB RAM recommended.',
        'best_for': 'Organizations that want analytical capability '
                   'beyond IOC management. See relationships between '
                   'threats, track campaigns over time, produce '
                   'intelligence products for leadership.',
    },
}

for name, data in PLATFORMS.items():
    print(f"=== {data['full_name']} ({name.upper()}) ===")
    print(f"  Type: {data['type']}")
    print(f"  Primary function: {data['primary_function']}")
    print(f"  Deployment: {data['deployment']}")
    print(f"  Best for: {data['best_for']}")
    print(f"  Features:")
    for feat in data['key_features']:
        print(f"    - {feat}")
    print()

# The choice between MISP and OpenCTI is not either/or.
# Many mature programs run BOTH:
# - MISP handles IOC ingestion, sharing, and SIEM export
# - OpenCTI handles analysis, visualization, and reporting
# - They sync with each other via STIX/TAXII
print("Mature setup: MISP (IOC operations) + OpenCTI (analysis)")
print("They integrate natively. Use both.")

That decay scoring feature in OpenCTI is worth calling out. Remember the IOC expiration problem we discussed earlier? OpenCTI solves it automatically: indicators lose confidence over time based on configurable decay curves. A fresh IOC from yesterday has 95% confidence. The same IOC three months later has 20% confidence and eventually gets retired from active detection. This prevents the stale-IOC problem without requiring manual cleanup -- which in practice never happens because nobody has time for housekeeping when there are active incidents to respond to.

The Intelligence Cycle -- From Raw Data to Actionable Intelligence

Raw data is not intelligence. A list of 50,000 IP addresses is data. "APT29 is targeting your sector using these 5 techniques, and here are the detection rules" is intelligence. The intelligence cycle is the process that transforms one into the other:

#!/usr/bin/env python3
"""intel_cycle.py -- the six-phase intelligence cycle"""

INTELLIGENCE_CYCLE = {
    1: {
        'phase': 'Direction',
        'description': 'Define what you need to know',
        'key_activities': [
            'Leadership defines intelligence requirements',
            'What threats are most relevant to our business?',
            'What decisions will this intelligence inform?',
            'Priority: focus collection, do not boil the ocean',
        ],
        'example': 'CISO requirement: "I need to know which threat '
                  'actors are actively targeting healthcare '
                  'organizations in the EU, what their primary '
                  'initial access methods are, and whether our '
                  'current detections cover those methods."',
        'common_mistake': 'No requirements at all. Analysts collect '
                         'everything, analyze nothing, produce '
                         'reports nobody reads.',
    },
    2: {
        'phase': 'Collection',
        'description': 'Gather raw data from all available sources',
        'key_activities': [
            'Open source feeds (OTX, Abuse.ch, CISA)',
            'Commercial feeds (Recorded Future, Mandiant)',
            'ISAC membership (sector-specific sharing)',
            'Dark web monitoring (forums, marketplaces)',
            'Internal data (IR findings, SOC observations)',
            'Peer organization sharing (informal networks)',
        ],
        'example': 'Pull IOCs from CIRCL MISP feed, subscribe to '
                  'H-ISAC alerts, monitor BreachForums for healthcare '
                  'database listings, review Mandiant APT reports '
                  'from the last 90 days.',
        'common_mistake': 'Collection without direction. Subscribing '
                         'to 50 feeds with no plan for what to do '
                         'with the data. Volume is not value.',
    },
    3: {
        'phase': 'Processing',
        'description': 'Normalize, deduplicate, and structure the data',
        'key_activities': [
            'Deduplicate IOCs across sources',
            'Normalize formats (everything into STIX)',
            'Enrich with context (geolocation, ASN, reputation)',
            'Filter false positives (warning lists in MISP)',
            'Tag and categorize by threat actor and campaign',
        ],
        'example': 'Import 15,000 IOCs from 5 feeds. Dedup reduces '
                  'to 8,200 unique indicators. Enrich IPs with '
                  'geolocation and hosting provider. Filter out '
                  'known CDN IPs (Cloudflare, AWS, Google). Tag '
                  'healthcare-relevant IOCs.',
        'common_mistake': 'Skipping dedup and enrichment. Dumping '
                         'raw feeds directly into the SIEM creates '
                         'massive false positive problems.',
    },
    4: {
        'phase': 'Analysis',
        'description': 'Turn processed data into actionable intelligence',
        'key_activities': [
            'Correlate indicators across sources and campaigns',
            'Assess relevance to YOUR organization specifically',
            'Determine confidence levels for each assessment',
            'Identify trends and patterns over time',
            'Produce intelligence products (reports, briefings)',
        ],
        'example': 'Analysis shows 3 separate feeds are reporting '
                  'IOCs linked to the same infrastructure cluster. '
                  'Cross-referencing with MITRE ATT&CK shows TTPs '
                  'consistent with FIN12 (healthcare ransomware). '
                  'FIN12 has targeted organizations of our size '
                  'and sector in the last 6 months. Assessment: '
                  'HIGH relevance, MEDIUM confidence.',
        'common_mistake': 'No analysis at all. Importing IOCs and '
                         'generating alerts is NOT intelligence. '
                         'Intelligence requires a human analyst '
                         'to assess meaning and relevance.',
    },
    5: {
        'phase': 'Dissemination',
        'description': 'Deliver intelligence to consumers in usable format',
        'key_activities': [
            'IOCs to SOC (automated SIEM/EDR ingestion)',
            'Campaign reports to security managers',
            'Risk briefings to executives',
            'Detection rules to engineering team',
            'Hunting queries to threat hunters',
        ],
        'example': 'Push 43 high-confidence IOCs to SIEM for '
                  'automated alerting. Send campaign brief to SOC '
                  'lead with 5 new detection rules. Schedule CISO '
                  'briefing on FIN12 risk posture.',
        'common_mistake': 'One format for all audiences. The CISO '
                         'does not need 43 IOCs. The SOC analyst '
                         'does not need a strategic risk assessment.',
    },
    6: {
        'phase': 'Feedback',
        'description': 'Evaluate whether the intelligence was useful',
        'key_activities': [
            'Did the SOC use the IOCs? Did they catch anything?',
            'Were the detection rules effective or noisy?',
            'Did leadership change decisions based on the briefing?',
            'What gaps remain? What should we collect next?',
            'Feed results back into Phase 1 (new requirements)',
        ],
        'example': 'SOC reports 2 of 43 IOCs triggered alerts -- '
                  'both were FPs (CDN infrastructure). Detection '
                  'rules caught 0 real incidents but hunting query '
                  'found historical evidence of FIN12 tool in '
                  'forensic timeline from an old incident. '
                  'Adjust: refine IOC quality filter, expand '
                  'hunting scope to last 12 months.',
        'common_mistake': 'Skipping feedback entirely. Without it '
                         'you are producing intelligence in a vacuum '
                         'with no way to improve.',
    },
}

print("=== The Intelligence Cycle ===\n")
for num, phase in INTELLIGENCE_CYCLE.items():
    print(f"Phase {num}: {phase['phase']}")
    print(f"  {phase['description']}")
    print(f"  Example: {phase['example']}")
    print(f"  Mistake: {phase['common_mistake']}")
    print()

The feedback loop (Phase 6 back to Phase 1) is what distinguishes a real intelligence program from an IOC import pipeline. Without feedback, you're producing intelligence that nobody uses, collecting data that nobody needs, and generating alerts that nobody investigates. The entire cycle exists to answer a specific question ("what threatens us?"), and the only way to know if you answered it well is to ask the consumers whether it was useful.

Threat-Informed Defense -- Connecting Intel to Action

This is where threat intelligence stops being academic and starts saving your organization from actual breaches. The concept is simple: instead of trying to defend against everything, focus your defenses on the specific threats that target YOUR industry, YOUR technology stack, YOUR geographic region:

#!/usr/bin/env python3
"""threat_informed_defense.py -- prioritize based on intel"""

def prioritize_defenses(org_profile, threat_actors):
    """Map threat actor TTPs to detection gaps and prioritize."""

    print(f"=== Threat-Informed Defense for {org_profile['name']} ===")
    print(f"Sector: {org_profile['sector']}")
    print(f"Region: {org_profile['region']}")
    print(f"\nRelevant threat actors:\n")

    all_techniques = set()
    for actor in threat_actors:
        if (org_profile['sector'] in actor['target_sectors'] or
            org_profile['region'] in actor.get('target_regions', [])):
            print(f"  {actor['name']} ({actor['motivation']})")
            print(f"    Targets: {', '.join(actor['target_sectors'])}")
            for ttp in actor['primary_ttps']:
                all_techniques.add(ttp)
                print(f"    - {ttp}")
            print()

    # Check existing detection coverage
    covered = org_profile.get('detection_coverage', set())
    gaps = all_techniques - covered

    print(f"Techniques to defend against: {len(all_techniques)}")
    print(f"Currently detected: {len(covered)}")
    print(f"GAPS: {len(gaps)}\n")

    if gaps:
        print("Priority detection rules to build:")
        for i, gap in enumerate(sorted(gaps), 1):
            print(f"  {i}. {gap}")

    return gaps


# Example: a European healthcare organization
org = {
    'name': 'EuroMed Health Services',
    'sector': 'Healthcare',
    'region': 'EU',
    'detection_coverage': {
        'T1566.001 Spearphishing Attachment',
        'T1059.001 PowerShell',
        'T1547.001 Registry Run Keys',
    }
}

actors = [
    {
        'name': 'FIN12',
        'motivation': 'Financial -- ransomware',
        'target_sectors': ['Healthcare', 'Education'],
        'primary_ttps': [
            'T1566.001 Spearphishing Attachment',
            'T1059.001 PowerShell',
            'T1003.001 LSASS Memory',
            'T1021.002 SMB/Windows Admin Shares',
            'T1486 Data Encrypted for Impact',
        ],
    },
    {
        'name': 'APT41',
        'motivation': 'Espionage + Financial (dual purpose)',
        'target_sectors': ['Healthcare', 'Technology', 'Telecom'],
        'target_regions': ['EU', 'US'],
        'primary_ttps': [
            'T1190 Exploit Public-Facing Application',
            'T1059.001 PowerShell',
            'T1003.001 LSASS Memory',
            'T1547.001 Registry Run Keys',
            'T1071.001 Web Protocols (HTTPS C2)',
        ],
    },
    {
        'name': 'Lazarus Group',
        'motivation': 'Financial -- theft, espionage',
        'target_sectors': ['Financial', 'Cryptocurrency', 'Defense'],
        'primary_ttps': [
            'T1566.002 Spearphishing Link',
            'T1059.007 JavaScript',
            'T1195.002 Supply Chain Compromise',
        ],
    },
]

gaps = prioritize_defenses(org, actors)

Notice that Lazarus Group doesn't appear in the output because they target Financial, Cryptocurrency, and Defense -- not Healthcare. That's the power of threat-informed defense: you don't waste resources building detection for Lazarus techniques if Lazarus isn't targeting your sector. You focus on FIN12 and APT41 instead. The ATT&CK Navigator we discussed in episode 50 is the visualization tool that makes this real -- you overlay your threat actors' known techniques, color-code your detection coverage, and the red gaps are your priority work items for the next quarter.

Building Your Threat Intel Program

#!/usr/bin/env python3
"""build_ti_program.py -- practical steps from zero to operational"""

IMPLEMENTATION_PLAN = {
    'week_1_2': {
        'phase': 'Foundation',
        'actions': [
            'Identify your top 3 relevant threat actors using '
            'MITRE ATT&CK Groups page + CISA advisories for your sector',
            'Subscribe to CISA KEV catalog (automated alerts)',
            'Create free accounts on: AlienVault OTX, VirusTotal, '
            'Abuse.ch (URLhaus, MalwareBazaar, ThreatFox)',
            'Document intelligence requirements with your CISO or '
            'security manager (what do they need to know?)',
        ],
        'cost': 'Free',
        'output': 'Written intelligence requirements + feed subscriptions',
    },
    'week_3_4': {
        'phase': 'IOC Operations',
        'actions': [
            'Deploy MISP in Docker (github.com/MISP/MISP)',
            'Connect MISP to 3 open source feeds (CIRCL OSINT, '
            'Abuse.ch, CISA)',
            'Configure MISP to export IOCs in your SIEM format',
            'Build first IOC-based detection rules in SIEM',
            'Establish IOC lifecycle (creation, consumption, retirement)',
        ],
        'cost': 'Free (open source) + server resources',
        'output': 'Operational MISP instance feeding your SIEM',
    },
    'month_2': {
        'phase': 'Analysis Capability',
        'actions': [
            'Map top 3 threat actors TTPs in ATT&CK Navigator',
            'Assess your current detection coverage against those TTPs',
            'Build 5 TTP-based detection rules for your top gaps',
            'Produce first threat landscape briefing for leadership',
            'Join your sector ISAC if one exists (FS-ISAC, H-ISAC, etc.)',
        ],
        'cost': 'Low (ISAC membership may have annual fee)',
        'output': 'Detection gap analysis + first TI report',
    },
    'month_3_plus': {
        'phase': 'Maturation',
        'actions': [
            'Deploy OpenCTI alongside MISP for analysis capability',
            'Establish regular threat hunting cadence based on intel',
            'Build adversary emulation exercises (episode 50) based '
            'on your top threat actors',
            'Start contributing IOCs from your incidents back to '
            'community platforms (intelligence is more valuable shared)',
            'Produce quarterly strategic intelligence briefings',
        ],
        'cost': 'Medium (analyst time is the real cost)',
        'output': 'Mature TI program with feedback loop',
    },
}

print("=== Building a TI Program from Scratch ===\n")
for timeline, data in IMPLEMENTATION_PLAN.items():
    label = timeline.replace('_', ' ').title()
    print(f"--- {label}: {data['phase']} ---")
    print(f"Cost: {data['cost']}")
    print(f"Output: {data['output']}")
    for action in data['actions']:
        print(f"  - {action}")
    print()

The implementation plan starts free and scales with maturity. You don't need a $200,000 annual Recorded Future subscription to do threat intelligence. You need free feeds, a MISP instance, and someone who actually analyzes what comes in instead of just piping it to the SIEM and forgetting about it. The analyst time is the real cost -- and the real value. Feeds without analysis are just data. An analyst who understands your organization, your threat landscape, and your detection capabilites turns that data into intelligence.

The AI Slop Connection

AI is simultaneously the best and worst thing to happen to threat intelligence, and the asymetry is uncomfortable.

On the positive side: AI processes millions of IOCs, correlates across datasets that no human could hold in their head, identifies patterns that would take analysts weeks to spot, and generates detection rules automatically. AI-powered TI platforms like Recorded Future and Microsoft Sentinel can surface relevant threats before human analysts even know they exist. A competent AI system that ingests 500 threat reports per day and says "these 3 are relevant to your organization" is genuinely, massively valuable.

On the negative side: AI generates plausible-sounding threat intelligence reports that are completely fabricated. An AI that "summarizes" a threat campaign it was never trained on will hallucinate details -- fake IOCs that block legitimate services, invented TTPs that lead you to build useless detection rules, fictional threat actor names that waste your analysts' time researching something that doesn't exist. If an analyst trusts the AI summary without verifying against primary sources, they deploy detection rules for attacks that do not exist while missing the real ones.

The rule is the same one we've applied throughout this series: AI is a tool for PROCESSING intelligence, not a SOURCE of intelligence. Use it to correlate, enrich, and prioritize. Do not use it to generate assessments you haven't verified. Every claim needs a primary source. Every IOC needs provenance. Verify everything. Trust nothing the AI says without checking it yourself.

What Comes Next

Threat intelligence gives the defender a structural advantage: knowing who targets you, what they use, and how they operate BEFORE the attack arrives. But intelligence is only as valuable as the systems that implement it. The next dimension of security asks a harder question: can you design systems that resist attack by architecture, not just by detection? Building security into the foundations -- network segmentation, zero trust, defense in depth as an architectural principle rather than a marketing buzzword -- is where organizations move from "detect and respond" to "resist and survive." It's the difference between having a fire alarm and building the structure out of fireproof materials ;-)

Exercises

Exercise 1: Set up MISP (https://github.com/MISP/MISP) in a Docker container or VM. Import a public feed (e.g., CIRCL OSINT feed). Explore: (a) how events are structured, (b) how IOCs are correlated across events, (c) how to export IOCs in a format your SIEM would accept (CSV, Snort rules, STIX). Document your setup and findings in ~/lab-notes/misp-setup.md.

Exercise 2: Select a threat actor relevant to your industry (or use APT28/Fancy Bear as default). Using ONLY public sources (MITRE ATT&CK, vendor reports, CISA advisories), build a threat profile: (a) attribution (nation-state, criminal, hacktivist), (b) target sectors, (c) known campaigns with dates, (d) top 10 TTPs mapped to ATT&CK, (e) known tools and malware families. Save to ~/lab-notes/threat-actor-profile.md.

Exercise 3: Practice the Pyramid of Pain in your lab. Create 5 detection rules at different pyramid levels: (a) a hash-based rule (detect a specific malware sample), (b) an IP-based rule (block a known C2 address), (c) a domain-based rule (alert on DNS resolution of a malicious domain), (d) a tool-based rule (detect Mimikatz execution regardless of hash), (e) a TTP-based rule (detect credential dumping behavior regardless of tool). For each, estimate how long the detection remains useful before the attacker adapts. Save to ~/lab-notes/pyramid-of-pain-rules.md.


Bedankt en tot de volgende keer!

@scipio



0
0
0.000
0 comments