Skip to main content

Programmatic queries on MITRE ATT&CK threat actor techniques with natural language support

Project description

attack-query

Version CI Python 3.10+ License: MIT Ruff

Programmatic queries on MITRE ATT&CK threat actor techniques with natural language support.

Features

  • Cross-matrix support: Query Enterprise, Mobile, or ICS ATT&CK matrices
  • Natural language queries: "techniques used by APT28 or APT29 but not APT33"
  • Set operations: Union (or), intersection (and), difference (but not), complement (NOT used by)
  • Tactics queries: Query which tactics a group uses (derived from techniques)
  • Sub-technique support: Query parent/child technique relationships (T1566.001)
  • Group alias resolution: Use aliases like "Fancy Bear" instead of "APT28"
  • Software/Tool queries: Query malware and tools used by groups or implementing techniques
  • Mitigation queries: Find countermeasures for techniques or see what a mitigation covers
  • Data source queries: Explore detection data sources and data components for detection coverage
  • Campaign queries: Explore ATT&CK campaigns, attributed groups, and techniques used
  • Timeline queries: Filter campaigns and techniques by year or date range
  • Version selection: Query specific ATT&CK versions (e.g., v12.0, v15.1)
  • Similarity scoring: Find groups with similar technique profiles (Jaccard, Overlap, Cosine)
  • Smart mode: LLM-assisted query parsing for ambiguous queries (optional)
  • Fuzzy matching: Helpful suggestions when you make typos
  • Navigator export: Generate ATT&CK Navigator layer files
  • Heatmap generation: Visualize technique overlap across groups
  • Offline support: Cache data locally for offline use
  • Type-safe: Full type annotations with strict mypy checking

Installation

Using UV (recommended)

# Install from source
uv pip install git+https://github.com/swoodeng/attack-query.git

# Or clone and install in development mode
git clone https://github.com/swoodeng/attack-query.git
cd attack-query
uv pip install -e ".[dev]"

Using pip

pip install git+https://github.com/swoodeng/attack-query.git

Quick Start

Command Line

# Union: techniques used by ANY of the groups
attack-query "techniques used by APT28 or APT29"

# Intersection: techniques used by ALL groups
attack-query "techniques used by APT28 and APT29"
attack-query "techniques employed by APT28, APT29, and APT33"  # Alternative phrasing

# Difference: exclude techniques from certain groups
attack-query "techniques used by APT28 or APT29 but not APT33"
attack-query "techniques used by APT28 but not by APT29"       # "but not by" also works

# Verbose output (includes tactics)
attack-query "techniques used by APT28" -v

# Complement: techniques NOT used by a group
attack-query "techniques NOT used by APT28"

# Sub-technique queries
attack-query "sub-techniques of T1566"
attack-query "parent of T1566.001"

# Group alias resolution
attack-query "who is Fancy Bear"
attack-query "aliases of APT28"

# Software/Tool queries
attack-query "software used by APT28"
attack-query "groups using Mimikatz"
attack-query "techniques for Cobalt Strike"
attack-query "software using T1566"
attack-query "software info Mimikatz"

# Mixed software + group queries
attack-query "techniques used by Mimikatz but not APT29"           # Software minus group
attack-query "techniques used by software Mimikatz and group APT28" # Explicit qualifiers
attack-query "techniques used by both Cobalt Strike and APT28"      # Intersection

# Tactics queries
attack-query "tactics used by APT28"             # Tactics from group's techniques
attack-query "tactics used by APT28 and APT29"   # Tactics shared by both groups
attack-query "tactics used by APT28 or APT29"    # Tactics from either group
attack-query "tactics not used by APT28"         # Tactics NOT used by a group

# Mitigation queries
attack-query "mitigations for T1566"
attack-query "how to mitigate T1566"
attack-query "techniques mitigated by M1031"
attack-query "mitigation info M1017"

# Data source queries
attack-query "data sources"
attack-query "data source info Process"
attack-query "data components"
attack-query "data component info Process Creation"
attack-query "techniques detectable by Process Creation"

