Detection rules › Elastic

Ollama DNS Query to Untrusted Domain

Status
production
Kind
building block (feeds higher-level correlation rules; not a standalone alert)
Severity
low
Time window
119m
Author
Elastic
Source
github.com/elastic/detection-rules

Detects Ollama DNS queries to domains outside official infrastructure. Adversaries can redirect Ollama to pull models from attacker-controlled servers via OLLAMA_HOST or custom manifests. Malicious models may contain backdoors, exploit parsing vulnerabilities like CVE-2025-1975, or poison inference outputs.

MITRE ATT&CK coverage

MITRE ATLAS coverage

Adversarial-ML threat framework (not MITRE ATT&CK).

Rule body elastic

[metadata]
creation_date = "2026/01/09"
integration = ["endpoint"]
maturity = "production"
updated_date = "2026/03/24"

[rule]
author = ["Elastic"]
building_block_type = "default"
description = """
Detects Ollama DNS queries to domains outside official infrastructure. Adversaries can redirect Ollama to pull models
from attacker-controlled servers via OLLAMA_HOST or custom manifests. Malicious models may contain backdoors, exploit
parsing vulnerabilities like CVE-2025-1975, or poison inference outputs.
"""
from = "now-119m"
index = ["logs-endpoint.events.network-*"]
interval = "60m"
language = "eql"
license = "Elastic License v2"
name = "Ollama DNS Query to Untrusted Domain"
references = [
    "https://www.greynoise.io/blog/threat-actors-actively-targeting-llms",
    "https://atlas.mitre.org/techniques/AML.T0010.003",
    "https://nvd.nist.gov/vuln/detail/CVE-2025-1975",
]
risk_score = 21
rule_id = "e9a3b2c1-d4f5-6789-0abc-def123456789"
severity = "low"
tags = [
    "Domain: Endpoint",
    "OS: Linux",
    "OS: macOS",
    "OS: Windows",
    "Use Case: Threat Detection",
    "Tactic: Command and Control",
    "Data Source: Elastic Defend",
    "Domain: LLM",
    "Mitre Atlas: T0010.003",
    "Rule Type: BBR",
]
timestamp_override = "event.ingested"
type = "eql"

query = '''
network where event.action == "lookup_requested" and
  process.name in ("ollama", "ollama.exe") and
  dns.question.name != null and
  not dns.question.name : (
    "ollama.ai", "*.ollama.ai", "ollama.com", "*.ollama.com",
    "github.com", "*.github.com", "*.githubusercontent.com",
    "*.r2.cloudflarestorage.com", "*.cloudflare.com", "*.cloudflarestorage.com",
    "localhost", "*.local", "*.internal", "*.localdomain"
  )
'''


[[rule.threat]]
framework = "MITRE ATT&CK"

[[rule.threat.technique]]
id = "T1105"
name = "Ingress Tool Transfer"
reference = "https://attack.mitre.org/techniques/T1105/"

[rule.threat.tactic]
id = "TA0011"
name = "Command and Control"
reference = "https://attack.mitre.org/tactics/TA0011/"

[[rule.threat]]
framework = "MITRE ATT&CK"

[[rule.threat.technique]]
id = "T1195"
name = "Supply Chain Compromise"
reference = "https://attack.mitre.org/techniques/T1195/"

[[rule.threat.technique.subtechnique]]
id = "T1195.001"
name = "Compromise Software Dependencies and Development Tools"
reference = "https://attack.mitre.org/techniques/T1195/001/"

[[rule.threat.technique.subtechnique]]
id = "T1195.002"
name = "Compromise Software Supply Chain"
reference = "https://attack.mitre.org/techniques/T1195/002/"

[rule.threat.tactic]
id = "TA0001"
name = "Initial Access"
reference = "https://attack.mitre.org/tactics/TA0001/"

Stages and Predicates

Stage 1: network

network where event.action == "lookup_requested" and
  process.name in ("ollama", "ollama.exe") and
  dns.question.name != null and
  not dns.question.name : (
    "ollama.ai", "*.ollama.ai", "ollama.com", "*.ollama.com",
    "github.com", "*.github.com", "*.githubusercontent.com",
    "*.r2.cloudflarestorage.com", "*.cloudflare.com", "*.cloudflarestorage.com",
    "localhost", "*.local", "*.internal", "*.localdomain"
  )

Exclusions

Top-level NOT(...) conjuncts: predicates this rule actively suppresses.

FieldKindExcluded values
dns.question.namewildcardollama.ai, *.ollama.ai, ollama.com, *.ollama.com, github.com, *.github.com, *.githubusercontent.com, *.r2.cloudflarestorage.com, *.cloudflare.com, *.cloudflarestorage.com, localhost, *.local, *.internal, *.localdomain

Indicators

Each row is a field, operator, and value that the rule matches. The corpus column counts how many other rules in the catalog look for the same combination: high numbers point to widely-used, community-vetted indicators. Blank or 1 shows that the indicator is specific to this rule.

FieldKindValues
dns.question.nameis_not_null
  • (no value, null check)
event.actioneq
  • lookup_requested corpus 4 (elastic 4)
process.namein
  • ollama
  • ollama.exe