Command and Scripting Interpreter via Windows Scripts
Identifies PowerShell, PowerShell ISE, or Cmd execution spawned from Windows Script Host or MSHTA.
Elastic rule (View on GitHub)
1[metadata]
2creation_date = "2024/09/09"
3integration = ["windows", "system", "sentinel_one_cloud_funnel", "m365_defender", "crowdstrike"]
4maturity = "production"
5updated_date = "2026/05/03"
6
7[rule]
8author = ["Elastic"]
9description = "Identifies PowerShell, PowerShell ISE, or Cmd execution spawned from Windows Script Host or MSHTA."
10from = "now-9m"
11index = [
12 "logs-m365_defender.event-*",
13 "logs-sentinel_one_cloud_funnel.*",
14 "logs-system.security*",
15 "logs-windows.forwarded*",
16 "logs-windows.sysmon_operational-*",
17 "winlogbeat-*",
18 "endgame-*",
19 "logs-crowdstrike.fdr*",
20]
21language = "eql"
22license = "Elastic License v2"
23name = "Command and Scripting Interpreter via Windows Scripts"
24risk_score = 73
25rule_id = "2d62889e-e758-4c5e-b57e-c735914ee32a"
26severity = "high"
27tags = [
28 "Domain: Endpoint",
29 "OS: Windows",
30 "Use Case: Threat Detection",
31 "Tactic: Execution",
32 "Resources: Investigation Guide",
33 "Data Source: Windows Security Event Logs",
34 "Data Source: Sysmon",
35 "Data Source: SentinelOne",
36 "Data Source: Microsoft Defender XDR",
37 "Data Source: Elastic Endgame",
38 "Data Source: Crowdstrike",
39]
40timestamp_override = "event.ingested"
41type = "eql"
42
43query = '''
44process where host.os.type == "windows" and event.type == "start" and
45 process.command_line != null and
46 (
47 process.name : ("powershell.exe", "pwsh.exe", "powershell_ise.exe", "cmd.exe") or
48 ?process.pe.original_file_name : ("powershell.exe", "pwsh.dll", "powershell_ise.exe", "Cmd.Exe")
49 ) and
50 process.parent.name : ("wscript.exe", "mshta.exe") and
51 not (
52 process.args : (
53 "C:\\Program Files\\Intel\\SUR\\QUEENCREEK\\x64\\task.bat",
54 "\"C:\\Program Files\\Intel\\SUR\\QUEENCREEK\\x64\\task.bat\""
55 ) or
56 process.command_line : (
57 "\"C:\\Windows\\system32\\cmd.exe\" /c auditpol.exe /set /SUBCATEGORY:*",
58 "\"C:\\Windows\\system32\\cmd.exe\" /c auditpol.exe /get*",
59 "\"C:\\Windows\\system32\\cmd.exe\" /c exit\""
60 ) or
61 (process.args == "-File" and process.args == "-ExecutionPolicy")
62 )
63 and
64 not (
65 ?user.id == "S-1-5-18" and
66 /* Don't apply the user.id exclusion to Sysmon for compatibility */
67 not data_stream.dataset : ("windows.sysmon_operational", "windows.sysmon")
68 )
69'''
70
71note = """## Triage and analysis
72
73### Investigating Command and Scripting Interpreter via Windows Scripts
74
75#### Possible investigation steps
76
77- What script-host-to-interpreter chain did the alert capture?
78 - Focus: `process.parent.name`, `process.parent.executable`, `process.parent.command_line`, `process.name`, and `process.command_line`.
79 - 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.
80
81- Does the child command express staging, retrieval, persistence, or defense evasion?
82 - 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.
83 - Hint: decode or reconstruct encoded or inline PowerShell before deciding intent; use script-block logs as optional corroboration.
84 - Follow-on: inspect child starts from `process.entity_id`; PID-only matches are timestamp-bound candidates. $investigate_2
85 - 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.
86
87- Does the child binary identity fit the observed command line and location?
88 - Focus: `process.executable`, `process.pe.original_file_name`, `process.hash.sha256`, `process.code_signature.subject_name`, and `process.code_signature.trusted`.
89 - 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.
90
91- Did the alerting process stage scripts, archives, or follow-on payloads?
92 - 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_0
93 - Hint: for PID fallback, require file time within the child lifetime.
94 - 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.
95
96- Did same-process network events show retrieval, staging, or callback behavior?
97 - 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_1
98 - Hint: map DNS `dns.resolved_ip` to later connections before treating a domain as confirmed.
99 - 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.
100
101- If local evidence stays suspicious or unresolved, does the same pattern appear in related alerts?
102 - 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_3
103 - 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_4
104 - 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.
105
106- 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.
107
108### False positive analysis
109
110- 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.
111- 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.
112- 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.
113
114### Response and remediation
115
116- 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.
117- 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.
118- 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.
119- 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.
120- 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.
121"""
122
123setup = """## Setup
124
125This rule requires telemetry from one of the configured source integrations to be enabled and ingested.
126
127### Supported data sources
128
129This rule can use the following data sources. For setup instructions, refer to the links below:
130
131- [CrowdStrike](https://ela.st/crowdstrike-integration)
132- [Microsoft Defender XDR](https://ela.st/m365-defender)
133- [SentinelOne Cloud Funnel](https://ela.st/sentinel-one-cloud-funnel)
134- [Sysmon Event ID 1 - Process Creation](https://ela.st/sysmon-event-1-setup)
135- [Windows Process Creation Logs](https://ela.st/audit-process-creation)
136"""
137
138[rule.investigation_fields]
139field_names = [
140 "@timestamp",
141 "host.id",
142 "user.id",
143 "process.entity_id",
144 "process.pid",
145 "process.executable",
146 "process.command_line",
147 "process.pe.original_file_name",
148 "process.hash.sha256",
149 "process.code_signature.subject_name",
150 "process.code_signature.trusted",
151 "process.parent.name",
152 "process.parent.executable",
153 "process.parent.command_line",
154 "process.parent.args",
155]
156
157[transform]
158
159[[transform.investigate]]
160label = "File events for the script-launched process"
161description = ""
162providers = [
163 [
164 { excluded = false, field = "host.id", queryType = "phrase", value = "{{host.id}}", valueType = "string" },
165 { excluded = false, field = "process.entity_id", queryType = "phrase", value = "{{process.entity_id}}", valueType = "string" },
166 { excluded = false, field = "event.category", queryType = "phrase", value = "file", valueType = "string" }
167 ],
168 [
169 { excluded = false, field = "host.id", queryType = "phrase", value = "{{host.id}}", valueType = "string" },
170 { excluded = false, field = "process.pid", queryType = "phrase", value = "{{process.pid}}", valueType = "string" },
171 { excluded = false, field = "event.category", queryType = "phrase", value = "file", valueType = "string" }
172 ]
173]
174relativeFrom = "now-1h"
175relativeTo = "now"
176
177[[transform.investigate]]
178label = "Network events for the script-launched process"
179description = ""
180providers = [
181 [
182 { excluded = false, field = "host.id", queryType = "phrase", value = "{{host.id}}", valueType = "string" },
183 { excluded = false, field = "process.entity_id", queryType = "phrase", value = "{{process.entity_id}}", valueType = "string" },
184 { excluded = false, field = "event.category", queryType = "phrase", value = "network", valueType = "string" }
185 ],
186 [
187 { excluded = false, field = "host.id", queryType = "phrase", value = "{{host.id}}", valueType = "string" },
188 { excluded = false, field = "process.pid", queryType = "phrase", value = "{{process.pid}}", valueType = "string" },
189 { excluded = false, field = "event.category", queryType = "phrase", value = "network", valueType = "string" }
190 ]
191]
192relativeFrom = "now-1h"
193relativeTo = "now"
194
195[[transform.investigate]]
196label = "Child process events for the script-launched process"
197description = ""
198providers = [
199 [
200 { excluded = false, field = "event.category", queryType = "phrase", value = "process", valueType = "string" },
201 { excluded = false, field = "event.type", queryType = "phrase", value = "start", valueType = "string" },
202 { excluded = false, field = "host.id", queryType = "phrase", value = "{{host.id}}", valueType = "string" },
203 { excluded = false, field = "process.parent.entity_id", queryType = "phrase", value = "{{process.entity_id}}", valueType = "string" }
204 ],
205 [
206 { excluded = false, field = "event.category", queryType = "phrase", value = "process", valueType = "string" },
207 { excluded = false, field = "event.type", queryType = "phrase", value = "start", valueType = "string" },
208 { excluded = false, field = "host.id", queryType = "phrase", value = "{{host.id}}", valueType = "string" },
209 { excluded = false, field = "process.parent.pid", queryType = "phrase", value = "{{process.pid}}", valueType = "string" }
210 ]
211]
212relativeFrom = "now-1h"
213relativeTo = "now"
214
215[[transform.investigate]]
216label = "Alerts associated with the user"
217description = ""
218providers = [
219 [
220 { excluded = false, field = "event.kind", queryType = "phrase", value = "signal", valueType = "string" },
221 { excluded = false, field = "user.id", queryType = "phrase", value = "{{user.id}}", valueType = "string" }
222 ]
223]
224relativeFrom = "now-48h/h"
225relativeTo = "now"
226
227[[transform.investigate]]
228label = "Alerts associated with the host"
229description = ""
230providers = [
231 [
232 { excluded = false, field = "event.kind", queryType = "phrase", value = "signal", valueType = "string" },
233 { excluded = false, field = "host.id", queryType = "phrase", value = "{{host.id}}", valueType = "string" }
234 ]
235]
236relativeFrom = "now-48h/h"
237relativeTo = "now"
238
239[[rule.threat]]
240framework = "MITRE ATT&CK"
241
242[[rule.threat.technique]]
243id = "T1059"
244name = "Command and Scripting Interpreter"
245reference = "https://attack.mitre.org/techniques/T1059/"
246
247[[rule.threat.technique.subtechnique]]
248id = "T1059.001"
249name = "PowerShell"
250reference = "https://attack.mitre.org/techniques/T1059/001/"
251
252[[rule.threat.technique.subtechnique]]
253id = "T1059.003"
254name = "Windows Command Shell"
255reference = "https://attack.mitre.org/techniques/T1059/003/"
256
257[[rule.threat.technique.subtechnique]]
258id = "T1059.005"
259name = "Visual Basic"
260reference = "https://attack.mitre.org/techniques/T1059/005/"
261
262[[rule.threat.technique.subtechnique]]
263id = "T1059.007"
264name = "JavaScript"
265reference = "https://attack.mitre.org/techniques/T1059/007/"
266
267[rule.threat.tactic]
268id = "TA0002"
269name = "Execution"
270reference = "https://attack.mitre.org/tactics/TA0002/"
271
272[[rule.threat]]
273framework = "MITRE ATT&CK"
274
275[[rule.threat.technique]]
276id = "T1218"
277name = "System Binary Proxy Execution"
278reference = "https://attack.mitre.org/techniques/T1218/"
279
280[[rule.threat.technique.subtechnique]]
281id = "T1218.005"
282name = "Mshta"
283reference = "https://attack.mitre.org/techniques/T1218/005/"
284
285[rule.threat.tactic]
286id = "TA0005"
287name = "Defense Evasion"
288reference = "https://attack.mitre.org/tactics/TA0005/"
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, andprocess.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, andhost.idfit one recognized logon, deployment, or vendor workflow.
- Focus:
-
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_2 - 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.
- Focus:
-
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, andprocess.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.
- Focus:
-
Did the alerting process stage scripts, archives, or follow-on payloads?
- Focus: file events scoped by
host.idplusprocess.entity_id, orhost.idplusprocess.pidin a tight window, checkingfile.path,file.Ext.original.path,file.Ext.original.extension,file.Ext.header_bytes, andfile.Ext.windows.zone_identifier. $investigate_0 - 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.
- Focus: file events scoped by
-
Did same-process network events show retrieval, staging, or callback behavior?
- Focus: network events scoped by
host.idplusprocess.entity_id, orhost.idplusprocess.pidin a tight window, separating DNSdns.question.nameanddns.resolved_ipfrom connectiondestination.ip,destination.port, anddestination.as.organization.name. $investigate_1 - Hint: map DNS
dns.resolved_ipto 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.
- Focus: network events scoped by
-
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 preservedprocess.parent.executable,process.parent.command_line, orprocess.command_linefragments. $investigate_3 - Hint: use
host.idalerts 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_4 - 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.
- Focus: related alerts for
-
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-processfile.pathordestination.iprecovered throughhost.idplusprocess.entity_id, orhost.idplusprocess.pidin 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, childprocess.executable, stableprocess.command_linefragment,process.code_signature.subject_name,user.id, andhost.id. Avoid exceptions onprocess.name, childprocess.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, andhost.idproving the workflow. Create exceptions only for exact workflows recurring in prior rule alerts. - If suspicious but unconfirmed, preserve the process event,
process.entity_idorprocess.pidwithhost.idand time, command lines, suspiciousfile.pathvalues, and confirmeddns.question.name,destination.ip, ordestination.portbefore 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, writtenfile.pathartifacts, 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.
Related rules
- Suspicious Cmd Execution via WMI
- Suspicious Execution from a WebDav Share
- Suspicious JavaScript Execution via Deno
- Suspicious Windows Command Shell Arguments
- Clearing Windows Console History