Command and Scripting Interpreter via Windows Scripts

edit
IMPORTANT: This documentation is no longer updated. Refer to Elastic's version policy and the latest documentation.

Command and Scripting Interpreter via Windows Scripts

edit

Identifies PowerShell, PowerShell ISE, or Cmd execution spawned from Windows Script Host or MSHTA.

Rule type: eql

Rule indices:

  • logs-m365_defender.event-*
  • logs-sentinel_one_cloud_funnel.*
  • logs-system.security*
  • logs-windows.forwarded*
  • logs-windows.sysmon_operational-*
  • winlogbeat-*
  • endgame-*
  • logs-crowdstrike.fdr*

Severity: high

Risk score: 73

Runs every: 5m

Searches indices from: now-9m (Date Math format, see also Additional look-back time)

Maximum alerts per execution: 100

References: None

Tags:

  • Domain: Endpoint
  • OS: Windows
  • Use Case: Threat Detection
  • Tactic: Execution
  • Resources: Investigation Guide
  • Data Source: Windows Security Event Logs
  • Data Source: Sysmon
  • Data Source: SentinelOne
  • Data Source: Microsoft Defender XDR
  • Data Source: Elastic Endgame
  • Data Source: Crowdstrike

Version: 211

Rule authors:

  • Elastic

Rule license: Elastic License v2

Investigation guide

edit

Triage and analysis

Investigating Command and Scripting Interpreter via Windows Scripts

