Detection rules › Elastic

Suspicious Instance Metadata Service (IMDS) API Command Line Execution

Status
production
Severity
medium
Time window
9m
Author
Elastic
Source
github.com/elastic/detection-rules

This rule identifies various tools/scripts performing command line execution attempting to access the cloud service provider's instance metadata service (IMDS) API endpoint, which can be used to retrieve sensitive instance-specific information such as instance ID, public IP address, and even temporary security credentials if roles are assumed by that instance.

MITRE ATT&CK coverage

Event coverage

Rule body elastic

[metadata]
creation_date = "2024/08/22"
integration = ["endpoint", "windows", "system", "m365_defender", "sentinel_one_cloud_funnel", "crowdstrike", "auditd_manager"]
maturity = "production"
updated_date = "2026/05/22"

[rule]
author = ["Elastic"]
description = """
This rule identifies various tools/scripts performing command line execution attempting to access the cloud service
provider's instance metadata service (IMDS) API endpoint, which can be used to retrieve sensitive instance-specific
information such as instance ID, public IP address, and even temporary security credentials if roles are assumed by
that instance.
"""
from = "now-9m"
index = [
    "endgame-*",
    "logs-crowdstrike.fdr*",
    "logs-endpoint.events.process-*",
    "logs-m365_defender.event-*",
    "logs-sentinel_one_cloud_funnel.*",
    "logs-system.security*",
    "logs-windows.forwarded*",
    "logs-windows.sysmon_operational-*",
    "winlogbeat-*",
    "auditbeat-*",
    "logs-auditd_manager.auditd-*"
]
language = "eql"
license = "Elastic License v2"
name = "Suspicious Instance Metadata Service (IMDS) API Command Line Execution"
note = """## Triage and analysis

> **Disclaimer**:
> This investigation guide was created using generative AI technology and has been reviewed to improve its accuracy and relevance. While every effort has been made to ensure its quality, we recommend validating the content and adapting it to suit your specific environment and operational needs.

### Investigating Suspicious Instance Metadata Service (IMDS) API Command Line Execution

This rule detects command-line tools, shells, or scripts attempting to query a cloud instance metadata endpoint from a host, which matters because that service can reveal instance details and temporary credentials attached to the workload. A common attacker pattern is gaining code execution on a cloud VM and using curl against the local metadata address to pull IAM role credentials or managed identity tokens, then reusing them to access cloud resources without passwords.

### Possible investigation steps

- Review the full execution chain and any referenced script or binary contents to determine whether the metadata request came from approved bootstrap or agent activity versus an interactive shell, web application process, scheduled job, or recently dropped file.
- Identify the initiating account, session context, and trigger for the execution to separate expected automation from hands-on-keyboard behavior, especially if it followed a remote login, privilege escalation, or exploitation event.
- Correlate the host and timeframe with cloud control-plane telemetry to confirm whether instance role credentials or managed identity tokens were later used against storage, secrets, IAM, subscription, or other sensitive APIs.
- Examine nearby endpoint activity for follow-on collection and staging behavior such as writing token output to disk, exporting environment data, invoking cloud CLIs or SDKs, compressing files, or making outbound connections to unfamiliar destinations.
- Validate with the asset owner whether the workload legitimately requires IMDS access, and if the activity is unexplained, contain the host and rotate any exposed instance profile or managed identity credentials.

### False positive analysis

- A VM bootstrap, login, or scheduled maintenance script may use curl, wget, or a shell to query IMDS for role credentials or identity tokens needed by the workload; verify the parent process, script path, and change timing with the asset owner to confirm it matches approved initialization or routine automation.
- An administrator or developer may manually test instance identity or application authentication from the command line during troubleshooting or deployment; verify the initiating user, interactive session context, and related change records to confirm the host and command were part of authorized maintenance.

### Response and remediation

- Isolate the affected host or cloud instance from the network, preserve volatile evidence per your IR process, and immediately revoke or rotate any instance profile credentials, managed identity tokens, or application secrets that could have been exposed by access to the metadata service.
- Remove the attacker foothold by deleting the script or binary that queried `169.254.169.254`, `metadata.google.internal`, or the Azure identity token path, and eradicate related persistence such as scheduled tasks, cron entries, systemd services, startup items, Run keys, or web shells that launched it.
- Terminate any active shell, interpreter, or cloud CLI sessions tied to the intrusion and review cloud activity for the retrieved credentials being used against storage, secrets, IAM, subscriptions, or other sensitive services, disabling the affected role or identity if abuse is confirmed.
- Restore the workload to a known-good state by rebuilding or reimaging from a trusted template, redeploying only validated application code and configuration, and do not return the original system to production unless its integrity has been fully verified.
- Escalate to incident response immediately if the metadata query returned temporary credentials or OAuth tokens, if those credentials were used from another host or geography, or if multiple systems show similar command-line access to the metadata service.
- Harden the environment by requiring IMDSv2 or equivalent protections, limiting which users, services, or containers can reach the metadata endpoint, reducing attached role permissions to least privilege, and adding detections for future `curl`, `wget`, shell, or script access to instance metadata paths.
"""
references = [
    "https://hackingthe.cloud/aws/general-knowledge/intro_metadata_service/",
    "https://www.wiz.io/blog/imds-anomaly-hunting-zero-day",
]
risk_score = 47
rule_id = "ecc0cd54-608e-11ef-ab6d-f661ea17fbce"
severity = "medium"
tags = [
    "Domain: Endpoint",
    "Domain: Cloud",
    "OS: Linux",
    "OS: Windows",
    "OS: macOS",
    "Use Case: Threat Detection",
    "Tactic: Credential Access",
    "Data Source: Elastic Endgame",
    "Data Source: Elastic Defend",
    "Data Source: Windows Security Event Logs",
    "Data Source: Microsoft Defender XDR",
    "Data Source: Sysmon",
    "Data Source: SentinelOne",
    "Data Source: Crowdstrike",
    "Data Source: Auditd Manager",
    "Resources: Investigation Guide",
]
timestamp_override = "event.ingested"
type = "eql"
query = '''
process where host.os.type in ("linux", "macos", "windows") and event.type == "start" and
event.action like ("exec", "exec_event", "start", "ProcessRollup2", "executed", "process_started", "Process Create*") and
(
  process.name in~ (
    "curl", "curl.exe", "wget", "wget.exe", "bash", "dash", "sh", "tcsh", "tclsh", "wish",
    "csh", "zsh", "ksh", "fish", "mksh", "busybox", "powershell.exe", "cmd.exe", "pwsh.exe", "pwsh"
  ) or
  process.name like~ (".*", "python*", "perl*", "ruby*", "php*", "lua*", "java*") or
  ?process.executable like~ (
    "/tmp/*", "/var/tmp/*", "/dev/shm/*", "/home/*/*", "/var/run/*", "/run/*", "/boot/*", "/.*", "C:\\Users\\*",
    "?:\\ProgramData\\*", "/var/www/*", "./*"
  )
) and
process.args like~ (
  "*/latest/meta-data/iam/security-credentials/?*",
  "*computeMetadata/v1/instance/service-accounts/*/oauth2/access_token*",
  "*/metadata/identity/oauth2/token*resource=*"
)
'''

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

