Suspicious Microsoft HTML Application Child Process

Identifies Mshta.exe spawning a suspicious child process. This may indicate adversarial activity, as Mshta is often leveraged by adversaries to execute malicious scripts and evade detection.

Elastic rule (View on GitHub)

  1[metadata]
  2creation_date = "2025/08/19"
  3integration = ["endpoint", "windows", "system", "m365_defender", "sentinel_one_cloud_funnel", "crowdstrike"]
  4maturity = "production"
  5updated_date = "2026/04/29"
  6
  7[rule]
  8author = ["Elastic"]
  9description = """
 10Identifies Mshta.exe spawning a suspicious child process. This may indicate adversarial activity, as Mshta is often
 11leveraged by adversaries to execute malicious scripts and evade detection.
 12"""
 13from = "now-9m"
 14index = [
 15    "endgame-*",
 16    "logs-crowdstrike.fdr*",
 17    "logs-endpoint.events.process-*",
 18    "logs-m365_defender.event-*",
 19    "logs-sentinel_one_cloud_funnel.*",
 20    "logs-system.security*",
 21    "logs-windows.forwarded*",
 22    "logs-windows.sysmon_operational-*",
 23    "winlogbeat-*",
 24]
 25language = "eql"
 26license = "Elastic License v2"
 27name = "Suspicious Microsoft HTML Application Child Process"
 28references = [
 29    "https://lolbas-project.github.io/lolbas/Binaries/Mshta/",
 30]
 31risk_score = 73
 32rule_id = "48e60a73-08e8-42aa-8f51-4ed92c64dbea"
 33severity = "high"
 34tags = [
 35    "Domain: Endpoint",
 36    "OS: Windows",
 37    "Use Case: Threat Detection",
 38    "Tactic: Defense Evasion",
 39    "Data Source: Elastic Endgame",
 40    "Data Source: Elastic Defend",
 41    "Data Source: Windows Security Event Logs",
 42    "Data Source: Microsoft Defender XDR",
 43    "Data Source: Sysmon",
 44    "Data Source: SentinelOne",
 45    "Data Source: Crowdstrike",
 46    "Resources: Investigation Guide",
 47]
 48timestamp_override = "event.ingested"
 49type = "eql"
 50
 51query = '''
 52process where host.os.type == "windows" and event.type == "start" and
 53  process.parent.name : "mshta.exe" and process.command_line != null and
 54  (
 55   process.name : (
 56       "cmd.exe", "powershell.exe", "certutil.exe", "bitsadmin.exe", "curl.exe", "msiexec.exe",
 57       "schtasks.exe", "reg.exe", "wscript.exe", "rundll32.exe"
 58   ) or
 59   process.executable : ("C:\\Users\\*\\*.exe", "\\Device\\HarddiskVolume*\\Users\\*\\*.exe")
 60  ) and
 61  not (process.name : "cmd.exe" and process.command_line : "*\\HP\\HP*HPUDC*") and
 62  not ?process.parent.command_line : "*\\HP\\*\\HPSolutionsPortal.hta*"
 63'''
 64
 65note = """## Triage and analysis
 66
 67### Investigating Suspicious Microsoft HTML Application Child Process
 68
 69#### Possible investigation steps
 70
 71- What did mshta broker into the child process?
 72  - Focus: `process.name`, `process.executable`, `process.command_line`, and `process.parent.command_line`, separating interpreters, script engines, transfer tools, installers, persistence utilities, DLL proxy loaders, and user-profile binaries; for transfer, installer, or user-profile children, recover same-child file and network/DNS events. $investigate_0 $investigate_1
 73  - Implication: treat download, staging, persistence, scripting, or arbitrary user-space execution as high-risk proxy execution; narrow only when child arguments and mshta command line identify one recognized HTA-driven deployment, enrollment, support, or internal-portal flow. Missing file, network, or DNS telemetry is unresolved, not benign.
 74
 75- Is the child binary identity consistent with its claimed role?
 76  - Focus: `process.executable`, `process.hash.sha256`, `process.pe.original_file_name`, `process.code_signature.subject_name`, and `process.code_signature.trusted`.
 77  - Implication: renamed, unsigned/untrusted, user-writable, newly seen, or PE-mismatched children strengthen proxy-execution; a trusted signer identifies the binary but does not clear the mshta chain.
 78
 79- What source did mshta execute?
 80  - Focus: `process.parent.executable`, `process.parent.command_line`, `process.parent.code_signature.subject_name`, and `process.parent.code_signature.trusted`, checking expected System32/SysWOW64 mshta plus inline "vbscript:"/"javascript:", "script:" monikers, remote URLs, ADS syntax, UNC paths, temp/downloads, or "INetCache" sources.
 81  - Implication: inline scriptlets, remote/ADS-backed content, user-writable sources, obfuscation, or unexpected signer/path make mshta the likely delivery mechanism; internal HTAs, vendor packages, or deployment sources must still match the child workflow.
 82
 83- What process launched mshta?
 84  - Why: recovering the mshta start event shows whether a browser, document, archive tool, installer, or management process initiated the chain.
 85  - Focus: process-start events on `host.id` where recovered `process.entity_id` equals alert `process.parent.entity_id`; if absent, use `host.id`, `process.parent.pid`, and a tight alert window, then inspect recovered `process.parent.executable` and `process.parent.command_line`. $investigate_2
 86  - Implication: Office, browser, archive, chat, script-host, or unexpected-service launchers indicate delivery or user-execution risk; software-distribution, support, enrollment, or portal launchers explain the chain only when they start the same flow on the same host cohort.
 87
 88- Did the same mshta instance launch more suspicious children?
 89  - Focus: process-start events on `host.id` where `process.parent.entity_id` matches alert `process.parent.entity_id`; fall back to `host.id`, `process.parent.pid`, and a tight alert window; inspect child `process.name`, `process.executable`, and `process.command_line`. $investigate_3
 90  - Implication: same-instance fan-out into shells, transfer tools, schedulers, configuration changes, script hosts, or multiple user-space binaries widens response beyond one child; a single child stays narrow only if it matches the recovered benign workflow.
 91
 92- Does the user, session, and host cohort fit that workflow?
 93  - Focus: `user.id`, `host.name`, `process.Ext.session_info.logon_type`, and recovered launcher `process.parent.executable`, using `host.id` as the stable host anchor.
 94  - Implication: standard-user, shared-workstation, unusual remote/service-session, or non-management-host context raises priority without matching workflow history; cohort fit is reassuring only when session type and launcher match the deployment, support, enrollment, or portal pattern.
 95
 96- If local evidence is suspicious or unresolved, does alert history show broader proxy execution?
 97  - Focus: related alerts for `user.id` in 48 hours where the same child `process.executable` or mshta command pattern (`process.command_line`, `process.parent.command_line`) recurs in proxy-execution alerts. $investigate_4
 98  - Hint: if the user view is quiet or ambiguous, compare related alerts for `host.id` in 48 hours; quiet history does not clear unresolved local evidence. $investigate_5
 99  - Implication: escalate scope when the same delivery path or child-command pattern recurs across proxy-execution alerts; stay local only when the chain is resolved and related history fits the same recognized workflow.
100
101- Escalate on suspicious child intent, identity mismatch, inline/remote/ADS mshta source, abnormal launcher, same-mshta fan-out, or broader proxy-execution history; close only when process evidence binds one exact recognized workflow on this host and no contradictions remain; preserve the process tree and escalate mixed or incomplete evidence.
102
103### False positive analysis
104
105- HP printer software (HPSolutionsPortal.hta) uses mshta to run a vendor portal that spawns cmd.exe for UDC telemetry cleanup and rundll32.exe for printui operations. The rule excludes the UDC cmd.exe pattern cross-source and the parent HTA path when `process.parent.command_line` is available. On sources without parent command_line (CrowdStrike, SecurityLog), these alerts still fire; confirm by matching `process.command_line` to HP ProgramData paths or printui.dll printer-name arguments before closing.
106- Treat software distribution, device enrollment, remote support, or internal HTA portals as benign candidates only after process telemetry proves the same chain. Confirm child `process.executable`, `process.command_line`, `process.hash.sha256`, signer, mshta `process.parent.command_line`, recovered launcher executable/command line, and `user.id` plus `host.id` cohort. Use change records, support tickets, asset-role inventories, or prior alerts only as corroboration; never close unresolved local process evidence on recurrence or workflow labels alone.
107- Do not close on partial matches. Inline scriptlets, remote URLs, ADS syntax, user-profile child executables, unexpected launchers, or same-mshta fan-out contradict a benign HTA workflow unless process telemetry and outside confirmation verify that exact activity.
108- Build exceptions from the minimum confirmed pattern: recovered launcher `process.parent.executable`, mshta `process.parent.command_line`, child `process.executable` plus `process.command_line`, and stable `user.id` or `host.id` cohort. Avoid exceptions on mshta alone, `process.name` alone, or `user.name` alone.
109
110### Response and remediation
111
112- If confirmed benign, record the child `process.command_line`, mshta `process.parent.command_line`, recovered launcher `process.parent.executable`, `user.id`, and `host.id` evidence that validated the workflow, then reverse temporary containment. Create an exception only for that narrow process pattern, using prior alerts as stability evidence when available.
113- If suspicious but unconfirmed, preserve the alert record, process tree, child `process.entity_id`, alert `process.parent.entity_id`, child and mshta command lines, child `process.hash.sha256`, signer evidence, recovered launcher, `process.Ext.session_info.logon_type`, and related-alert results before containment. Apply reversible controls first, such as blocking the exact HTA URL or share visible in `process.parent.command_line`, restricting the child hash or path, or increasing monitoring on the affected `host.id` and `user.id`.
114- If confirmed malicious, isolate the host or terminate the mshta/child process only after recording the child and mshta entity IDs, command lines, launcher, hash, signer, user, and host evidence. If endpoint response is unavailable, hand off that preserved evidence to the team that can contain the endpoint or affected account.
115- After containment, block confirmed malicious child hashes, child executable paths, and exact mshta command-line sources, then remove only scripts, binaries, scheduled tasks, or persistence changes proven to belong to this chain. Remediate the delivery vector that started mshta, such as browser download, attachment, archive extraction, remote share, software package, or compromised management workflow.
116- Post-incident hardening: restrict mshta use for users and hosts that do not need HTA execution, package legitimate HTA workflows through signed deployment tooling, and record adjacent variants such as inline "vbscript:" / "javascript:", remote "script:" monikers, ADS-backed HTAs, and INetCache retrievals for future triage.
117"""
118
119setup = """## Setup
120
121This 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.
122
123Setup instructions: https://ela.st/install-elastic-defend
124
125### Additional data sources
126
127This rule also supports the following third-party data sources. For setup instructions, refer to the links below:
128
129- [CrowdStrike](https://ela.st/crowdstrike-integration)
130- [Microsoft Defender XDR](https://ela.st/m365-defender)
131- [SentinelOne Cloud Funnel](https://ela.st/sentinel-one-cloud-funnel)
132- [Sysmon Event ID 1 - Process Creation](https://ela.st/sysmon-event-1-setup)
133- [Windows Process Creation Logs](https://ela.st/audit-process-creation)
134"""
135
136[rule.investigation_fields]
137field_names = [
138    "@timestamp",
139    "host.name",
140    "host.id",
141    "user.name",
142    "user.id",
143    "process.entity_id",
144    "process.pid",
145    "process.executable",
146    "process.command_line",
147    "process.Ext.session_info.logon_type",
148    "process.pe.original_file_name",
149    "process.hash.sha256",
150    "process.code_signature.trusted",
151    "process.parent.entity_id",
152    "process.parent.command_line",
153]
154
155[transform]
156
157[[transform.investigate]]
158label = "File events for the child process"
159description = ""
160providers = [
161  [
162    { excluded = false, field = "event.category", queryType = "phrase", value = "file", valueType = "string" },
163    { excluded = false, field = "host.id", queryType = "phrase", value = "{{host.id}}", valueType = "string" },
164    { excluded = false, field = "process.entity_id", queryType = "phrase", value = "{{process.entity_id}}", valueType = "string" }
165  ]
166]
167relativeFrom = "now-1h"
168relativeTo = "now"
169
170[[transform.investigate]]
171label = "Network and DNS events for the child process"
172description = ""
173providers = [
174  [
175    { excluded = false, field = "event.category", queryType = "phrase", value = "network", valueType = "string" },
176    { excluded = false, field = "host.id", queryType = "phrase", value = "{{host.id}}", valueType = "string" },
177    { excluded = false, field = "process.entity_id", queryType = "phrase", value = "{{process.entity_id}}", valueType = "string" }
178  ],
179  [
180    { excluded = false, field = "event.category", queryType = "phrase", value = "dns", valueType = "string" },
181    { excluded = false, field = "host.id", queryType = "phrase", value = "{{host.id}}", valueType = "string" },
182    { excluded = false, field = "process.entity_id", queryType = "phrase", value = "{{process.entity_id}}", valueType = "string" }
183  ]
184]
185relativeFrom = "now-1h"
186relativeTo = "now"
187
188[[transform.investigate]]
189label = "Mshta parent process event"
190description = ""
191providers = [
192  [
193    { excluded = false, field = "event.category", queryType = "phrase", value = "process", valueType = "string" },
194    { excluded = false, field = "host.id", queryType = "phrase", value = "{{host.id}}", valueType = "string" },
195    { excluded = false, field = "process.entity_id", queryType = "phrase", value = "{{process.parent.entity_id}}", valueType = "string" }
196  ]
197]
198relativeFrom = "now-1h"
199relativeTo = "now"
200
201[[transform.investigate]]
202label = "Process events launched by the same mshta instance"
203description = ""
204providers = [
205  [
206    { excluded = false, field = "event.category", queryType = "phrase", value = "process", valueType = "string" },
207    { excluded = false, field = "host.id", queryType = "phrase", value = "{{host.id}}", valueType = "string" },
208    { excluded = false, field = "process.parent.entity_id", queryType = "phrase", value = "{{process.parent.entity_id}}", valueType = "string" }
209  ]
210]
211relativeFrom = "now-1h"
212relativeTo = "now"
213
214[[transform.investigate]]
215label = "Alerts associated with the user"
216description = ""
217providers = [
218  [
219    { excluded = false, field = "event.kind", queryType = "phrase", value = "signal", valueType = "string" },
220    { excluded = false, field = "user.id", queryType = "phrase", value = "{{user.id}}", valueType = "string" }
221  ]
222]
223relativeFrom = "now-48h/h"
224relativeTo = "now"
225
226[[transform.investigate]]
227label = "Alerts associated with the host"
228description = ""
229providers = [
230  [
231    { excluded = false, field = "event.kind", queryType = "phrase", value = "signal", valueType = "string" },
232    { excluded = false, field = "host.id", queryType = "phrase", value = "{{host.id}}", valueType = "string" }
233  ]
234]
235relativeFrom = "now-48h/h"
236relativeTo = "now"
237
238[[rule.threat]]
239framework = "MITRE ATT&CK"
240
241[[rule.threat.technique]]
242id = "T1218"
243name = "System Binary Proxy Execution"
244reference = "https://attack.mitre.org/techniques/T1218/"
245
246[[rule.threat.technique.subtechnique]]
247id = "T1218.005"
248name = "Mshta"
249reference = "https://attack.mitre.org/techniques/T1218/005/"
250
251[[rule.threat.technique.subtechnique]]
252id = "T1218.007"
253name = "Msiexec"
254reference = "https://attack.mitre.org/techniques/T1218/007/"
255
256[[rule.threat.technique.subtechnique]]
257id = "T1218.011"
258name = "Rundll32"
259reference = "https://attack.mitre.org/techniques/T1218/011/"
260
261[rule.threat.tactic]
262id = "TA0005"
263name = "Defense Evasion"
264reference = "https://attack.mitre.org/tactics/TA0005/"
265
266[[rule.threat]]
267framework = "MITRE ATT&CK"
268
269[[rule.threat.technique]]
270id = "T1059"
271name = "Command and Scripting Interpreter"
272reference = "https://attack.mitre.org/techniques/T1059/"
273
274[[rule.threat.technique.subtechnique]]
275id = "T1059.001"
276name = "PowerShell"
277reference = "https://attack.mitre.org/techniques/T1059/001/"
278
279[[rule.threat.technique.subtechnique]]
280id = "T1059.003"
281name = "Windows Command Shell"
282reference = "https://attack.mitre.org/techniques/T1059/003/"
283
284[rule.threat.tactic]
285id = "TA0002"
286name = "Execution"
287reference = "https://attack.mitre.org/tactics/TA0002/"