# Campaign queries
attack-query "campaigns"                          # List all campaigns
attack-query "campaigns by APT28"                 # Campaigns attributed to a group
attack-query "techniques in C0027"                # Techniques used in a campaign
attack-query "campaign info C0027"                # Campaign details

# Timeline queries
attack-query "campaigns in 2023"                  # Campaigns active in a year
attack-query "campaigns between 2022 and 2024"    # Campaigns in date range
attack-query "techniques used in 2023"            # Techniques from campaigns in year

# Similarity scoring
attack-query "groups similar to APT28"            # Find groups with similar TTPs
attack-query "similarity APT28 APT29"             # Detailed metrics between two groups
attack-query "groups like APT28 threshold 0.5"    # With minimum similarity score
attack-query "groups similar to APT28 using cosine"  # Different similarity metric

# Export formats
attack-query "techniques used by APT28" --format csv       # CSV output
attack-query "techniques used by APT28" --format md        # Markdown table
attack-query "techniques used by APT28" --format layer     # Navigator layer JSON
attack-query "techniques used by APT28" --json             # JSON output

# Use a specific ATT&CK version
attack-query --version 12.0 "techniques used by APT28"

# Use a different matrix (Mobile or ICS)
attack-query --matrix mobile "techniques used by APT28"
attack-query --matrix ics "techniques used by ALLANITE"

# List available versions
attack-query --list-versions

# Interactive mode
attack-query

Python API

from attack_query import ATTACKDataStore, ATTACKQueryEngine, Matrix

# Load latest ATT&CK data (Enterprise matrix by default)
store = ATTACKDataStore()
store.load()

# Or load a specific version
store = ATTACKDataStore(version="12.0")
store.load()

# Or load a different matrix (Mobile or ICS)
store = ATTACKDataStore(matrix=Matrix.MOBILE)
store.load()

store = ATTACKDataStore(matrix="ics")  # Also accepts string
store.load()

# Create query engine
engine = ATTACKQueryEngine(store)

# Get techniques used by a group
apt28_techniques = engine.get_group_techniques("APT28")

# Set operations
shared = engine.techniques_intersection(["APT28", "APT29"])
unique_to_apt28_29 = engine.techniques_difference(
    include_groups=["APT28", "APT29"],
    exclude_groups=["APT33"]
)

# Compare groups
comparison = engine.compare_groups("APT28", "APT29")
print(f"Jaccard similarity: {comparison['jaccard_similarity']:.1%}")

# Export to Navigator
layer = engine.export_navigator_layer(
    unique_to_apt28_29,
    name="Unique to APT28/29"
)

Natural Language Parser

from attack_query import ATTACKDataStore, ATTACKQueryEngine, NLQueryParser

store = ATTACKDataStore()
store.load()
engine = ATTACKQueryEngine(store)
parser = NLQueryParser(engine)

# Parse and execute natural language queries
# 'or' = union, 'and' = intersection, 'but not' = difference
results = parser.parse_and_execute(
    "techniques used by APT28 or APT29 but not APT33"
)

# Access results
for technique in results["techniques"]:
    print(f"{technique['id']}: {technique['name']}")

Supported Query Patterns

