Script Execution via Microsoft HTML Application

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

Script Execution via Microsoft HTML Application

edit

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.

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-*
  • logs-endpoint.events.process-*
  • logs-crowdstrike.fdr*
  • endgame-*

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: Defense Evasion
  • Data Source: Windows Security Event Logs
  • Data Source: Sysmon
  • Data Source: SentinelOne
  • Data Source: Microsoft Defender XDR
  • Data Source: Elastic Defend
  • Data Source: Crowdstrike
  • Resources: Investigation Guide
  • Data Source: Elastic Endgame

Version: 210

Rule authors:

  • Elastic

Rule license: Elastic License v2

Investigation guide

edit

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, and process.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, and process.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.
  • What parent and user context explain the launch?
  • Focus: process.parent.executable, process.parent.command_line, user.id, and host.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.
  • What referenced HTA, scriptlet, URL, or path can be recovered?
  • 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{"description":"","label":"File events for the same proxy instance","providers":[[{"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.entity_id","queryType":"phrase","value":"{{process.entity_id}}","valueType":"string"}]],"relativeFrom":"now-1h","relativeTo":"now"}} !{investigate{"description":"","label":"Network and DNS events for the same proxy instance","providers":[[{"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.entity_id","queryType":"phrase","value":"{{process.entity_id}}","valueType":"string"}],[{"excluded":false,"field":"event.category","queryType":"phrase","value":"dns","valueType":"string"},{"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"}]],"relativeFrom":"now-1h","relativeTo":"now"}}
  • 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.
  • Did the proxy spawn follow-on code or payload execution?
  • 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{"description":"","label":"Child process events for the same proxy instance","providers":[[{"excluded":false,"field":"event.category","queryType":"phrase","value":"process","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"}]],"relativeFrom":"now-1h","relativeTo":"now"}}
  • 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.
  • 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.
  • If evidence remains suspicious or incomplete, is it isolated?
  • Focus: user.id, host.id, stable process.command_line fragments, child process.executable, and child process.command_line recovered above. !{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"}} !{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, host, command fragment, or child process repeats across alerts or other hosts; keep scope local only when isolated and aligned with one recognized workflow.
  • 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, 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.
  • 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.

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.
  • 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.id and user.id; use host isolation only when child-process or staging evidence indicates active payload execution and host criticality permits it.
  • 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.

Setup

edit

Setup

This rule is designed for data generated by Elastic Defend, which provides native endpoint detection and response, along with event enrichments designed to work with our detection rules.

Setup instructions: https://ela.st/install-elastic-defend

Additional data sources

This rule also supports the following third-party 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.name : ("rundll32.exe", "mshta.exe") and
  (
     (process.command_line :
        (
        "*script*eval(*",
         "*script*GetObject*",
         "*.regread(*",
         "*WScript.Shell*",
         "*.run(*",
         "*).Exec()*",
         "*mshta*http*",
         "*mshtml*RunHTMLApplication*",
         "*mshtml*,#135*",
         "*StrReverse*",
         "*.RegWrite*",
         /* Issue #379 */
         "*window.close(*",
         "* Chr(*"
         )
     and not ?process.parent.executable :
                  ("?:\\Program Files (x86)\\Citrix\\System32\\wfshell.exe",
                   "?:\\Program Files (x86)\\Microsoft Office\\Office*\\MSACCESS.EXE",
                   "?:\\Program Files\\Quokka.Works GTInstaller\\GTInstaller.exe")
     ) or

    (process.name : "mshta.exe" and
     not process.command_line : ("*.hta*", "*.htm*", "-Embedding") and ?process.args_count >=2) or

     /* Execution of HTA file downloaded from the internet */
     (process.name : "mshta.exe" and process.command_line : "*\\Users\\*\\Downloads\\*.hta*") or

     /* Execution of HTA file from archive */
     (process.name : "mshta.exe" and
      process.args : ("?:\\Users\\*\\Temp\\7z*", "?:\\Users\\*\\Temp\\Rar$*", "?:\\Users\\*\\Temp\\Temp?_*", "?:\\Users\\*\\Temp\\BNZ.*"))
   )

Framework: MITRE ATT&CKTM