Script Execution via Microsoft HTML Application
Identifies the execution of scripts via HTML applications using Windows utilities rundll32.exe or mshta.exe. Adversaries may bypass process and/or signature-based defenses by proxying execution of malicious content with signed binaries.
Elastic rule (View on GitHub)
1[metadata]
2creation_date = "2020/09/09"
3integration = ["endpoint", "windows", "system", "sentinel_one_cloud_funnel", "m365_defender", "crowdstrike"]
4maturity = "production"
5updated_date = "2026/10/09"
6
7[rule]
8author = ["Elastic"]
9description = """
10Identifies the execution of scripts via HTML applications using Windows utilities rundll32.exe or mshta.exe. Adversaries
11may bypass process and/or signature-based defenses by proxying execution of malicious content with signed binaries.
12"""
13from = "now-9m"
14index = [
15 "logs-m365_defender.event-*",
16 "logs-sentinel_one_cloud_funnel.*",
17 "logs-system.security*",
18 "logs-windows.forwarded*",
19 "logs-windows.sysmon_operational-*",
20 "winlogbeat-*",
21 "logs-endpoint.events.process-*",
22 "logs-crowdstrike.fdr*",
23 "endgame-*"
24]
25language = "eql"
26license = "Elastic License v2"
27name = "Script Execution via Microsoft HTML Application"
28risk_score = 73
29rule_id = "181f6b23-3799-445e-9589-0018328a9e46"
30severity = "high"
31tags = [
32 "Domain: Endpoint",
33 "OS: Windows",
34 "Use Case: Threat Detection",
35 "Tactic: Defense Evasion",
36 "Data Source: Windows Security Event Logs",
37 "Data Source: Sysmon",
38 "Data Source: SentinelOne",
39 "Data Source: Microsoft Defender XDR",
40 "Data Source: Elastic Defend",
41 "Data Source: Crowdstrike",
42 "Resources: Investigation Guide",
43 "Data Source: Elastic Endgame",
44 "Noise: Low",
45 "Performance: Normal",
46 "Profile: Recommended",
47 "Threat: Living off the Land",
48 "Rule Type: Event Correlation (EQL)",
49 "Platform: Windows",
50]
51timestamp_override = "event.ingested"
52type = "eql"
53
54query = '''
55process where host.os.type == "windows" and event.type == "start" and
56 process.name : ("rundll32.exe", "mshta.exe") and
57 (
58 (process.command_line :
59 (
60 "*script*eval(*",
61 "*script*GetObject*",
62 "*.regread(*",
63 "*WScript.Shell*",
64 "*.run(*",
65 "*).Exec()*",
66 "*mshta*http*",
67 "*mshtml*RunHTMLApplication*",
68 "*mshtml*,#135*",
69 "*StrReverse*",
70 "*.RegWrite*",
71 /* Issue #379 */
72 "*window.close(*",
73 "* Chr(*"
74 ) and
75 not (
76 ?process.parent.executable : (
77 "?:\\Program Files (x86)\\Citrix\\System32\\wfshell.exe",
78 "?:\\Program Files (x86)\\Microsoft Office\\Office*\\MSACCESS.EXE",
79 "?:\\Program Files\\Quokka.Works GTInstaller\\GTInstaller.exe") and
80 ?process.parent.executable != null
81 )
82 ) or
83
84 (process.name : "mshta.exe" and
85 not process.command_line : ("*.hta*", "*.htm*", "-Embedding") and process.args_count >=2) or
86
87 /* Execution of HTA file downloaded from the internet */
88 (process.name : "mshta.exe" and process.command_line : "*\\Users\\*\\Downloads\\*.hta*") or
89
90 /* Execution of HTA file from archive */
91 (process.name : "mshta.exe" and
92 process.args : ("?:\\Users\\*\\Temp\\7z*", "?:\\Users\\*\\Temp\\Rar$*", "?:\\Users\\*\\Temp\\Temp?_*", "?:\\Users\\*\\Temp\\BNZ.*"))
93 )
94'''
95
96note = """## Triage and analysis
97
98### Investigating Script Execution via Microsoft HTML Application
99
100#### Possible investigation steps
101
102- Which HTML-application proxy path did the alert capture?
103 - Why: proxy path determines the containment target.
104 - Focus: `process.name`, `process.command_line`, and `process.args_count`: ".hta", ".htm", "vbscript:", "javascript:", "GetObject("script:")", "mshtml,RunHTMLApplication", "mshtml,#135", "http", "WScript.Shell", "StrReverse", "window.close(", or "Chr(".
105 - Implication: escalate on inline script, remote retrieval, obfuscation, "RunHTMLApplication", archive/temp execution, or non-HTA "mshta.exe"; lower concern only for one stable internal HTA/HTM path with no inline script, remote locator, or obfuscation.
106
107- Is the proxy binary a genuine Microsoft LOLBin or a masqueraded executable?
108 - Focus: `process.executable`, `process.pe.original_file_name`, `process.hash.sha256`, `process.code_signature.subject_name`, and `process.code_signature.trusted`.
109 - Implication: escalate when "mshta.exe" or "rundll32.exe" runs from a user-writable or non-Windows path, has a mismatched original filename, or lacks a trusted Microsoft signature; canonical Microsoft identity lowers masquerade risk but does not clear suspicious arguments.
110
111- What parent and user context explain the launch?
112 - Focus: `process.parent.executable`, `process.parent.command_line`, `user.id`, and `host.id`.
113 - Implication: escalate when the parent is Office, a browser, archive utility, script host, user-writable executable, or a chain outside the rule's excluded parents; lower concern when the same parent, user cohort, and host cohort repeatedly launch the same recognized HTA workflow.
114
115- What referenced HTA, scriptlet, URL, or path can be recovered?
116 - Focus: `process.command_line`, `process.args`, and `process.working_directory`: literal HTA/HTM path, scriptlet URL, remote locator, archive/temp marker, or relative path; recover same-process file and network/DNS events when artifact or remote locator evidence exists. $investigate_0 $investigate_1
117 - Implication: escalate when the locator points to Downloads, Temp, archive extraction, external URLs, scriptlet retrieval, alternate data stream-like syntax, or a single-user path; lower concern only for the same stable internal path from the same recognized workflow. Missing file, network, or DNS telemetry is unresolved, not benign.
118
119- Did the proxy spawn follow-on code or payload execution?
120 - Focus: child starts on `host.id` where `process.parent.entity_id` equals alert `process.entity_id`; inspect child `process.executable`, `process.command_line`, `process.pe.original_file_name`, `process.code_signature.subject_name`, and `process.code_signature.trusted`. $investigate_2
121 - Hint: if `process.entity_id` is absent, use `host.id` + `process.pid` + the tight alert window as a weaker fallback; treat PID reuse as unresolved ambiguity.
122 - Implication: escalate when the proxy spawns shells, PowerShell, script hosts, "regsvr32.exe", another "rundll32.exe", unsigned payloads, or tooling unrelated to the parent workflow; lower concern when child activity stays within the same recognized signed application flow.
123
124- If evidence remains suspicious or incomplete, is it isolated?
125 - Focus: `user.id`, `host.id`, stable `process.command_line` fragments, child `process.executable`, and child `process.command_line` recovered above. $investigate_3 $investigate_4
126 - Implication: broaden scope when the same user, host, command fragment, or child process repeats across alerts or other hosts; keep scope local only when isolated and aligned with one recognized workflow.
127
128- Escalate on proxy script execution, masquerade, suspicious lineage, external/temporary sourcing, follow-on payloads, or recurrence; close only when command intent, binary identity, lineage, locator, child behavior, and scope align with one recognized internal HTA/HTM workflow; preserve artifacts and escalate when evidence is mixed or incomplete.
129
130### False positive analysis
131
132- Legacy internal HTA applications or support tools may use "mshta.exe" when identity, intent, and context align: canonical Microsoft `process.executable`, stable `process.parent.executable`, repeated `process.command_line` for one internal HTA/HTM path, consistent `user.id`/`host.id` cohort, and no child branching into shells or script hosts. If inventory, owner, or change records exist, require alignment with this telemetry; otherwise require recurrence of the same stable process pattern across prior alerts from this rule for the same cohort.
133- Vendor installers or deployment tools can trigger archive/temp HTA patterns when parent executable, signer context, command line, and bounded child chain match the same recognized package workflow. Do not close on parent name alone; contradictory locator, child process, user/host scope, or signer evidence stays suspicious. Exceptions should use the minimum confirmed pattern, such as `process.parent.executable` + stable `process.command_line` fragment + `host.id` or `user.id`, not `process.name`.
134
135### Response and remediation
136
137- If confirmed benign:
138 - Reverse temporary containment and record the parent workflow, `process.command_line`, extracted locator/path, `user.id`, `host.id`, and recurrence or business records that confirmed the recognized application path. Build exceptions only from the minimum stable workflow pattern, not from "mshta.exe" or "rundll32.exe" alone.
139- If suspicious but unconfirmed:
140 - Preserve the alert event export, process tree, `process.entity_id`, `process.pid`, `process.command_line`, `process.args`, parent lineage, user/host context, recovered child process events, and literal URLs or paths extracted from the command line before cleanup.
141 - Apply reversible containment tied to the findings, such as temporary destination restrictions for remote locators, child-process blocking, or heightened monitoring on the affected `host.id` and `user.id`; use host isolation only when child-process or staging evidence indicates active payload execution and host criticality permits it.
142- If confirmed malicious:
143 - Isolate the host or contain the affected identity after preserving the process and child-process evidence that established malicious execution. Terminate the proxy and spawned payload processes only after recording their identifiers and command lines.
144 - Block confirmed malicious command-line locators, child binaries, domains, and addresses identified during triage, then review other hosts and users for the same command fragment or child-process pattern before eradication.
145 - Remove the malicious HTA, scriptlet, archive-extracted payload, or staged child artifacts identified during investigation; remediate the parent document, browser, archive, or script delivery path; investigate credential exposure if follow-on behavior suggests collection or lateral movement.
146- Post-incident hardening:
147 - Restrict or monitor "mshta.exe" and unusual "rundll32.exe" script-execution paths where the business does not require them.
148 - Retain process telemetry for these binaries and record any missing artifact, library, or destination visibility that limited the case so future triage can account for the gap.
149"""
150
151setup = """## Setup
152
153This rule is designed for data generated by [Elastic Defend](https://www.elastic.co/security/endpoint-security), which provides native endpoint detection and response, along with event enrichments designed to work with our detection rules.
154
155Setup instructions: https://ela.st/install-elastic-defend
156
157### Additional data sources
158
159This rule also supports the following third-party data sources. For setup instructions, refer to the links below:
160
161- [CrowdStrike](https://ela.st/crowdstrike-integration)
162- [Microsoft Defender XDR](https://ela.st/m365-defender)
163- [SentinelOne Cloud Funnel](https://ela.st/sentinel-one-cloud-funnel)
164- [Sysmon Event ID 1 - Process Creation](https://ela.st/sysmon-event-1-setup)
165- [Windows Process Creation Logs](https://ela.st/audit-process-creation)
166"""
167
168[rule.investigation_fields]
169field_names = [
170 "@timestamp",
171 "host.name",
172 "host.id",
173 "user.name",
174 "user.id",
175 "process.entity_id",
176 "process.code_signature.subject_name",
177 "process.executable",
178 "process.command_line",
179 "process.args",
180 "process.pe.original_file_name",
181 "process.code_signature.trusted",
182 "process.parent.entity_id",
183 "process.parent.executable",
184 "process.parent.command_line",
185]
186
187[transform]
188
189[[transform.investigate]]
190label = "File events for the same proxy instance"
191description = ""
192providers = [
193 [
194 { excluded = false, field = "event.category", queryType = "phrase", value = "file", valueType = "string" },
195 { excluded = false, field = "host.id", queryType = "phrase", value = "{{host.id}}", valueType = "string" },
196 { excluded = false, field = "process.entity_id", queryType = "phrase", value = "{{process.entity_id}}", valueType = "string" }
197 ]
198]
199relativeFrom = "now-1h"
200relativeTo = "now"
201
202[[transform.investigate]]
203label = "Network and DNS events for the same proxy instance"
204description = ""
205providers = [
206 [
207 { excluded = false, field = "event.category", queryType = "phrase", value = "network", valueType = "string" },
208 { excluded = false, field = "host.id", queryType = "phrase", value = "{{host.id}}", valueType = "string" },
209 { excluded = false, field = "process.entity_id", queryType = "phrase", value = "{{process.entity_id}}", valueType = "string" }
210 ],
211 [
212 { excluded = false, field = "event.category", queryType = "phrase", value = "dns", valueType = "string" },
213 { excluded = false, field = "host.id", queryType = "phrase", value = "{{host.id}}", valueType = "string" },
214 { excluded = false, field = "process.entity_id", queryType = "phrase", value = "{{process.entity_id}}", valueType = "string" }
215 ]
216]
217relativeFrom = "now-1h"
218relativeTo = "now"
219
220[[transform.investigate]]
221label = "Child process events for the same proxy instance"
222description = ""
223providers = [
224 [
225 { excluded = false, field = "event.category", queryType = "phrase", value = "process", valueType = "string" },
226 { excluded = false, field = "host.id", queryType = "phrase", value = "{{host.id}}", valueType = "string" },
227 { excluded = false, field = "process.parent.entity_id", queryType = "phrase", value = "{{process.entity_id}}", valueType = "string" }
228 ]
229]
230relativeFrom = "now-1h"
231relativeTo = "now"
232
233[[transform.investigate]]
234label = "Alerts associated with the user"
235description = ""
236providers = [
237 [
238 { excluded = false, field = "event.kind", queryType = "phrase", value = "signal", valueType = "string" },
239 { excluded = false, field = "user.id", queryType = "phrase", value = "{{user.id}}", valueType = "string" }
240 ]
241]
242relativeFrom = "now-48h/h"
243relativeTo = "now"
244
245[[transform.investigate]]
246label = "Alerts associated with the host"
247description = ""
248providers = [
249 [
250 { excluded = false, field = "event.kind", queryType = "phrase", value = "signal", valueType = "string" },
251 { excluded = false, field = "host.id", queryType = "phrase", value = "{{host.id}}", valueType = "string" }
252 ]
253]
254relativeFrom = "now-48h/h"
255relativeTo = "now"
256
257[[rule.threat]]
258framework = "MITRE ATT&CK"
259
260[[rule.threat.technique]]
261id = "T1218"
262name = "System Binary Proxy Execution"
263reference = "https://attack.mitre.org/techniques/T1218/"
264
265[[rule.threat.technique.subtechnique]]
266id = "T1218.005"
267name = "Mshta"
268reference = "https://attack.mitre.org/techniques/T1218/005/"
269
270[[rule.threat.technique.subtechnique]]
271id = "T1218.011"
272name = "Rundll32"
273reference = "https://attack.mitre.org/techniques/T1218/011/"
274
275[rule.threat.tactic]
276id = "TA0005"
277name = "Defense Evasion"
278reference = "https://attack.mitre.org/tactics/TA0005/"
279
280[[rule.threat]]
281framework = "MITRE ATT&CK"
282
283[[rule.threat.technique]]
284id = "T1059"
285name = "Command and Scripting Interpreter"
286reference = "https://attack.mitre.org/techniques/T1059/"
287
288[[rule.threat.technique.subtechnique]]
289id = "T1059.005"
290name = "Visual Basic"
291reference = "https://attack.mitre.org/techniques/T1059/005/"
292
293[[rule.threat.technique.subtechnique]]
294id = "T1059.007"
295name = "JavaScript"
296reference = "https://attack.mitre.org/techniques/T1059/007/"
297
298[rule.threat.tactic]
299id = "TA0002"
300name = "Execution"
301reference = "https://attack.mitre.org/tactics/TA0002/"
Triage and analysis
Investigating Script Execution via Microsoft HTML Application
Possible investigation steps
-
Which HTML-application proxy path did the alert capture?
- Why: proxy path determines the containment target.
- Focus:
process.name,process.command_line, andprocess.args_count: ".hta", ".htm", "vbscript:", "javascript:", "GetObject("script:")", "mshtml,RunHTMLApplication", "mshtml,#135", "http", "WScript.Shell", "StrReverse", "window.close(", or "Chr(". - Implication: escalate on inline script, remote retrieval, obfuscation, "RunHTMLApplication", archive/temp execution, or non-HTA "mshta.exe"; lower concern only for one stable internal HTA/HTM path with no inline script, remote locator, or obfuscation.
-
Is the proxy binary a genuine Microsoft LOLBin or a masqueraded executable?
- Focus:
process.executable,process.pe.original_file_name,process.hash.sha256,process.code_signature.subject_name, andprocess.code_signature.trusted. - Implication: escalate when "mshta.exe" or "rundll32.exe" runs from a user-writable or non-Windows path, has a mismatched original filename, or lacks a trusted Microsoft signature; canonical Microsoft identity lowers masquerade risk but does not clear suspicious arguments.
- Focus:
-
What parent and user context explain the launch?
- Focus:
process.parent.executable,process.parent.command_line,user.id, andhost.id. - Implication: escalate when the parent is Office, a browser, archive utility, script host, user-writable executable, or a chain outside the rule's excluded parents; lower concern when the same parent, user cohort, and host cohort repeatedly launch the same recognized HTA workflow.
- Focus:
-
What referenced HTA, scriptlet, URL, or path can be recovered?
- Focus:
process.command_line,process.args, andprocess.working_directory: literal HTA/HTM path, scriptlet URL, remote locator, archive/temp marker, or relative path; recover same-process file and network/DNS events when artifact or remote locator evidence exists. $investigate_0 $investigate_1 - Implication: escalate when the locator points to Downloads, Temp, archive extraction, external URLs, scriptlet retrieval, alternate data stream-like syntax, or a single-user path; lower concern only for the same stable internal path from the same recognized workflow. Missing file, network, or DNS telemetry is unresolved, not benign.
- Focus:
-
Did the proxy spawn follow-on code or payload execution?
- Focus: child starts on
host.idwhereprocess.parent.entity_idequals alertprocess.entity_id; inspect childprocess.executable,process.command_line,process.pe.original_file_name,process.code_signature.subject_name, andprocess.code_signature.trusted. $investigate_2 - Hint: if
process.entity_idis absent, usehost.id+process.pid+ the tight alert window as a weaker fallback; treat PID reuse as unresolved ambiguity. - Implication: escalate when the proxy spawns shells, PowerShell, script hosts, "regsvr32.exe", another "rundll32.exe", unsigned payloads, or tooling unrelated to the parent workflow; lower concern when child activity stays within the same recognized signed application flow.
- Focus: child starts on
-
If evidence remains suspicious or incomplete, is it isolated?
- Focus:
user.id,host.id, stableprocess.command_linefragments, childprocess.executable, and childprocess.command_linerecovered above. $investigate_3 $investigate_4 - Implication: broaden scope when the same user, host, command fragment, or child process repeats across alerts or other hosts; keep scope local only when isolated and aligned with one recognized workflow.
- Focus:
-
Escalate on proxy script execution, masquerade, suspicious lineage, external/temporary sourcing, follow-on payloads, or recurrence; close only when command intent, binary identity, lineage, locator, child behavior, and scope align with one recognized internal HTA/HTM workflow; preserve artifacts and escalate when evidence is mixed or incomplete.
False positive analysis
- Legacy internal HTA applications or support tools may use "mshta.exe" when identity, intent, and context align: canonical Microsoft
process.executable, stableprocess.parent.executable, repeatedprocess.command_linefor one internal HTA/HTM path, consistentuser.id/host.idcohort, and no child branching into shells or script hosts. If inventory, owner, or change records exist, require alignment with this telemetry; otherwise require recurrence of the same stable process pattern across prior alerts from this rule for the same cohort. - Vendor installers or deployment tools can trigger archive/temp HTA patterns when parent executable, signer context, command line, and bounded child chain match the same recognized package workflow. Do not close on parent name alone; contradictory locator, child process, user/host scope, or signer evidence stays suspicious. Exceptions should use the minimum confirmed pattern, such as
process.parent.executable+ stableprocess.command_linefragment +host.idoruser.id, notprocess.name.
Response and remediation
- If confirmed benign:
- Reverse temporary containment and record the parent workflow,
process.command_line, extracted locator/path,user.id,host.id, and recurrence or business records that confirmed the recognized application path. Build exceptions only from the minimum stable workflow pattern, not from "mshta.exe" or "rundll32.exe" alone.
- Reverse temporary containment and record the parent workflow,
- If suspicious but unconfirmed:
- Preserve the alert event export, process tree,
process.entity_id,process.pid,process.command_line,process.args, parent lineage, user/host context, recovered child process events, and literal URLs or paths extracted from the command line before cleanup. - Apply reversible containment tied to the findings, such as temporary destination restrictions for remote locators, child-process blocking, or heightened monitoring on the affected
host.idanduser.id; use host isolation only when child-process or staging evidence indicates active payload execution and host criticality permits it.
- Preserve the alert event export, process tree,
- If confirmed malicious:
- Isolate the host or contain the affected identity after preserving the process and child-process evidence that established malicious execution. Terminate the proxy and spawned payload processes only after recording their identifiers and command lines.
- Block confirmed malicious command-line locators, child binaries, domains, and addresses identified during triage, then review other hosts and users for the same command fragment or child-process pattern before eradication.
- Remove the malicious HTA, scriptlet, archive-extracted payload, or staged child artifacts identified during investigation; remediate the parent document, browser, archive, or script delivery path; investigate credential exposure if follow-on behavior suggests collection or lateral movement.
- Post-incident hardening:
- Restrict or monitor "mshta.exe" and unusual "rundll32.exe" script-execution paths where the business does not require them.
- Retain process telemetry for these binaries and record any missing artifact, library, or destination visibility that limited the case so future triage can account for the gap.
Related rules
- Execution via Windows Command Debugging Utility
- Potential File Transfer via Certreq
- Suspicious Shell Execution via Velociraptor
- Suspicious Microsoft HTML Application Child Process
- Control Panel Process with Unusual Arguments