Pattern Example Set Operation
Single group techniques used by APT28
Union (ANY) techniques used by APT28 or APT29 A ∪ B
Intersection (ALL) techniques used by APT28 and APT29 A ∩ B
Comma-list with and techniques employed by APT28, APT29, and APT33 A ∩ B ∩ C
Union with exclusion techniques used by APT28 or APT29 but not APT33 (A ∪ B) − C
Intersection with exclusion techniques used by APT28 and APT29 but not APT33 (A ∩ B) − C
Complement techniques NOT used by APT28 Ā (all − A)
Sub-techniques sub-techniques of T1566
Parent technique parent of T1566.001
Group alias lookup who is Fancy Bear
List aliases aliases of APT28
Tactic filter techniques used by APT28 for initial access
Tactics by group tactics used by APT28
Tactics intersection tactics used by APT28 and APT29 A ∩ B
Tactics union tactics used by APT28 or APT29 A ∪ B
Tactics complement tactics not used by APT28 Ā (all − A)
Reverse lookup groups using T1566 x ∈ A
Comparison compare APT28 and APT29 Shows ∩, A−B, B−A
Software by group software used by APT28
Groups by software groups using Mimikatz
Techniques by software techniques for Cobalt Strike
Software by technique software using T1566
Software info software info Mimikatz
Mixed: software + group techniques used by Mimikatz but not APT29 S − G
Mixed: explicit qualifiers techniques used by software X and group Y S ∩ G
Mixed: both keyword techniques used by both Cobalt Strike and APT28 S ∩ G
Mitigations for technique mitigations for T1566
Techniques by mitigation techniques mitigated by M1031
Mitigation info mitigation info M1017
List data sources data sources
Data source info data source info Process
List data components data components
Data component info data component info Process Creation
Techniques by data component techniques detectable by Process Creation
List campaigns campaigns
Campaigns by group campaigns by APT28
Techniques in campaign techniques in C0027
Campaign info campaign info C0027
Campaigns in year campaigns in 2023
Campaigns in range campaigns between 2022 and 2024
Techniques in year techniques used in 2023
Techniques in range techniques between 2022 and 2024
Similar groups groups similar to APT28
Group similarity similarity APT28 APT29 Jaccard, Overlap, Cosine
Similarity with threshold groups like APT28 threshold 0.5
Similarity with metric groups similar to APT28 using cosine
Export to CSV --format csv
Export to Markdown --format md
Export to Navigator --format layer

Matrix Selection

The tool supports all three ATT&CK matrices:

Matrix Flag Description
Enterprise --matrix enterprise (default) Techniques for Windows, Linux, macOS, Cloud, etc.
Mobile --matrix mobile Techniques for Android and iOS
ICS --matrix ics Techniques for Industrial Control Systems
# Query Mobile ATT&CK (default is Enterprise)
attack-query --matrix mobile "techniques used by APT28"

# Query ICS ATT&CK
attack-query --matrix ics "techniques used by ALLANITE"

# Combine with version selection
attack-query --matrix mobile --version 12.0 "groups"

Version Selection

The tool supports specific ATT&CK versions for reproducibility:

# List available versions
attack-query --list-versions

# Use ATT&CK v12.0 (October 2022)
attack-query --version 12.0 "techniques used by APT28"

Caching Behavior

Data Type Cache Duration Example Location
Specific version Permanent (immutable) ~/.cache/attack/enterprise-attack-12.0.json
Latest version 7 days ~/.cache/attack/mobile-attack-latest.json

Each matrix is cached separately, so you can work with Enterprise and Mobile data without re-downloading.

Smart Mode (LLM-Assisted)

Enable smart mode for LLM-assisted query parsing. Useful for ambiguous or non-standard queries.

Installation

# Install with smart mode dependencies
pip install attack-query[smart]

Usage

# Use smart mode with default model (ollama:llama3.2)
attack-query --smart "what attacks does fancy bear do"

# Specify a different model
attack-query --smart --model ollama:mistral "show me APT28 tools"
attack-query --smart --model openai:gpt-4o-mini "phishing techniques by russian groups"

Configuration

# Environment variables
export ATTACK_QUERY_COMPLETION_MODEL=ollama:llama3.2  # Default model
export OLLAMA_BASE_URL=http://localhost:11434         # Ollama endpoint
export OPENAI_API_KEY=sk-...                          # For OpenAI models

Supported Providers

Provider Model Examples Notes
ollama llama3.2, mistral, codellama Local, requires Ollama running
openai gpt-4o-mini, gpt-4o Cloud, requires API key

Fuzzy Matching

Even without smart mode, attack-query provides fuzzy matching suggestions when queries fail:

$ attack-query "techniques used by APT27"

❌ Error: Could not parse query
   Did you mean:
      • 'APT27' → 'APT28'
   Try pattern: techniques used by {GROUP}

Limitations