Triage and analysis

Investigating Suspicious Microsoft HTML Application Child Process

Possible investigation steps

  • What did mshta broker into the child process?

    • Focus: process.name, process.executable, process.command_line, and process.parent.command_line, separating interpreters, script engines, transfer tools, installers, persistence utilities, DLL proxy loaders, and user-profile binaries; for transfer, installer, or user-profile children, recover same-child file and network/DNS events. $investigate_0 $investigate_1
    • Implication: treat download, staging, persistence, scripting, or arbitrary user-space execution as high-risk proxy execution; narrow only when child arguments and mshta command line identify one recognized HTA-driven deployment, enrollment, support, or internal-portal flow. Missing file, network, or DNS telemetry is unresolved, not benign.
  • Is the child binary identity consistent with its claimed role?

    • Focus: process.executable, process.hash.sha256, process.pe.original_file_name, process.code_signature.subject_name, and process.code_signature.trusted.
    • Implication: renamed, unsigned/untrusted, user-writable, newly seen, or PE-mismatched children strengthen proxy-execution; a trusted signer identifies the binary but does not clear the mshta chain.
  • What source did mshta execute?

    • Focus: process.parent.executable, process.parent.command_line, process.parent.code_signature.subject_name, and process.parent.code_signature.trusted, checking expected System32/SysWOW64 mshta plus inline "vbscript:"/"javascript:", "script:" monikers, remote URLs, ADS syntax, UNC paths, temp/downloads, or "INetCache" sources.
    • Implication: inline scriptlets, remote/ADS-backed content, user-writable sources, obfuscation, or unexpected signer/path make mshta the likely delivery mechanism; internal HTAs, vendor packages, or deployment sources must still match the child workflow.
  • What process launched mshta?

    • Why: recovering the mshta start event shows whether a browser, document, archive tool, installer, or management process initiated the chain.
    • Focus: process-start events on host.id where recovered process.entity_id equals alert process.parent.entity_id; if absent, use host.id, process.parent.pid, and a tight alert window, then inspect recovered process.parent.executable and process.parent.command_line. $investigate_2
    • Implication: Office, browser, archive, chat, script-host, or unexpected-service launchers indicate delivery or user-execution risk; software-distribution, support, enrollment, or portal launchers explain the chain only when they start the same flow on the same host cohort.
  • Did the same mshta instance launch more suspicious children?

    • Focus: process-start events on host.id where process.parent.entity_id matches alert process.parent.entity_id; fall back to host.id, process.parent.pid, and a tight alert window; inspect child process.name, process.executable, and process.command_line. $investigate_3
    • Implication: same-instance fan-out into shells, transfer tools, schedulers, configuration changes, script hosts, or multiple user-space binaries widens response beyond one child; a single child stays narrow only if it matches the recovered benign workflow.
  • Does the user, session, and host cohort fit that workflow?

    • Focus: user.id, host.name, process.Ext.session_info.logon_type, and recovered launcher process.parent.executable, using host.id as the stable host anchor.
    • Implication: standard-user, shared-workstation, unusual remote/service-session, or non-management-host context raises priority without matching workflow history; cohort fit is reassuring only when session type and launcher match the deployment, support, enrollment, or portal pattern.
  • If local evidence is suspicious or unresolved, does alert history show broader proxy execution?

    • Focus: related alerts for user.id in 48 hours where the same child process.executable or mshta command pattern (process.command_line, process.parent.command_line) recurs in proxy-execution alerts. $investigate_4
    • Hint: if the user view is quiet or ambiguous, compare related alerts for host.id in 48 hours; quiet history does not clear unresolved local evidence. $investigate_5
    • Implication: escalate scope when the same delivery path or child-command pattern recurs across proxy-execution alerts; stay local only when the chain is resolved and related history fits the same recognized workflow.
  • Escalate on suspicious child intent, identity mismatch, inline/remote/ADS mshta source, abnormal launcher, same-mshta fan-out, or broader proxy-execution history; close only when process evidence binds one exact recognized workflow on this host and no contradictions remain; preserve the process tree and escalate mixed or incomplete evidence.