Possible investigation steps

  • What script-host-to-interpreter chain did the alert capture?
  • Focus: process.parent.name, process.parent.executable, process.parent.command_line, process.name, and process.command_line.
  • Implication: escalate when "wscript.exe" or "mshta.exe" launches PowerShell/pwsh/ISE/cmd from user-writable script/HTA, archive, download path, or URL; lower suspicion only when parent source, child command, user.id, and host.id fit one recognized logon, deployment, or vendor workflow.
  • Does the child command express staging, retrieval, persistence, or defense evasion?
  • Focus: process.command_line: "-EncodedCommand"/"-e", "-NoProfile", hidden windows, execution-policy bypass, Invoke-Expression/DownloadString, cmd "/c" chaining, curl/bitsadmin retrieval, or schtasks/sc.exe changes.
  • Hint: decode or reconstruct encoded or inline PowerShell before deciding intent; use script-block logs as optional corroboration.
  • Follow-on: inspect child starts from process.entity_id; PID-only matches are timestamp-bound candidates. !{investigate{"description":"","label":"Child process events for the script-launched process","providers":[[{"excluded":false,"field":"event.category","queryType":"phrase","value":"process","valueType":"string"},{"excluded":false,"field":"event.type","queryType":"phrase","value":"start","valueType":"string"},{"excluded":false,"field":"host.id","queryType":"phrase","value":"{{host.id}}","valueType":"string"},{"excluded":false,"field":"process.parent.entity_id","queryType":"phrase","value":"{{process.entity_id}}","valueType":"string"}],[{"excluded":false,"field":"event.category","queryType":"phrase","value":"process","valueType":"string"},{"excluded":false,"field":"event.type","queryType":"phrase","value":"start","valueType":"string"},{"excluded":false,"field":"host.id","queryType":"phrase","value":"{{host.id}}","valueType":"string"},{"excluded":false,"field":"process.parent.pid","queryType":"phrase","value":"{{process.pid}}","valueType":"string"}]],"relativeFrom":"now-1h","relativeTo":"now"}}
  • Implication: escalate when the command fetches content, decodes or executes inline script, launches another shell, or changes tasks/services; lower risk only when it runs a local script from the same logon, deployment, or vendor source without staging or unexpected egress.
  • Does the child binary identity fit the observed command line and location?
  • Focus: process.executable, process.pe.original_file_name, process.hash.sha256, process.code_signature.subject_name, and process.code_signature.trusted.
  • Implication: escalate when the child is renamed, unsigned or untrusted from a user-writable path, or mismatched to original file name; lower identity risk when signer, path, and hash history fit the expected interpreter, but identity alone never clears suspicious command intent.
  • Did the alerting process stage scripts, archives, or follow-on payloads?
  • Focus: file events scoped by host.id plus process.entity_id, or host.id plus process.pid in a tight window, checking file.path, file.Ext.original.path, file.Ext.original.extension, file.Ext.header_bytes, and file.Ext.windows.zone_identifier. !{investigate{"description":"","label":"File events for the script-launched process","providers":[[{"excluded":false,"field":"host.id","queryType":"phrase","value":"{{host.id}}","valueType":"string"},{"excluded":false,"field":"process.entity_id","queryType":"phrase","value":"{{process.entity_id}}","valueType":"string"},{"excluded":false,"field":"event.category","queryType":"phrase","value":"file","valueType":"string"}],[{"excluded":false,"field":"host.id","queryType":"phrase","value":"{{host.id}}","valueType":"string"},{"excluded":false,"field":"process.pid","queryType":"phrase","value":"{{process.pid}}","valueType":"string"},{"excluded":false,"field":"event.category","queryType":"phrase","value":"file","valueType":"string"}]],"relativeFrom":"now-1h","relativeTo":"now"}}
  • Hint: for PID fallback, require file time within the child lifetime.
  • Implication: escalate when the child writes or renames scriptable or executable content under temp, profile, public, startup, or deceptive paths, especially with internet provenance or type/extension mismatch; absent file telemetry is unresolved, not benign.
  • Did same-process network events show retrieval, staging, or callback behavior?
  • Focus: network events scoped by host.id plus process.entity_id, or host.id plus process.pid in a tight window, separating DNS dns.question.name and dns.resolved_ip from connection destination.ip, destination.port, and destination.as.organization.name. !{investigate{"description":"","label":"Network events for the script-launched process","providers":[[{"excluded":false,"field":"host.id","queryType":"phrase","value":"{{host.id}}","valueType":"string"},{"excluded":false,"field":"process.entity_id","queryType":"phrase","value":"{{process.entity_id}}","valueType":"string"},{"excluded":false,"field":"event.category","queryType":"phrase","value":"network","valueType":"string"}],[{"excluded":false,"field":"host.id","queryType":"phrase","value":"{{host.id}}","valueType":"string"},{"excluded":false,"field":"process.pid","queryType":"phrase","value":"{{process.pid}}","valueType":"string"},{"excluded":false,"field":"event.category","queryType":"phrase","value":"network","valueType":"string"}]],"relativeFrom":"now-1h","relativeTo":"now"}}
  • Hint: map DNS dns.resolved_ip to later connections before treating a domain as confirmed.
  • Implication: escalate when the process reaches external script-delivery, paste, storage, or C2 infra unrelated to the workflow; lower network risk when connections stay on recognized internal, proxy, or vendor services. Missing network telemetry is unresolved, not benign.
  • If local evidence stays suspicious or unresolved, does the same pattern appear in related alerts?
  • Focus: related alerts for user.id, checking execution, persistence, defense-evasion, or outbound context before comparing preserved process.parent.executable, process.parent.command_line, or process.command_line fragments. !{investigate{"description":"","label":"Alerts associated with the user","providers":[[{"excluded":false,"field":"event.kind","queryType":"phrase","value":"signal","valueType":"string"},{"excluded":false,"field":"user.id","queryType":"phrase","value":"{{user.id}}","valueType":"string"}]],"relativeFrom":"now-48h/h","relativeTo":"now"}}
  • Hint: use host.id alerts to test whether the chain is isolated, repeats with suspicious activity, or appears as adjacent variants such as "cscript.exe" launchers or delayed descendant shells. !{investigate{"description":"","label":"Alerts associated with the host","providers":[[{"excluded":false,"field":"event.kind","queryType":"phrase","value":"signal","valueType":"string"},{"excluded":false,"field":"host.id","queryType":"phrase","value":"{{host.id}}","valueType":"string"}]],"relativeFrom":"now-48h/h","relativeTo":"now"}}
  • Implication: broaden scope when the same user or host shows repeated script-host launches, task or service changes, persistence, or outbound staging; keep local only when the pattern is isolated and local evidence supports one recognized workflow.
  • Escalate when parent provenance, command intent, identity, artifacts, destinations, or related alerts support proxy execution or second-stage activity; close only when alert-local evidence and recovery bind one recognized workflow, with outside confirmation for telemetry gaps; preserve artifacts and escalate when evidence conflicts or visibility is incomplete.

