Detection rules › Elastic

Suspicious Child Process via Azure VM CustomScript Extension

Status
production
Severity
medium
Time window
1m
Sequence by
host.id, process.Ext.ancestry, process.entity_id
Author
Elastic
Source
github.com/elastic/detection-rules

Identifies a suspicious process executing as a descendant of the Azure VM CustomScript extension handler (CustomScriptHandler.exe) on a Windows host. The Azure CustomScript extension runs an attacker-supplied script with high privilege (SYSTEM) via the guest agent, and is a common cloud-to-host code-execution and persistence primitive. Because the extension's resource name is attacker-controlled and absent from on-host telemetry, this rule anchors on the type-bearing handler binary ('Microsoft.Compute.CustomScriptExtension...\CustomScriptHandler.exe') rather than the spoofable extension name, making it resistant to renaming. CustomScript legitimately launches PowerShell and cmd, so the rule fires only when the descendant is an execution-proxy, download, or discovery LOLBin, or PowerShell exhibiting suspicious tradecraft.

MITRE ATT&CK coverage

Telemetry coverage

Rule body

[metadata]
creation_date = "2026/06/17"
integration = ["endpoint"]
maturity = "production"
updated_date = "2026/06/17"

[rule]
author = ["Elastic"]
description = """
Identifies a suspicious process executing as a descendant of the Azure VM CustomScript extension handler
(CustomScriptHandler.exe) on a Windows host. The Azure CustomScript extension runs an attacker-supplied script with high
privilege (SYSTEM) via the guest agent, and is a common cloud-to-host code-execution and persistence primitive. Because
the extension's resource name is attacker-controlled and absent from on-host telemetry, this rule anchors on the
type-bearing handler binary ('Microsoft.Compute.CustomScriptExtension\\...\\CustomScriptHandler.exe') rather than the
spoofable extension name, making it resistant to renaming. CustomScript legitimately launches PowerShell and cmd, so the
rule fires only when the descendant is an execution-proxy, download, or discovery LOLBin, or PowerShell exhibiting
suspicious tradecraft.
"""
from = "now-9m"
index = ["logs-endpoint.events.process-*"]
language = "eql"
license = "Elastic License v2"
name = "Suspicious Child Process via Azure VM CustomScript Extension"
note = """## Triage and analysis

### Investigating Suspicious Child Process via Azure VM CustomScript Extension

The Azure CustomScript extension executes a script as SYSTEM via the guest agent. The extension's resource name is
attacker-controlled and not present on the host, so this rule anchors on the handler binary path
(`Microsoft.Compute.CustomScriptExtension\\...\\CustomScriptHandler.exe`), which is rename-proof, and alerts when a
LOLBin or suspicious PowerShell runs anywhere in its process tree.

### Possible investigation steps

- Review the full process tree from `CustomScriptHandler.exe` to the alerting process, including `process.command_line`
  and `process.args`.
- Identify the descendant: execution proxies (`mshta`, `regsvr32`, `rundll32`, `installutil`, `msbuild`), download tools
  (`certutil`, `bitsadmin`), script hosts (`wscript`, `cscript`), or discovery utilities (`whoami`, `net`, `nltest`,
  `wmic`) are not expected children of a benign CustomScript payload.
- Correlate with the control-plane event: a `MICROSOFT.COMPUTE/VIRTUALMACHINES/EXTENSIONS/WRITE` in
  `logs-azure.activitylogs-*` for this host around the same time, and the acting principal/source behind it.
- Retrieve the extension's settings/protectedSettings from the VM (the activity log does not contain the script body) to
  assess intent.
- Pivot on the host for credential access, new local accounts, persistence, or outbound C2 following the execution.
- Review who deployed the extension (Entra sign-in logs and RBAC for the principal in the correlated activity log event).

### False positive analysis

- Infrastructure-as-code and configuration-management scripts deployed via CustomScript may legitimately run discovery
  utilities (`whoami`, `net`, `nltest`, `systeminfo`, `wmic`, `tasklist`, `arp`) for bootstrap or inventory. If the
  activity recurs from known automation, baseline it and exclude by `process.command_line`/`process.args`.
- Software installation and bootstrapping via CustomScript can invoke `msbuild`, `installutil`, `regsvr32`, `regasm`,
  `regsvcs`, `certutil`, or `bitsadmin` to build, register, or download legitimate components. Verify the target
  file/URL and, if benign, scope the exclusion to the specific command or signed binary rather than the whole LOLBin.
- Legitimate setup scripts (DSC bootstrap, agent installers) may use PowerShell download cradles
  (`Invoke-WebRequest`, `DownloadString`, `-EncodedCommand`) against trusted internal or Microsoft endpoints. Confirm
  the destination host and content before excluding, and exclude by the specific command line, not by host.
- A known automation principal deploying the extension from expected corporate egress (corroborated by the correlated
  `MICROSOFT.COMPUTE/VIRTUALMACHINES/EXTENSIONS/WRITE` and an approved change) lowers confidence, but still review the
  executed content. Prefer narrow, command- or argument-scoped exclusions over broad host or LOLBin exclusions, since
  the same execution chain is exactly what an attacker abuses.

### Response and remediation

- If unauthorized, remove the extension, isolate the host, rotate credentials reachable from it, and review RBAC on the affected subscription/resource group.
"""
references = [
    "https://blog.pwnedlabs.io/diving-deep-into-azure-vm-attack-vectors",
    "https://www.sysdig.com/blog/the-expendable-extension-name-azure-vmaccess-naming-chaos-password-resets-and-a-detection-gap",
    "https://learn.microsoft.com/en-us/azure/virtual-machines/extensions/custom-script-windows",
]
risk_score = 47
rule_id = "b4d4f0fb-908e-4cd1-ac8f-795c0433db0a"
severity = "medium"
tags = [
    "Domain: Endpoint",
    "OS: Windows",
    "Use Case: Threat Detection",
    "Tactic: Execution",
    "Tactic: Defense Evasion",
    "Data Source: Elastic Defend",
    "Resources: Investigation Guide",
]
timestamp_override = "event.ingested"
type = "eql"
query = '''
sequence by host.id with maxspan=1m
  /* Azure CustomScript extension handler */
  [process where host.os.type == "windows" and event.type == "start" and
     (process.name : "CustomScriptHandler.exe" or
      process.executable : "?:\\Packages\\Plugins\\*CustomScript*\\*\\CustomScriptHandler.exe")] by process.entity_id
  /* Abused LOLBin / suspicious PowerShell anywhere in its tree */
  [process where host.os.type == "windows" and event.type == "start" and
   (
     process.name : ("mshta.exe", "regsvr32.exe", "rundll32.exe", "installutil.exe", "msbuild.exe", "regasm.exe",
                     "regsvcs.exe", "wscript.exe", "cscript.exe", "bitsadmin.exe", "nltest.exe", "whoami.exe",
                     "net.exe", "net1.exe", "wmic.exe", "systeminfo.exe", "quser.exe", "arp.exe", "tasklist.exe") or
     (process.name : "certutil.exe" and process.args : ("*urlcache*", "*-decode*", "*-encode*")) or
     (process.name : ("powershell.exe", "pwsh.exe") and
      process.command_line : ("*-enc*", "*EncodedCommand*", "*FromBase64String*", "*DownloadString*", "*DownloadFile*",
                              "*Invoke-Expression*", "*IEX *", "*IEX(*", "*|IEX*", "*-w hidden*", "*WindowStyle Hidden*",
                              "*Net.WebClient*", "*Invoke-WebRequest*", "*Start-BitsTransfer*"))
   )] by process.Ext.ancestry
'''

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