False positive analysis

  • HP printer software (HPSolutionsPortal.hta) uses mshta to run a vendor portal that spawns cmd.exe for UDC telemetry cleanup and rundll32.exe for printui operations. The rule excludes the UDC cmd.exe pattern cross-source and the parent HTA path when process.parent.command_line is available. On sources without parent command_line (CrowdStrike, SecurityLog), these alerts still fire; confirm by matching process.command_line to HP ProgramData paths or printui.dll printer-name arguments before closing.
  • Treat software distribution, device enrollment, remote support, or internal HTA portals as benign candidates only after process telemetry proves the same chain. Confirm child process.executable, process.command_line, process.hash.sha256, signer, mshta process.parent.command_line, recovered launcher executable/command line, and user.id plus host.id cohort. Use change records, support tickets, asset-role inventories, or prior alerts only as corroboration; never close unresolved local process evidence on recurrence or workflow labels alone.
  • Do not close on partial matches. Inline scriptlets, remote URLs, ADS syntax, user-profile child executables, unexpected launchers, or same-mshta fan-out contradict a benign HTA workflow unless process telemetry and outside confirmation verify that exact activity.
  • Build exceptions from the minimum confirmed pattern: recovered launcher process.parent.executable, mshta process.parent.command_line, child process.executable plus process.command_line, and stable user.id or host.id cohort. Avoid exceptions on mshta alone, process.name alone, or user.name alone.

