DEV Community

Alex Spinov
Alex Spinov

Posted on

MITRE ATT&CK Has a Free API — Map Any Cyber Attack to Known Techniques

MITRE ATT&CK is the universal language of cybersecurity. Every SOC, every threat report, every security vendor references it. And the entire knowledge base is available through a free API.

No API key. No authentication. Pure STIX/TAXII data.

What Is ATT&CK?

ATT&CK catalogs real-world adversary tactics and techniques — not theoretical attacks, but exactly how APT groups like Lazarus, Fancy Bear, and Turla actually operate.

14 Tactics. 200+ Techniques. 130+ Threat Groups. All documented with real-world examples.

Accessing the Data

ATT&CK data is hosted on GitHub in STIX 2.1 format and also available via TAXII server:

\`python
import requests

Direct GitHub access (simplest method)

def get_attack_data():
"""Download the entire ATT&CK Enterprise dataset."""

url = "https://raw.githubusercontent.com/mitre/cti/master/enterprise-attack/enterprise-attack.json"
response = requests.get(url, timeout=60)
data = response.json()

# Count objects by type
type_counts = {}
for obj in data["objects"]:
    obj_type = obj["type"]
    type_counts[obj_type] = type_counts.get(obj_type, 0) + 1

print("ATT&CK Enterprise dataset:")
for t, c in sorted(type_counts.items(), key=lambda x: -x[1]):
    print(f"  {t}: {c}")

return data
Enter fullscreen mode Exit fullscreen mode

data = get_attack_data()
`\

Search for Techniques

\`python
def search_techniques(data, keyword):
"""Search ATT&CK techniques by keyword."""

techniques = [
    obj for obj in data["objects"]
    if obj["type"] == "attack-pattern"
    and not obj.get("revoked", False)
    and keyword.lower() in obj.get("name", "").lower()
]

for tech in techniques[:10]:
    # Get ATT&CK ID
    ext_refs = tech.get("external_references", [])
    attack_id = next((r["external_id"] for r in ext_refs 
                     if r.get("source_name") == "mitre-attack"), "?")

    name = tech["name"]
    desc = tech.get("description", "")[:100]

    # Get tactic (kill chain phase)
    phases = [p["phase_name"] for p in tech.get("kill_chain_phases", [])]

    print(f"\n{attack_id}: {name}")
    print(f"  Tactics: {', '.join(phases)}")
    print(f"  {desc}...")

return techniques
Enter fullscreen mode Exit fullscreen mode

Find all phishing techniques

search_techniques(data, "phishing")

Find all credential access techniques

search_techniques(data, "credential")
`\

Look Up Threat Groups

\`python
def get_threat_groups(data, limit=10):
"""List known APT groups from ATT&CK."""

groups = [
    obj for obj in data["objects"]
    if obj["type"] == "intrusion-set"
    and not obj.get("revoked", False)
]

print(f"Total threat groups: {len(groups)}")

for group in groups[:limit]:
    ext_refs = group.get("external_references", [])
    group_id = next((r["external_id"] for r in ext_refs 
                    if r.get("source_name") == "mitre-attack"), "?")

    name = group["name"]
    aliases = group.get("aliases", [])[:3]
    desc = group.get("description", "")[:120]

    print(f"\n{group_id}: {name}")
    if aliases:
        print(f"  Aliases: {', '.join(aliases)}")
    print(f"  {desc}...")
Enter fullscreen mode Exit fullscreen mode

get_threat_groups(data)
`\

Map a Group's Techniques

\`python
def group_techniques(data, group_name):
"""Find all techniques used by a specific threat group."""

# Find the group
group = next(
(obj for obj in data["objects"]
if obj["type"] == "intrusion-set"
and obj["name"].lower() == group_name.lower()),
None
)

if not group:
print(f"Group '{group_name}' not found")
return

group_id = group["id"]

Find relationships (group -> technique)

relationships = [
obj for obj in data["objects"]
if obj["type"] == "relationship"
and obj.get("source_ref") == group_id
and obj.get("relationship_type") == "uses"
]

Resolve technique names

technique_ids = [r["target_ref"] for r in relationships]
techniques = [
obj for obj in data["objects"]
if obj["id"] in technique_ids
and obj["type"] == "attack-pattern"
]

print(f"\n{group_name} uses {len(techniques)} known techniques:")

for tech in techniques[:15]:
ext_refs = tech.get("external_references", [])
attack_id = next((r["external_id"] for r in ext_refs
if r.get("source_name") == "mitre-attack"), "?")
print(f" {attack_id}: {tech['name']}")

Enter fullscreen mode Exit fullscreen mode




See what techniques APT29 (Cozy Bear) uses

group_techniques(data, "APT29")
`\

Build a Detection Coverage Map

\`python
def coverage_report(data, detected_techniques):
"""Show how many ATT&CK techniques your detections cover."""

all_techniques = [
obj for obj in data["objects"]
if obj["type"] == "attack-pattern"
and not obj.get("revoked", False)
and not obj.get("x_mitre_deprecated", False)
]

total = len(all_techniques)
covered = len([t for t in detected_techniques if t in
[next((r["external_id"] for r in obj.get("external_references", [])
if r.get("source_name") == "mitre-attack"), None)
for obj in all_techniques]])

print(f"Detection Coverage: {covered}/{total} ({covered/total*100:.1f}%)")

Group by tactic

tactic_coverage = {}
for tech in all_techniques:
for phase in tech.get("kill_chain_phases", []):
tactic = phase["phase_name"]
ext_refs = tech.get("external_references", [])
tid = next((r["external_id"] for r in ext_refs
if r.get("source_name") == "mitre-attack"), None)
if tactic not in tactic_coverage:
tactic_coverage[tactic] = {"total": 0, "covered": 0}
tactic_coverage[tactic]["total"] += 1
if tid in detected_techniques:
tactic_coverage[tactic]["covered"] += 1

print("\nCoverage by tactic:")
for tactic, counts in sorted(tactic_coverage.items()):
pct = counts["covered"]/counts["total"]*100 if counts["total"] else 0
bar = "█" * int(pct/5) + "░" * (20 - int(pct/5))
print(f" {tactic:<30} {bar} {pct:.0f}%")

Enter fullscreen mode Exit fullscreen mode




Example: your SIEM detects these techniques

my_detections = ["T1566.001", "T1059.001", "T1053.005", "T1078", "T1021.001"]
coverage_report(data, my_detections)
`\

What You Can Build

  • Threat modeling — map your defenses against the ATT&CK matrix
  • Detection gap analysis — find which techniques you can't detect
  • Threat reports — auto-tag incidents with ATT&CK IDs
  • Training tools — quiz SOC analysts on techniques
  • Risk scoring — weight risks based on technique prevalence

The entire cybersecurity industry runs on ATT&CK. Now you can programmatically access it.


More free security APIs and tools on my GitHub.

Top comments (0)