[[rule.threat.technique]]
id = "T1651"
name = "Cloud Administration Command"
reference = "https://attack.mitre.org/techniques/T1651/"

[[rule.threat.technique]]
id = "T1059"
name = "Command and Scripting Interpreter"
reference = "https://attack.mitre.org/techniques/T1059/"

[[rule.threat.technique.subtechnique]]
id = "T1059.001"
name = "PowerShell"
reference = "https://attack.mitre.org/techniques/T1059/001/"

[[rule.threat.technique.subtechnique]]
id = "T1059.003"
name = "Windows Command Shell"
reference = "https://attack.mitre.org/techniques/T1059/003/"

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

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

[[rule.threat.technique]]
id = "T1218"
name = "System Binary Proxy Execution"
reference = "https://attack.mitre.org/techniques/T1218/"

[rule.threat.tactic]
id = "TA0005"
name = "Defense Evasion"
reference = "https://attack.mitre.org/tactics/TA0005/"

Stages and Predicates

Ordered sequence: each step below must occur in order within 1m, correlated by host.id, process.Ext.ancestry, process.entity_id.

Stage 1: process

[process where host.os.type == "windows" and event.type == "start" and
     (process.name : "CustomScriptHandler.exe" or
      process.executable : "?:\\Packages\\Plugins\\*CustomScript*\\*\\CustomScriptHandler.exe")] by process.entity_id