[[rule.threat.technique]]
id = "T1552"
name = "Unsecured Credentials"
reference = "https://attack.mitre.org/techniques/T1552/"

[[rule.threat.technique.subtechnique]]
id = "T1552.005"
name = "Cloud Instance Metadata API"
reference = "https://attack.mitre.org/techniques/T1552/005/"

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

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

[[rule.threat.technique]]
id = "T1016"
name = "System Network Configuration Discovery"
reference = "https://attack.mitre.org/techniques/T1016/"

[[rule.threat.technique]]
id = "T1082"
name = "System Information Discovery"
reference = "https://attack.mitre.org/techniques/T1082/"

[[rule.threat.technique]]
id = "T1580"
name = "Cloud Infrastructure Discovery"
reference = "https://attack.mitre.org/techniques/T1580/"

[rule.threat.tactic]
id = "TA0007"
name = "Discovery"
reference = "https://attack.mitre.org/tactics/TA0007/"

Stages and Predicates

Stage 1: process

process where host.os.type in ("linux", "macos", "windows") and event.type == "start" and
event.action like ("exec", "exec_event", "start", "ProcessRollup2", "executed", "process_started", "Process Create*") and
(
  process.name in~ (
    "curl", "curl.exe", "wget", "wget.exe", "bash", "dash", "sh", "tcsh", "tclsh", "wish",
    "csh", "zsh", "ksh", "fish", "mksh", "busybox", "powershell.exe", "cmd.exe", "pwsh.exe", "pwsh"
  ) or
  process.name like~ (".*", "python*", "perl*", "ruby*", "php*", "lua*", "java*") or
  ?process.executable like~ (
    "/tmp/*", "/var/tmp/*", "/dev/shm/*", "/home/*/*", "/var/run/*", "/run/*", "/boot/*", "/.*", "C:\\Users\\*",
    "?:\\ProgramData\\*", "/var/www/*", "./*"
  )
) and
process.args like~ (
  "*/latest/meta-data/iam/security-credentials/?*",
  "*computeMetadata/v1/instance/service-accounts/*/oauth2/access_token*",
  "*/metadata/identity/oauth2/token*resource=*"
)

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
event.actionwildcard
  • Process Create*
  • ProcessRollup2
  • exec corpus 171 (elastic 156, sigma 15)
  • exec_event
  • executed corpus 3 (elastic 3)
  • process_started
  • start corpus 16 (elastic 16)