Temporal queries for groups: ATT&CK data does not include timestamps for when a specific group used a specific technique. Queries like "techniques APT28 used in 2024" are not possible. The temporal data exists only for campaigns (which have first_seen/last_seen dates).

What works:

  • "techniques used by APT28 for initial access" — tactic + group ✅
  • "techniques used in 2024" — techniques from campaigns active in 2024 ✅
  • "techniques APT28 used in 2024" — not supported (no temporal data for group-technique mappings) ❌

Export Formats

Export query results in different formats:

Command Line

# CSV format for spreadsheets
attack-query "techniques used by APT28" --format csv > apt28.csv

# Markdown format for documentation
attack-query "techniques used by APT28" --format md > apt28.md

# Navigator layer for visualization
attack-query "techniques used by APT28" --format layer > apt28_layer.json

# JSON format for scripting
attack-query "techniques used by APT28" --json > apt28.json

# CSV with descriptions (verbose mode)
attack-query "techniques used by APT28" --format csv -v > apt28_full.csv

Interactive Mode

query> techniques used by APT28
query> export csv results.csv      # Export to CSV
query> export md results.md        # Export to Markdown
query> export layer.json           # Export to Navigator layer

Navigator Layer Export

Export query results as ATT&CK Navigator layer files:

from attack_query import ATTACKDataStore, ATTACKQueryEngine
import json

store = ATTACKDataStore()
store.load()
engine = ATTACKQueryEngine(store)

# Get techniques
techniques = engine.techniques_difference(["APT28", "APT29"], ["APT33"])

# Export as Navigator layer
layer = engine.export_navigator_layer(
    techniques,
    name="APT28/29 Unique Techniques",
    description="Techniques used by APT28 or APT29 but not APT33",
    color="#ff6666"
)

# Save to file
with open("layer.json", "w") as f:
    json.dump(layer, f, indent=2)

Then import the layer at https://mitre-attack.github.io/attack-navigator/

Development

Setup

git clone https://github.com/swoodeng/attack-query.git
cd attack-query
uv venv
source .venv/bin/activate  # or `.venv\Scripts\activate` on Windows
uv pip install -e ".[dev]"

Running Tests

pytest
pytest --cov=attack_query  # with coverage

Code Quality

ruff check src tests       # linting
ruff format src tests      # formatting
mypy src                   # type checking

Data Source

This tool uses the official MITRE ATT&CK STIX data from: https://github.com/mitre-attack/attack-stix-data

License

MIT License - see LICENSE for details.

Related Projects

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

attack_query-0.6.0.tar.gz (90.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

attack_query-0.6.0-py3-none-any.whl (48.6 kB view details)

Uploaded Python 3

File details

Details for the file attack_query-0.6.0.tar.gz.

File metadata

  • Download URL: attack_query-0.6.0.tar.gz
  • Upload date:
  • Size: 90.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.9.11 {"installer":{"name":"uv","version":"0.9.11"},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for attack_query-0.6.0.tar.gz
Algorithm Hash digest
SHA256 844224986f91fbac2b2699e964a0541b0f4429271eebf2166d8906ace222cc72
MD5 8404a57979e71e52c9a5933ad1dfb7f0
BLAKE2b-256 1c4168bb6b0c5990fd63d081b8cce0717bd2b241cfb04eea565c1cf87be554bb

See more details on using hashes here.

File details

Details for the file attack_query-0.6.0-py3-none-any.whl.

File metadata

  • Download URL: attack_query-0.6.0-py3-none-any.whl
  • Upload date:
  • Size: 48.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.9.11 {"installer":{"name":"uv","version":"0.9.11"},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for attack_query-0.6.0-py3-none-any.whl
Algorithm Hash digest
SHA256 baad3ee74ba61cf66d2d65c308c1590eaa993b49dd38f85d271a3c9f5ac0fbf2
MD5 2e40a0559e227ed7f4cb0d6872acbf04
BLAKE2b-256 1fee63a1d370e493a77d98d5b9880eee2db89f78f54f37fc3669d65dea225ae8

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page