Privilege Escalation via Windir Environment Variable
Identifies a privilege escalation attempt via a rogue Windows directory (Windir) environment variable. This is a known primitive that is often combined with other vulnerabilities to elevate privileges.
Elastic rule (View on GitHub)
1[metadata]
2creation_date = "2020/11/26"
3integration = ["endpoint", "windows", "m365_defender", "sentinel_one_cloud_funnel", "crowdstrike"]
4maturity = "production"
5updated_date = "2026/05/03"
6
7[rule]
8author = ["Elastic"]
9description = """
10Identifies a privilege escalation attempt via a rogue Windows directory (Windir) environment variable. This is a known
11primitive that is often combined with other vulnerabilities to elevate privileges.
12"""
13from = "now-9m"
14index = [
15 "logs-endpoint.events.registry-*",
16 "endgame-*",
17 "logs-windows.sysmon_operational-*",
18 "winlogbeat-*",
19 "logs-m365_defender.event-*",
20 "logs-sentinel_one_cloud_funnel.*",
21 "logs-crowdstrike.fdr*",
22]
23language = "eql"
24license = "Elastic License v2"
25name = "Privilege Escalation via Windir Environment Variable"
26references = ["https://www.tiraniddo.dev/2017/05/exploiting-environment-variables-in.html"]
27risk_score = 73
28rule_id = "d563aaba-2e72-462b-8658-3e5ea22db3a6"
29severity = "high"
30tags = [
31 "Domain: Endpoint",
32 "OS: Windows",
33 "Use Case: Threat Detection",
34 "Tactic: Privilege Escalation",
35 "Data Source: Elastic Endgame",
36 "Data Source: Elastic Defend",
37 "Data Source: Sysmon",
38 "Data Source: Microsoft Defender XDR",
39 "Data Source: SentinelOne",
40 "Data Source: Crowdstrike",
41 "Resources: Investigation Guide",
42]
43timestamp_override = "event.ingested"
44type = "eql"
45
46query = '''
47registry where host.os.type == "windows" and event.type == "change" and
48registry.value : ("windir", "systemroot") and registry.data.strings != null and
49registry.path : (
50 "*\\Environment\\windir",
51 "*\\Environment\\systemroot"
52 ) and
53 not registry.data.strings : ("C:\\windows", "%SystemRoot%")
54'''
55
56note = """## Triage and analysis
57
58### Investigating Privilege Escalation via Windir Environment Variable
59
60#### Possible investigation steps
61
62- Does the alert show a Windir or SystemRoot override that can affect this user?
63 - Focus: `registry.path`, `registry.value`, `registry.data.strings`, `host.id`, and `user.id`.
64 - Implication: Escalate when a per-user Environment hive, such as HKEY_USERS SID or HKCU-equivalent context, changes "windir" or "systemroot" away from "C:\\Windows" or "%SystemRoot%"; lower suspicion only when the same host and user recur with the same test or image-engineering value.
65
66- Does the replacement value create a redirection path?
67 - Focus: `registry.data.strings` and `registry.data.type`: user-writable roots, UNC paths, or unexpected command content.
68 - Implication: Escalate when the value can redirect a Windows-root process to attacker-controlled content or command execution; lower suspicion only when the exact replacement is bounded test or image data and no later elevated execution uses it.
69
70- Is the writing process the expected tool in an explainable launch chain?
71 - Focus: `process.executable`, `process.command_line`, `process.code_signature.subject_name`, `process.code_signature.trusted`, and `process.parent.command_line`.
72 - Implication: Escalate when the writer is "reg.exe", a script host, unsigned or user-writable binary, browser or Office child, or renamed tool outside a recognized management chain; reduce suspicion only when signer, path, parent, and arguments match the same test or image-engineering toolchain.
73
74- Does the session and token context make a UAC-bypass path feasible?
75 - Focus: `user.id`, `user.domain`, `process.Ext.session_info.logon_type`, `process.Ext.token.integrity_level_name`, and `process.Ext.token.elevation_level`.
76 - Implication: Escalate when an interactive or remote-admin user changes a per-user value from a medium or limited token and later activity reaches high integrity; lower suspicion when a noninteractive service or repair context cannot exercise an interactive auto-elevated task.
77 - Hint: Recover session and token fields from the writer process by `process.entity_id`; if absent, use the same host plus `process.pid` and a tight time window. $investigate_0
78
79- Did follow-on process execution exercise the override?
80 - Focus: same-host, same-user process starts after the alert, comparing `process.executable`, `process.command_line`, `process.parent.executable`, and `process.Ext.token.integrity_level_name` to the replacement value.
81 - Implication: Escalate when follow-on execution resolves through the substituted path or higher integrity, or when command-line evidence consumes then deletes or restores the value.
82 - Hint: If no follow-on execution appears in the alert window, treat the value as staged and extend only far enough to test later starts reusing the same replacement string. $investigate_1
83
84- If local evidence is suspicious or unresolved, do related alerts change scope?
85 - Focus: related alerts for meaningful `user.id` values, such as real users or named service accounts. For machine, local service, or generic service identities, prioritize same-host alerts.
86 - $investigate_2
87 - $investigate_3
88 - Implication: Broaden response when the same user or host has adjacent privilege-escalation, persistence, defense-evasion, credential-access, or suspicious elevated-process alerts; keep scope local when related alerts are absent and local telemetry supports the same test or image-engineering pattern.
89
90Final - Escalate when the non-default value enables redirection or command execution and writer, session, follow-on, or related-alert evidence is suspicious; close only when the registry value, writer path and parent, session, timeline, and host or user pattern fit the same test or image-engineering workflow; preserve artifacts and escalate when evidence is mixed or visibility is incomplete.
91
92### False positive analysis
93
94- Non-default per-user "windir" or "systemroot" values are unusual on production endpoints. Close as benign only when registry value, writer identity, parent chain, session, host and user pattern, and surrounding process or registry activity converge on one exact test or image-engineering workflow; outside confirmation can corroborate only after telemetry aligns. Recurrence can support missing records but not unresolved current telemetry.
95- Do not close if the replacement value, writer lineage, host or user pattern, or elevated-execution evidence drifts.
96- Before creating an exception, validate the minimum stable pattern: exact `registry.path`, exact or tightly bounded `registry.data.strings`, writer `process.executable`, parent `process.parent.command_line`, `host.id`, and `user.id`. Avoid exceptions on `registry.value`, process names such as "cmd.exe", or `host.id` alone.
97
98### Response and remediation
99
100- If confirmed benign, reverse temporary containment and record the exact evidence that proved the workflow: `registry.path`, `registry.data.strings`, writer `process.executable`, `process.parent.command_line`, `host.id`, and `user.id`. Create an exception only if the same bounded pattern is stable across prior alerts from this rule.
101- If suspicious but unconfirmed, preserve a case export of the alert and registry event, the original and modified Environment values, the writer process tree anchored on `process.entity_id`, command lines, and any substituted-path binaries or scripts recovered from the host before containment or cleanup.
102- Apply reversible containment first: heightened monitoring, temporary task or execution restrictions, or removal of the rogue Environment value after evidence capture if operations permit it. Escalate to host isolation or account containment only when follow-on elevated execution, higher-integrity child processes, or related post-exploitation alerts make active misuse likely and the host role can tolerate stronger action.
103- If confirmed malicious, isolate the endpoint when the registry value, writer lineage, session context, and follow-on execution show unauthorized privilege escalation. Before terminating processes or deleting artifacts, record the writer and follow-on process entity IDs, command lines, parent chain, modified registry path and value, substituted-path artifacts, and privileged process paths.
104- After scope is preserved, restore "windir" or "systemroot" to the expected value, remove substituted-path content or execution triggers identified during triage, and review which privileged processes executed from the substituted path before cleanup.
105- If the override was exercised or related alerts show broader compromise, treat the affected user context as potentially elevated beyond its intended boundary. Scope administrator or remote-access accounts active on the host and perform credential hygiene according to exposure and role.
106- Post-incident hardening: reduce use of environment-variable-expanded paths in auto-elevated tasks where possible, retain process and registry telemetry needed for writer-lineage and follow-on execution review, and record any uncovered variant or visibility gap in the case outcome."""
107
108setup = """## Setup
109
110This 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.
111
112Setup instructions: https://ela.st/install-elastic-defend
113
114### Additional data sources
115
116This rule also supports the following third-party data sources. For setup instructions, refer to the links below:
117
118- [CrowdStrike](https://ela.st/crowdstrike-integration)
119- [Microsoft Defender XDR](https://ela.st/m365-defender)
120- [SentinelOne Cloud Funnel](https://ela.st/sentinel-one-cloud-funnel)
121- [Sysmon Registry Events](https://ela.st/sysmon-event-reg-setup)
122"""
123
124[rule.investigation_fields]
125field_names = [
126 "@timestamp",
127 "host.id",
128 "user.id",
129 "process.executable",
130 "process.command_line",
131 "process.pid",
132 "process.entity_id",
133 "process.parent.command_line",
134 "registry.hive",
135 "registry.path",
136 "registry.value",
137 "registry.data.type",
138 "registry.data.strings",
139]
140
141[transform]
142
143[[transform.investigate]]
144label = "Writer process event"
145description = ""
146providers = [
147 [
148 { excluded = false, field = "event.category", queryType = "phrase", value = "process", valueType = "string" },
149 { excluded = false, field = "host.id", queryType = "phrase", value = "{{host.id}}", valueType = "string" },
150 { excluded = false, field = "process.entity_id", queryType = "phrase", value = "{{process.entity_id}}", valueType = "string" }
151 ],
152 [
153 { excluded = false, field = "event.category", queryType = "phrase", value = "process", valueType = "string" },
154 { excluded = false, field = "host.id", queryType = "phrase", value = "{{host.id}}", valueType = "string" },
155 { excluded = false, field = "process.pid", queryType = "phrase", value = "{{process.pid}}", valueType = "string" }
156 ]
157]
158relativeFrom = "now-1h"
159relativeTo = "now"
160
161[[transform.investigate]]
162label = "Process events for the same user and host"
163description = ""
164providers = [
165 [
166 { excluded = false, field = "event.category", queryType = "phrase", value = "process", valueType = "string" },
167 { excluded = false, field = "host.id", queryType = "phrase", value = "{{host.id}}", valueType = "string" },
168 { excluded = false, field = "user.id", queryType = "phrase", value = "{{user.id}}", valueType = "string" }
169 ]
170]
171relativeFrom = "now-1h"
172relativeTo = "now"
173
174[[transform.investigate]]
175label = "Alerts associated with the user"
176description = ""
177providers = [
178 [
179 { excluded = false, field = "event.kind", queryType = "phrase", value = "signal", valueType = "string" },
180 { excluded = false, field = "user.id", queryType = "phrase", value = "{{user.id}}", valueType = "string" }
181 ]
182]
183relativeFrom = "now-48h/h"
184relativeTo = "now"
185
186[[transform.investigate]]
187label = "Alerts associated with the host"
188description = ""
189providers = [
190 [
191 { excluded = false, field = "event.kind", queryType = "phrase", value = "signal", valueType = "string" },
192 { excluded = false, field = "host.id", queryType = "phrase", value = "{{host.id}}", valueType = "string" }
193 ]
194]
195relativeFrom = "now-48h/h"
196relativeTo = "now"
197
198[[rule.threat]]
199framework = "MITRE ATT&CK"
200
201[[rule.threat.technique]]
202id = "T1574"
203name = "Hijack Execution Flow"
204reference = "https://attack.mitre.org/techniques/T1574/"
205
206[[rule.threat.technique.subtechnique]]
207id = "T1574.007"
208name = "Path Interception by PATH Environment Variable"
209reference = "https://attack.mitre.org/techniques/T1574/007/"
210
211[rule.threat.tactic]
212id = "TA0004"
213name = "Privilege Escalation"
214reference = "https://attack.mitre.org/tactics/TA0004/"
215
216[[rule.threat]]
217framework = "MITRE ATT&CK"
218
219[[rule.threat.technique]]
220id = "T1112"
221name = "Modify Registry"
222reference = "https://attack.mitre.org/techniques/T1112/"
223
224[rule.threat.tactic]
225id = "TA0005"
226name = "Defense Evasion"
227reference = "https://attack.mitre.org/tactics/TA0005/"
Triage and analysis
Investigating Privilege Escalation via Windir Environment Variable
Possible investigation steps
-
Does the alert show a Windir or SystemRoot override that can affect this user?
- Focus:
registry.path,registry.value,registry.data.strings,host.id, anduser.id. - Implication: Escalate when a per-user Environment hive, such as HKEY_USERS SID or HKCU-equivalent context, changes "windir" or "systemroot" away from "C:\Windows" or "%SystemRoot%"; lower suspicion only when the same host and user recur with the same test or image-engineering value.
- Focus:
-
Does the replacement value create a redirection path?
- Focus:
registry.data.stringsandregistry.data.type: user-writable roots, UNC paths, or unexpected command content. - Implication: Escalate when the value can redirect a Windows-root process to attacker-controlled content or command execution; lower suspicion only when the exact replacement is bounded test or image data and no later elevated execution uses it.
- Focus:
-
Is the writing process the expected tool in an explainable launch chain?
- Focus:
process.executable,process.command_line,process.code_signature.subject_name,process.code_signature.trusted, andprocess.parent.command_line. - Implication: Escalate when the writer is "reg.exe", a script host, unsigned or user-writable binary, browser or Office child, or renamed tool outside a recognized management chain; reduce suspicion only when signer, path, parent, and arguments match the same test or image-engineering toolchain.
- Focus:
-
Does the session and token context make a UAC-bypass path feasible?
- Focus:
user.id,user.domain,process.Ext.session_info.logon_type,process.Ext.token.integrity_level_name, andprocess.Ext.token.elevation_level. - Implication: Escalate when an interactive or remote-admin user changes a per-user value from a medium or limited token and later activity reaches high integrity; lower suspicion when a noninteractive service or repair context cannot exercise an interactive auto-elevated task.
- Hint: Recover session and token fields from the writer process by
process.entity_id; if absent, use the same host plusprocess.pidand a tight time window. $investigate_0
- Focus:
-
Did follow-on process execution exercise the override?
- Focus: same-host, same-user process starts after the alert, comparing
process.executable,process.command_line,process.parent.executable, andprocess.Ext.token.integrity_level_nameto the replacement value. - Implication: Escalate when follow-on execution resolves through the substituted path or higher integrity, or when command-line evidence consumes then deletes or restores the value.
- Hint: If no follow-on execution appears in the alert window, treat the value as staged and extend only far enough to test later starts reusing the same replacement string. $investigate_1
- Focus: same-host, same-user process starts after the alert, comparing
-
If local evidence is suspicious or unresolved, do related alerts change scope?
- Focus: related alerts for meaningful
user.idvalues, such as real users or named service accounts. For machine, local service, or generic service identities, prioritize same-host alerts.- $investigate_2
- $investigate_3
- Implication: Broaden response when the same user or host has adjacent privilege-escalation, persistence, defense-evasion, credential-access, or suspicious elevated-process alerts; keep scope local when related alerts are absent and local telemetry supports the same test or image-engineering pattern.
- Focus: related alerts for meaningful
Final - Escalate when the non-default value enables redirection or command execution and writer, session, follow-on, or related-alert evidence is suspicious; close only when the registry value, writer path and parent, session, timeline, and host or user pattern fit the same test or image-engineering workflow; preserve artifacts and escalate when evidence is mixed or visibility is incomplete.
False positive analysis
- Non-default per-user "windir" or "systemroot" values are unusual on production endpoints. Close as benign only when registry value, writer identity, parent chain, session, host and user pattern, and surrounding process or registry activity converge on one exact test or image-engineering workflow; outside confirmation can corroborate only after telemetry aligns. Recurrence can support missing records but not unresolved current telemetry.
- Do not close if the replacement value, writer lineage, host or user pattern, or elevated-execution evidence drifts.
- Before creating an exception, validate the minimum stable pattern: exact
registry.path, exact or tightly boundedregistry.data.strings, writerprocess.executable, parentprocess.parent.command_line,host.id, anduser.id. Avoid exceptions onregistry.value, process names such as "cmd.exe", orhost.idalone.
Response and remediation
- If confirmed benign, reverse temporary containment and record the exact evidence that proved the workflow:
registry.path,registry.data.strings, writerprocess.executable,process.parent.command_line,host.id, anduser.id. Create an exception only if the same bounded pattern is stable across prior alerts from this rule. - If suspicious but unconfirmed, preserve a case export of the alert and registry event, the original and modified Environment values, the writer process tree anchored on
process.entity_id, command lines, and any substituted-path binaries or scripts recovered from the host before containment or cleanup. - Apply reversible containment first: heightened monitoring, temporary task or execution restrictions, or removal of the rogue Environment value after evidence capture if operations permit it. Escalate to host isolation or account containment only when follow-on elevated execution, higher-integrity child processes, or related post-exploitation alerts make active misuse likely and the host role can tolerate stronger action.
- If confirmed malicious, isolate the endpoint when the registry value, writer lineage, session context, and follow-on execution show unauthorized privilege escalation. Before terminating processes or deleting artifacts, record the writer and follow-on process entity IDs, command lines, parent chain, modified registry path and value, substituted-path artifacts, and privileged process paths.
- After scope is preserved, restore "windir" or "systemroot" to the expected value, remove substituted-path content or execution triggers identified during triage, and review which privileged processes executed from the substituted path before cleanup.
- If the override was exercised or related alerts show broader compromise, treat the affected user context as potentially elevated beyond its intended boundary. Scope administrator or remote-access accounts active on the host and perform credential hygiene according to exposure and role.
- Post-incident hardening: reduce use of environment-variable-expanded paths in auto-elevated tasks where possible, retain process and registry telemetry needed for writer-lineage and follow-on execution review, and record any uncovered variant or visibility gap in the case outcome.
References
Related rules
- Bypass UAC via Event Viewer
- Privilege Escalation via Named Pipe Impersonation
- UAC Bypass Attempt via Windows Directory Masquerading
- Potential privilege escalation via CVE-2022-38028
- Disabling User Account Control via Registry Modification