False positive analysis

  • Logon scripts and deployment wrappers can legitimately launch cmd or PowerShell through Windows Script Host. Confirm only when process.parent.executable, process.parent.command_line, process.command_line, user.id, host.id, and same-process file.path or destination.ip recovered through host.id plus process.entity_id, or host.id plus process.pid in a tight window, align with one recognized workflow. If file or network telemetry is absent, use outside confirmation. Stable recurrence for that parent source, child command, user, and host can support closure when script inventory or change context exists; first-observed workflows need outside confirmation before exceptioning. Any mismatch keeps the case suspicious.
  • Vendor/installer/hardware-diagnostic HTA/VBS launchers can trigger this rule. Confirm only when process.executable, process.pe.original_file_name, process.hash.sha256, process.code_signature.subject_name, parent script path, file writes, and destinations match one vendor package. Without package context, recurring signer/hash, parent source, child command, and host cohort can support closure; first-observed packages need outside confirmation.
  • For exceptions, validate: process.parent.executable, process.parent.command_line, child process.executable, stable process.command_line fragment, process.code_signature.subject_name, user.id, and host.id. Avoid exceptions on process.name, child process.executable, or parent process name alone.

Response and remediation

  • If confirmed benign, reverse temporary containment and record the parent script path, child command pattern, signer, user.id, and host.id proving the workflow. Create exceptions only for exact workflows recurring in prior rule alerts.
  • If suspicious but unconfirmed, preserve the process event, process.entity_id or process.pid with host.id and time, command lines, suspicious file.path values, and confirmed dns.question.name, destination.ip, or destination.port before response. Apply reversible containment first: temporary destination blocking, disabling newly created scripts or tasks, or heightened host monitoring. Isolate only when corroborating staging, persistence, or outbound activity is confirmed and interruption is tolerable. Avoid destructive cleanup until scope is clearer.
  • If confirmed malicious, preserve process.entity_id, process.parent.entity_id, command lines, written file.path artifacts, and confirmed destinations, then isolate the host or block destinations based on staging and network evidence. Terminate malicious child or descendant processes after evidence capture; if direct endpoint response is unavailable, hand off artifacts for isolation or destination blocking.
  • Review related hosts and users for the same parent-child command pattern, confirmed destinations, and confirmed staged files only when endpoint file telemetry or related alerts preserve them. Then remove malicious scripts, HTA content, scheduled tasks, or dropped payloads, and remediate the delivery path.
  • Post-incident hardening: restrict unsupported "mshta.exe" and Windows Script Host use on workstations, retain process/file/network telemetry needed for this investigation, and record adjacent variants found during triage.

Setup

edit

Setup

This rule requires telemetry from one of the configured source integrations to be enabled and ingested.

Supported data sources

This rule can use the following data sources. For setup instructions, refer to the links below:

Rule query

edit
process where host.os.type == "windows" and event.type == "start" and
  process.command_line != null and
  (
    process.name : ("powershell.exe", "pwsh.exe", "powershell_ise.exe", "cmd.exe") or
    ?process.pe.original_file_name : ("powershell.exe", "pwsh.dll", "powershell_ise.exe", "Cmd.Exe")
  ) and
  process.parent.name : ("wscript.exe", "mshta.exe") and
  not (
    process.args : (
      "C:\\Program Files\\Intel\\SUR\\QUEENCREEK\\x64\\task.bat",
      "\"C:\\Program Files\\Intel\\SUR\\QUEENCREEK\\x64\\task.bat\""
    ) or
    process.command_line : (
      "\"C:\\Windows\\system32\\cmd.exe\" /c auditpol.exe /set /SUBCATEGORY:*",
      "\"C:\\Windows\\system32\\cmd.exe\" /c auditpol.exe /get*",
      "\"C:\\Windows\\system32\\cmd.exe\" /c exit\""
    ) or
    (process.args == "-File" and process.args == "-ExecutionPolicy")
  )
  and
  not (
    ?user.id == "S-1-5-18" and
    /* Don't apply the user.id exclusion to Sysmon for compatibility */
    not data_stream.dataset : ("windows.sysmon_operational", "windows.sysmon")
  )

Framework: MITRE ATT&CKTM