analyzing-apt-group-with-mitre-navigator

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Analyzing APT Group with MITRE ATT&CK Navigator

使用MITRE ATT&CK Navigator分析APT组织

Overview

概述

MITRE ATT&CK Navigator is a web-based tool for annotating and exploring ATT&CK matrices, enabling analysts to visualize threat actor technique coverage, compare multiple APT groups, identify detection gaps, and build threat-informed defense strategies. This skill covers querying ATT&CK data programmatically, mapping APT group TTPs to Navigator layers, creating multi-layer overlays for gap analysis, and generating actionable intelligence reports for detection engineering teams.
MITRE ATT&CK Navigator是一款基于Web的工具,用于注释和探索ATT&CK矩阵,使分析人员能够可视化威胁行为者的技术覆盖范围、比较多个APT组织、识别检测缺口,并构建基于威胁的防御策略。本技能涵盖通过编程方式查询ATT&CK数据、将APT组织的TTP映射到Navigator图层、创建用于缺口分析的多层叠加层,以及为检测工程团队生成可操作的情报报告。

When to Use

使用场景

  • When investigating security incidents that require analyzing apt group with mitre navigator
  • When building detection rules or threat hunting queries for this domain
  • When SOC analysts need structured procedures for this analysis type
  • When validating security monitoring coverage for related attack techniques
  • 当调查需要用MITRE Navigator分析APT组织的安全事件时
  • 当为此领域构建检测规则或威胁狩猎查询时
  • 当SOC分析人员需要此类分析的结构化流程时
  • 当验证相关攻击技术的安全监控覆盖范围时

Prerequisites