Stage 2: process

[process where host.os.type == "windows" and event.type == "start" and
   (
     process.name : ("mshta.exe", "regsvr32.exe", "rundll32.exe", "installutil.exe", "msbuild.exe", "regasm.exe",
                     "regsvcs.exe", "wscript.exe", "cscript.exe", "bitsadmin.exe", "nltest.exe", "whoami.exe",
                     "net.exe", "net1.exe", "wmic.exe", "systeminfo.exe", "quser.exe", "arp.exe", "tasklist.exe") or
     (process.name : "certutil.exe" and process.args : ("*urlcache*", "*-decode*", "*-encode*")) or
     (process.name : ("powershell.exe", "pwsh.exe") and
      process.command_line : ("*-enc*", "*EncodedCommand*", "*FromBase64String*", "*DownloadString*", "*DownloadFile*",
                              "*Invoke-Expression*", "*IEX *", "*IEX(*", "*|IEX*", "*-w hidden*", "*WindowStyle Hidden*",
                              "*Net.WebClient*", "*Invoke-WebRequest*", "*Start-BitsTransfer*"))
   )] by process.Ext.ancestry

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
event.typeeq
  • start corpus 1078 (elastic 1078)
field:"event.type" kind:eq value:"start"
process.argswildcard
  • *-decode*
  • *-encode*
  • *urlcache*
field:"process.args" kind:wildcard
process.command_linewildcard
  • *-enc* corpus 3 (sigma 2, elastic 1)
  • *-w hidden*
  • *DownloadFile* corpus 6 (sigma 4, elastic 1, chronicle 1)
  • *DownloadString* corpus 9 (sigma 7, elastic 1, kusto 1)
  • *EncodedCommand* corpus 2 (sigma 1, elastic 1)
  • *FromBase64String* corpus 15 (sigma 9, elastic 4, splunk 2)
  • *IEX * corpus 7 (sigma 6, elastic 1)
  • *IEX(* corpus 4 (sigma 3, elastic 1)
  • *Invoke-Expression* corpus 5 (sigma 4, elastic 1)
  • *Invoke-WebRequest* corpus 15 (sigma 10, elastic 3, chronicle 1, kusto 1)
  • *Net.WebClient* corpus 3 (sigma 2, elastic 1)
  • *Start-BitsTransfer* corpus 5 (sigma 3, elastic 1, splunk 1)
  • *WindowStyle Hidden*
  • *|IEX*
field:"CommandLine" kind:wildcard
process.executablewildcard
  • ?:\Packages\Plugins\*CustomScript*\*\CustomScriptHandler.exe
field:"Image" kind:wildcard value:"?:\Packages\Plugins\*CustomScript*\*\CustomScriptHandler.exe"
process.namewildcard
  • CustomScriptHandler.exe
  • arp.exe corpus 9 (elastic 8, splunk 1)
  • bitsadmin.exe corpus 23 (elastic 21, splunk 2)
  • certutil.exe corpus 44 (elastic 38, splunk 6)
  • cscript.exe corpus 67 (elastic 65, splunk 2)
  • installutil.exe corpus 37 (elastic 32, splunk 5)
  • msbuild.exe corpus 39 (elastic 36, splunk 3)
  • mshta.exe corpus 84 (elastic 79, splunk 5)
  • net.exe corpus 28 (elastic 26, splunk 2)
  • net1.exe corpus 39 (elastic 20, splunk 19)
  • nltest.exe corpus 11 (elastic 9, splunk 2)
  • powershell.exe corpus 184 (elastic 140, splunk 44)
  • pwsh.exe corpus 77 (elastic 48, splunk 29)
  • quser.exe corpus 10 (elastic 9, splunk 1)
  • regasm.exe corpus 26 (elastic 24, splunk 2)
  • regsvcs.exe corpus 23 (elastic 21, splunk 2)
  • regsvr32.exe corpus 73 (elastic 68, splunk 5)
  • rundll32.exe corpus 126 (elastic 100, splunk 26)
  • systeminfo.exe corpus 9 (elastic 9)
  • tasklist.exe corpus 10 (elastic 10)
  • whoami.exe corpus 12 (elastic 10, splunk 2)
  • wmic.exe corpus 66 (elastic 39, splunk 27)
  • wscript.exe corpus 83 (elastic 82, splunk 1)
field:"process_name" kind:wildcard