Response and remediation

  • If confirmed benign, record the child process.command_line, mshta process.parent.command_line, recovered launcher process.parent.executable, user.id, and host.id evidence that validated the workflow, then reverse temporary containment. Create an exception only for that narrow process pattern, using prior alerts as stability evidence when available.
  • If suspicious but unconfirmed, preserve the alert record, process tree, child process.entity_id, alert process.parent.entity_id, child and mshta command lines, child process.hash.sha256, signer evidence, recovered launcher, process.Ext.session_info.logon_type, and related-alert results before containment. Apply reversible controls first, such as blocking the exact HTA URL or share visible in process.parent.command_line, restricting the child hash or path, or increasing monitoring on the affected host.id and user.id.
  • If confirmed malicious, isolate the host or terminate the mshta/child process only after recording the child and mshta entity IDs, command lines, launcher, hash, signer, user, and host evidence. If endpoint response is unavailable, hand off that preserved evidence to the team that can contain the endpoint or affected account.
  • After containment, block confirmed malicious child hashes, child executable paths, and exact mshta command-line sources, then remove only scripts, binaries, scheduled tasks, or persistence changes proven to belong to this chain. Remediate the delivery vector that started mshta, such as browser download, attachment, archive extraction, remote share, software package, or compromised management workflow.
  • Post-incident hardening: restrict mshta use for users and hosts that do not need HTA execution, package legitimate HTA workflows through signed deployment tooling, and record adjacent variants such as inline "vbscript:" / "javascript:", remote "script:" monikers, ADS-backed HTAs, and INetCache retrievals for future triage.

References

Related rules

to-top