前置条件

  • Python 3.9+ with
    attackcti
    ,
    mitreattack-python
    ,
    stix2
    ,
    requests
    libraries
  • ATT&CK Navigator (https://mitre-attack.github.io/attack-navigator/) or local deployment
  • Understanding of ATT&CK Enterprise matrix: 14 Tactics, 200+ Techniques, Sub-techniques
  • Access to threat intelligence reports or MISP/OpenCTI for threat actor data
  • Familiarity with STIX 2.1 Intrusion Set and Attack Pattern objects
  • Python 3.9+ 及
    attackcti
    mitreattack-python
    stix2
    requests
  • ATT&CK Navigator(https://mitre-attack.github.io/attack-navigator/)或本地部署版本
  • 了解ATT&CK企业矩阵:14个战术、200+个技术及子技术
  • 可访问威胁情报报告或MISP/OpenCTI获取威胁行为者数据
  • 熟悉STIX 2.1入侵集(Intrusion Set)和攻击模式(Attack Pattern)对象

Key Concepts

核心概念

ATT&CK Navigator Layers

ATT&CK Navigator图层

Navigator layers are JSON files that annotate ATT&CK techniques with scores, colors, comments, and metadata. Each layer can represent a single APT group's technique usage, a detection capability map, or a combined overlay. Layer version 4.5 supports enterprise-attack, mobile-attack, and ics-attack domains with filtering by platform (Windows, Linux, macOS, Cloud, Azure AD, Office 365, SaaS).
Navigator图层是为ATT&CK技术添加分数、颜色、注释和元数据的JSON文件。每个图层可代表单个APT组织的技术使用情况、检测能力映射或组合叠加层。4.5版本的图层支持企业攻击、移动攻击和ICS攻击领域,并可按平台(Windows、Linux、macOS、Cloud、Azure AD、Office 365、SaaS)过滤。

APT Group Profiles in ATT&CK

ATT&CK中的APT组织档案

ATT&CK catalogs over 140 threat groups with documented technique usage. Each group profile includes aliases, targeted sectors, associated campaigns, software used, and technique mappings with procedure-level detail. Groups are identified by G-codes (e.g., G0016 for APT29, G0007 for APT28, G0032 for Lazarus Group).
ATT&CK收录了超过140个威胁组织的已记录技术使用情况。每个组织档案包括别名、目标行业、相关活动、使用的软件,以及带有流程级细节的技术映射。组织通过G代码标识(例如,APT29对应G0016,APT28对应G0007,Lazarus Group对应G0032)。

Multi-Layer Analysis

多层分析

The Navigator supports loading multiple layers simultaneously, allowing analysts to overlay threat actor TTPs against detection coverage to identify gaps, compare multiple APT groups to find common techniques worth prioritizing, and track technique coverage changes over time.
Navigator支持同时加载多个图层,分析人员可将威胁行为者的TTP与检测覆盖范围叠加以识别缺口,比较多个APT组织以发现值得优先处理的通用技术,并跟踪技术覆盖范围随时间的变化。

Workflow

工作流程

Step 1: Query ATT&CK Data for APT Group

步骤1:查询APT组织的ATT&CK数据

python
from attackcti import attack_client
import json

lift = attack_client()
python
from attackcti import attack_client
import json

lift = attack_client()

Get all threat groups

Get all threat groups

groups = lift.get_groups() print(f"Total ATT&CK groups: {len(groups)}")
groups = lift.get_groups() print(f"Total ATT&CK groups: {len(groups)}")

Find APT29 (Cozy Bear / Midnight Blizzard)

Find APT29 (Cozy Bear / Midnight Blizzard)

apt29 = next((g for g in groups if g.get('name') == 'APT29'), None) if apt29: print(f"Group: {apt29['name']}") print(f"Aliases: {apt29.get('aliases', [])}") print(f"Description: {apt29.get('description', '')[:300]}")
apt29 = next((g for g in groups if g.get('name') == 'APT29'), None) if apt29: print(f"Group: {apt29['name']}") print(f"Aliases: {apt29.get('aliases', [])}") print(f"Description: {apt29.get('description', '')[:300]}")

Get techniques used by APT29 (G0016)

Get techniques used by APT29 (G0016)

techniques = lift.get_techniques_used_by_group("G0016") print(f"APT29 uses {len(techniques)} techniques")
technique_map = {} for tech in techniques: 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: tactics = [p.get("phase_name", "") for p in tech.get("kill_chain_phases", [])] technique_map[tech_id] = { "name": tech.get("name", ""), "tactics": tactics, "description": tech.get("description", "")[:500], "platforms": tech.get("x_mitre_platforms", []), "data_sources": tech.get("x_mitre_data_sources", []), }
undefined
techniques = lift.get_techniques_used_by_group("G0016") print(f"APT29 uses {len(techniques)} techniques")
technique_map = {} for tech in techniques: 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: tactics = [p.get("phase_name", "") for p in tech.get("kill_chain_phases", [])] technique_map[tech_id] = { "name": tech.get("name", ""), "tactics": tactics, "description": tech.get("description", "")[:500], "platforms": tech.get("x_mitre_platforms", []), "data_sources": tech.get("x_mitre_data_sources", []), }
undefined

Step 2: Generate Navigator Layer JSON

步骤2:生成Navigator图层JSON

python
def create_navigator_layer(group_name, technique_map, color="#ff6666"):
    techniques_list = []
    for tech_id, info in technique_map.items():
        for tactic in info["tactics"]:
            techniques_list.append({
                "techniqueID": tech_id,
                "tactic": tactic,
                "color": color,
                "comment": info["name"],
                "enabled": True,
                "score": 100,
                "metadata": [
                    {"name": "group", "value": group_name},
                    {"name": "platforms", "value": ", ".join(info["platforms"])},
                ],
            })

    layer = {
        "name": f"{group_name} TTP Coverage",
        "versions": {"attack": "16.1", "navigator": "5.1.0", "layer": "4.5"},
        "domain": "enterprise-attack",
        "description": f"Techniques attributed to {group_name}",
        "filters": {
            "platforms": ["Linux", "macOS", "Windows", "Cloud",
                          "Azure AD", "Office 365", "SaaS", "Google Workspace"]
        },
        "sorting": 0,
        "layout": {
            "layout": "side", "aggregateFunction": "average",
            "showID": True, "showName": True,
            "showAggregateScores": False, "countUnscored": False,
        },
        "hideDisabled": False,
        "techniques": techniques_list,
        "gradient": {"colors": ["#ffffff", color], "minValue": 0, "maxValue": 100},
        "legendItems": [
            {"label": f"Used by {group_name}", "color": color},
            {"label": "Not observed", "color": "#ffffff"},
        ],
        "showTacticRowBackground": True,
        "tacticRowBackground": "#dddddd",
        "selectTechniquesAcrossTactics": True,
        "selectSubtechniquesWithParent": False,
        "selectVisibleTechniques": False,
    }
    return layer

layer = create_navigator_layer("APT29", technique_map)
with open("apt29_layer.json", "w") as f:
    json.dump(layer, f, indent=2)
print("[+] Layer saved: apt29_layer.json")
python
def create_navigator_layer(group_name, technique_map, color="#ff6666"):
    techniques_list = []
    for tech_id, info in technique_map.items():
        for tactic in info["tactics"]:
            techniques_list.append({
                "techniqueID": tech_id,
                "tactic": tactic,
                "color": color,
                "comment": info["name"],
                "enabled": True,
                "score": 100,
                "metadata": [
                    {"name": "group", "value": group_name},
                    {"name": "platforms", "value": ", ".join(info["platforms"])},
                ],
            })

    layer = {
        "name": f"{group_name} TTP Coverage",
        "versions": {"attack": "16.1", "navigator": "5.1.0", "layer": "4.5"},
        "domain": "enterprise-attack",
        "description": f"Techniques attributed to {group_name}",
        "filters": {
            "platforms": ["Linux", "macOS", "Windows", "Cloud",
                          "Azure AD", "Office 365", "SaaS", "Google Workspace"]
        },
        "sorting": 0,
        "layout": {
            "layout": "side", "aggregateFunction": "average",
            "showID": True, "showName": True,
            "showAggregateScores": False, "countUnscored": False,
        },
        "hideDisabled": False,
        "techniques": techniques_list,
        "gradient": {"colors": ["#ffffff", color], "minValue": 0, "maxValue": 100},
        "legendItems": [
            {"label": f"Used by {group_name}", "color": color},
            {"label": "Not observed", "color": "#ffffff"},
        ],
        "showTacticRowBackground": True,
        "tacticRowBackground": "#dddddd",
        "selectTechniquesAcrossTactics": True,
        "selectSubtechniquesWithParent": False,
        "selectVisibleTechniques": False,
    }
    return layer

layer = create_navigator_layer("APT29", technique_map)
with open("apt29_layer.json", "w") as f:
    json.dump(layer, f, indent=2)
print("[+] Layer saved: apt29_layer.json")

Step 3: Compare Multiple APT Groups

步骤3:比较多个APT组织

python
groups_to_compare = {"G0016": "APT29", "G0007": "APT28", "G0032": "Lazarus Group"}
group_techniques = {}

for gid, gname in groups_to_compare.items():
    techs = lift.get_techniques_used_by_group(gid)
    tech_ids = set()
    for t in techs:
        for ref in t.get("external_references", []):
            if ref.get("source_name") == "mitre-attack":
                tech_ids.add(ref.get("external_id", ""))
    group_techniques[gname] = tech_ids

common_to_all = set.intersection(*group_techniques.values())
print(f"Techniques common to all groups: {len(common_to_all)}")
for tid in sorted(common_to_all):
    print(f"  {tid}")

for gname, techs in group_techniques.items():
    others = set.union(*[t for n, t in group_techniques.items() if n != gname])
    unique = techs - others
    print(f"\nUnique to {gname}: {len(unique)} techniques")
python
groups_to_compare = {"G0016": "APT29", "G0007": "APT28", "G0032": "Lazarus Group"}
group_techniques = {}

for gid, gname in groups_to_compare.items():
    techs = lift.get_techniques_used_by_group(gid)
    tech_ids = set()
    for t in techs:
        for ref in t.get("external_references", []):
            if ref.get("source_name") == "mitre-attack":
                tech_ids.add(ref.get("external_id", ""))
    group_techniques[gname] = tech_ids

common_to_all = set.intersection(*group_techniques.values())
print(f"Techniques common to all groups: {len(common_to_all)}")
for tid in sorted(common_to_all):
    print(f"  {tid}")

for gname, techs in group_techniques.items():
    others = set.union(*[t for n, t in group_techniques.items() if n != gname])
    unique = techs - others
    print(f"\nUnique to {gname}: {len(unique)} techniques")

Step 4: Detection Gap Analysis with Layer Overlay

步骤4:通过图层叠加进行检测缺口分析

python
undefined
python
undefined

Define your current detection capabilities

Define your current detection capabilities

detected_techniques = { "T1059", "T1059.001", "T1071", "T1071.001", "T1566", "T1566.001", "T1547", "T1547.001", "T1053", "T1053.005", "T1078", "T1027", }
actor_techniques = set(technique_map.keys()) covered = actor_techniques.intersection(detected_techniques) gaps = actor_techniques - detected_techniques
print(f"=== Detection Gap Analysis for APT29 ===") print(f"Actor techniques: {len(actor_techniques)}") print(f"Detected: {len(covered)} ({len(covered)/len(actor_techniques)*100:.0f}%)") print(f"Gaps: {len(gaps)} ({len(gaps)/len(actor_techniques)*100:.0f}%)")
detected_techniques = { "T1059", "T1059.001", "T1071", "T1071.001", "T1566", "T1566.001", "T1547", "T1547.001", "T1053", "T1053.005", "T1078", "T1027", }
actor_techniques = set(technique_map.keys()) covered = actor_techniques.intersection(detected_techniques) gaps = actor_techniques - detected_techniques
print(f"=== Detection Gap Analysis for APT29 ===") print(f"Actor techniques: {len(actor_techniques)}") print(f"Detected: {len(covered)} ({len(covered)/len(actor_techniques)*100:.0f}%)") print(f"Gaps: {len(gaps)} ({len(gaps)/len(actor_techniques)*100:.0f}%)")

Create gap layer (red = undetected, green = detected)

Create gap layer (red = undetected, green = detected)

gap_techniques = [] for tech_id in actor_techniques: info = technique_map.get(tech_id, {}) for tactic in info.get("tactics", [""]): color = "#66ff66" if tech_id in detected_techniques else "#ff3333" gap_techniques.append({ "techniqueID": tech_id, "tactic": tactic, "color": color, "comment": f"{'DETECTED' if tech_id in detected_techniques else 'GAP'}: {info.get('name', '')}", "enabled": True, "score": 100 if tech_id in detected_techniques else 0, })
gap_layer = { "name": "APT29 Detection Gap Analysis", "versions": {"attack": "16.1", "navigator": "5.1.0", "layer": "4.5"}, "domain": "enterprise-attack", "description": "Green = detected, Red = gap", "techniques": gap_techniques, "gradient": {"colors": ["#ff3333", "#66ff66"], "minValue": 0, "maxValue": 100}, "legendItems": [ {"label": "Detected", "color": "#66ff66"}, {"label": "Detection Gap", "color": "#ff3333"}, ], } with open("apt29_gap_layer.json", "w") as f: json.dump(gap_layer, f, indent=2)
undefined
gap_techniques = [] for tech_id in actor_techniques: info = technique_map.get(tech_id, {}) for tactic in info.get("tactics", [""]): color = "#66ff66" if tech_id in detected_techniques else "#ff3333" gap_techniques.append({ "techniqueID": tech_id, "tactic": tactic, "color": color, "comment": f"{'DETECTED' if tech_id in detected_techniques else 'GAP'}: {info.get('name', '')}", "enabled": True, "score": 100 if tech_id in detected_techniques else 0, })
gap_layer = { "name": "APT29 Detection Gap Analysis", "versions": {"attack": "16.1", "navigator": "5.1.0", "layer": "4.5"}, "domain": "enterprise-attack", "description": "Green = detected, Red = gap", "techniques": gap_techniques, "gradient": {"colors": ["#ff3333", "#66ff66"], "minValue": 0, "maxValue": 100}, "legendItems": [ {"label": "Detected", "color": "#66ff66"}, {"label": "Detection Gap", "color": "#ff3333"}, ], } with open("apt29_gap_layer.json", "w") as f: json.dump(gap_layer, f, indent=2)
undefined

Step 5: Tactic Breakdown Analysis

步骤5:战术细分分析

python
from collections import defaultdict

tactic_breakdown = defaultdict(list)
for tech_id, info in technique_map.items():
    for tactic in info["tactics"]:
        tactic_breakdown[tactic].append({"id": tech_id, "name": info["name"]})

tactic_order = [
    "reconnaissance", "resource-development", "initial-access",
    "execution", "persistence", "privilege-escalation",
    "defense-evasion", "credential-access", "discovery",
    "lateral-movement", "collection", "command-and-control",
    "exfiltration", "impact",
]

print("\n=== APT29 Tactic Breakdown ===")
for tactic in tactic_order:
    techs = tactic_breakdown.get(tactic, [])
    if techs:
        print(f"\n{tactic.upper()} ({len(techs)} techniques):")
        for t in techs:
            print(f"  {t['id']}: {t['name']}")
python
from collections import defaultdict

tactic_breakdown = defaultdict(list)
for tech_id, info in technique_map.items():
    for tactic in info["tactics"]:
        tactic_breakdown[tactic].append({"id": tech_id, "name": info["name"]})

tactic_order = [
    "reconnaissance", "resource-development", "initial-access",
    "execution", "persistence", "privilege-escalation",
    "defense-evasion", "credential-access", "discovery",
    "lateral-movement", "collection", "command-and-control",
    "exfiltration", "impact",
]

print("\n=== APT29 Tactic Breakdown ===")
for tactic in tactic_order:
    techs = tactic_breakdown.get(tactic, [])
    if techs:
        print(f"\n{tactic.upper()} ({len(techs)} techniques):")
        for t in techs:
            print(f"  {t['id']}: {t['name']}")

Validation Criteria

验证标准

  • ATT&CK data queried successfully via TAXII server
  • APT group mapped to all documented techniques with procedure examples
  • Navigator layer JSON validates and renders correctly in ATT&CK Navigator
  • Multi-layer overlay shows threat actor vs. detection coverage
  • Detection gap analysis identifies unmonitored techniques with data source recommendations
  • Cross-group comparison reveals shared and unique TTPs
  • Output is actionable for detection engineering prioritization
  • 成功通过TAXII服务器查询ATT&CK数据
  • APT组织已映射到所有带流程示例的已记录技术
  • Navigator图层JSON在ATT&CK Navigator中验证并正确渲染
  • 多层叠加层显示威胁行为者与检测覆盖范围的对比
  • 检测缺口分析识别出未监控的技术并提供数据源建议
  • 跨组织比较揭示了共享和独特的TTP
  • 输出可用于检测工程的优先级排序

References

参考资料