Detection rules › Splunk

Ollama Abnormal Service Crash Availability Attack

Status
experimental
Severity
low
Group by
host
Author
Rod Soto
Source
github.com/splunk/security_content

Detects critical service crashes, fatal errors, and abnormal process terminations in Ollama that may indicate exploitation attempts, resource exhaustion attacks, malicious input triggering unhandled exceptions, or deliberate denial of service attacks designed to disrupt AI model availability and degrade system stability.

MITRE ATT&CK coverage

TacticTechniques
ImpactT1489 Service Stop

Rule body splunk

name: Ollama Abnormal Service Crash Availability Attack
id: 327fa152-9b56-4e4e-bc0b-2795d4068afa
version: 4
creation_date: '2025-10-13'
modification_date: '2026-05-13'
author: Rod Soto
status: experimental
type: Anomaly
description: Detects critical service crashes, fatal errors, and abnormal process terminations in Ollama that may indicate exploitation attempts, resource exhaustion attacks, malicious input triggering unhandled exceptions, or deliberate denial of service attacks designed to disrupt AI model availability and degrade system stability.
data_source:
    - Ollama Server
search: '`ollama_server` (level=ERROR OR level=FATAL OR "service stopped" OR "terminated" OR "exit" OR "shutdown" OR "crash" OR "killed") | rex field=_raw "msg=\"(?<msg>[^\"]+)\"" | rex field=_raw "exit_code=(?<exit_code>\d+)" | bin _time span=5m | stats count as termination_count, earliest(_time) as first_seen, latest(_time) as last_seen, values(msg) as error_messages, values(exit_code) as exit_codes, dc(msg) as unique_errors by host | eval first_seen=strftime(first_seen, "%Y-%m-%d %H:%M:%S") | eval last_seen=strftime(last_seen, "%Y-%m-%d %H:%M:%S") | eval severity=case( termination_count > 5, "critical", termination_count > 2, "high", 1=1, "medium" ) | eval attack_type=case( termination_count > 5, "Resource Exhaustion", termination_count > 2, "Repeated Service Failures", 1=1, "Service Instability" ) | where termination_count > 1 | table first_seen, last_seen, host, termination_count, unique_errors, error_messages, severity, attack_type | `ollama_abnormal_service_crash_availability_attack_filter`'
how_to_implement: 'Ingest Ollama logs via Splunk TA-ollama add-on by configuring file monitoring inputs pointed to your Ollama server log directories (sourcetype: ollama:server), or enable HTTP Event Collector (HEC) for real-time API telemetry and prompt analytics (sourcetypes: ollama:api, ollama:prompts). CIM compatibility using the Web datamodel for standardized security detections.'
known_false_positives: Normal service restarts during system updates or maintenance windows, graceful shutdowns with non-zero exit codes, intentional service stops by administrators, software upgrades requiring process termination, out-of-memory conditions on resource-constrained systems, or known bugs in specific Ollama versions that cause benign crashes may trigger this detection during routine operations.
references:
    - https://github.com/rosplk/ta-ollama
drilldown_searches:
    - name: 'View the detection results for - "$host$"'
      search: '%original_detection_search% | search host="$host$"'
      earliest_offset: $info_min_time$
      latest_offset: $info_max_time$
    - name: 'View risk events for the last 7 days for - "$host$"'
      search: '| from datamodel Risk.All_Risk | search normalized_risk_object IN ("$host$") | stats count min(_time) as firstTime max(_time) as lastTime values(search_name) as "Search Name" values(risk_message) as "Risk Message" values(analyticstories) as "Analytic Stories" values(annotations._all) as "Annotations" values(annotations.mitre_attack.mitre_tactic) as "ATT&CK Tactics" by normalized_risk_object | `security_content_ctime(firstTime)` | `security_content_ctime(lastTime)`'
      earliest_offset: 7d
      latest_offset: "0"
intermediate_findings:
    entities:
        - field: host
          type: system
          score: 20
          message: 'Abnormal Ollama service termination detected on host $host$ between $first_seen$ and $last_seen$. Service stopped $termination_count$ times with $unique_errors$ unique error types. Severity: $severity$. Potential cause: $attack_type$. Error messages: $error_messages$ require investigation.'
analytic_story:
    - Suspicious Ollama Activities
asset_type: Web Application
mitre_attack_id:
    - T1489
product:
    - Splunk Enterprise
    - Splunk Enterprise Security
    - Splunk Cloud
category: application
security_domain: endpoint
tests:
    - name: True Positive Test
      attack_data:
        - data: https://media.githubusercontent.com/media/splunk/attack_data/master/datasets/ollama/app.log
          sourcetype: ollama:server
          source: app.log
      test_type: experimental
      description: This test is a legacy experimental test and may not be accurate.

Stages and Predicates

Stage 1: search

`ollama_server` (level=ERROR OR level=FATAL OR "service stopped" OR "terminated" OR "exit" OR "shutdown" OR "crash" OR "killed")

Stage 2: eval

| rex field=_raw "msg=\"(?<msg>[^\"]+)\""

Stage 3: rex

| rex field=_raw "exit_code=(?<exit_code>\d+)"

Stage 4: bucket

| bin _time span=5m

Stage 5: stats

| stats count as termination_count, earliest(_time) as first_seen, latest(_time) as last_seen, values(msg) as error_messages, values(exit_code) as exit_codes, dc(msg) as unique_errors by host

Stage 6: eval

| eval first_seen=strftime(first_seen, "%Y-%m-%d %H:%M:%S")

Stage 7: eval

| eval last_seen=strftime(last_seen, "%Y-%m-%d %H:%M:%S")

Stage 8: eval

| eval severity=case( termination_count > 5, "critical", termination_count > 2, "high", 1=1, "medium" )
severity =
iftermination_count > 5"critical"
eliftermination_count > 2"high"
else"medium"

Stage 9: eval

| eval attack_type=case( termination_count > 5, "Resource Exhaustion", termination_count > 2, "Repeated Service Failures", 1=1, "Service Instability" )
attack_type =
iftermination_count > 5"Resource Exhaustion"
eliftermination_count > 2"Repeated Service Failures"
else"Service Instability"

Stage 10: where

| where termination_count > 1

Stage 11: table

| table first_seen, last_seen, host, termination_count, unique_errors, error_messages, severity, attack_type

Stage 12: search

| `ollama_abnormal_service_crash_availability_attack_filter`

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
leveleq
  • ERROR
  • FATAL
sourcetypeeq
  • ollama:server
termination_countgt
  • 1

Search terms

Bare-string tokens in the SPL search body. Splunk matches each token against _raw (the untyped raw event text) anywhere it appears, not against a specific field. These don't surface in the Indicators table because they aren't predicates on a known field.

StageTerm
1"service stopped"
1"terminated"
1"exit"
1"shutdown"
1"crash"
1"killed"