event.typeeq
  • start corpus 606 (elastic 606)
process.argswildcard
  • */latest/meta-data/iam/security-credentials/?*
  • */metadata/identity/oauth2/token*resource=*
  • *computeMetadata/v1/instance/service-accounts/*/oauth2/access_token*
process.executablewildcard
  • ./* corpus 10 (elastic 10)
  • /.*
  • /boot/* corpus 10 (elastic 10)
  • /dev/shm/* corpus 23 (elastic 22, sigma 1)
  • /home/*/* corpus 5 (elastic 5)
  • /run/* corpus 8 (elastic 8)
  • /tmp/* corpus 25 (elastic 23, sigma 2)
  • /var/run/* corpus 11 (elastic 11)
  • /var/tmp/* corpus 24 (elastic 23, sigma 1)
  • /var/www/* corpus 5 (elastic 5)
  • ?:\ProgramData\*
  • C:\Users\*
process.namein
  • bash corpus 7 (elastic 7)
  • busybox corpus 8 (elastic 8)
  • cmd.exe corpus 77 (elastic 48, splunk 29)
  • csh corpus 5 (elastic 5)
  • curl corpus 18 (elastic 13, splunk 5)
  • curl.exe corpus 15 (elastic 12, splunk 3)
  • dash corpus 7 (elastic 7)
  • fish corpus 5 (elastic 5)
  • ksh corpus 6 (elastic 6)
  • mksh
  • powershell.exe corpus 104 (elastic 60, splunk 44)
  • pwsh
  • pwsh.exe corpus 62 (elastic 33, splunk 29)
  • sh corpus 8 (elastic 7, splunk 1)
  • tclsh
  • tcsh corpus 6 (elastic 6)
  • wget corpus 12 (elastic 11, splunk 1)
  • wget.exe corpus 5 (elastic 5)
  • wish
  • zsh corpus 7 (elastic 7)
process.namewildcard
  • .* corpus 18 (elastic 18)
  • java*
  • lua* corpus 15 (elastic 15)
  • perl* corpus 20 (elastic 20)
  • php* corpus 14 (elastic 14)
  • python* corpus 31 (elastic 31)
  • ruby* corpus 21 (elastic 21)