Potential Remote Desktop Shadowing Activity
Identifies the modification of the Remote Desktop Protocol (RDP) Shadow registry or the execution of processes indicative of an active RDP shadowing session. An adversary may abuse the RDP Shadowing feature to spy on or control other users active RDP sessions.
Elastic rule (View on GitHub)
1[metadata]
2creation_date = "2021/04/12"
3integration = ["endpoint", "windows", "m365_defender", "sentinel_one_cloud_funnel"]
4maturity = "production"
5updated_date = "2026/09/18"
6
7[rule]
8author = ["Elastic"]
9description = """
10Identifies the modification of the Remote Desktop Protocol (RDP) Shadow registry or the execution of processes
11indicative of an active RDP shadowing session. An adversary may abuse the RDP Shadowing feature to spy on or control
12other users active RDP sessions.
13"""
14from = "now-9m"
15index = [
16 "logs-endpoint.events.process-*",
17 "logs-endpoint.events.registry-*",
18 "winlogbeat-*",
19 "logs-windows.sysmon_operational-*",
20 "endgame-*",
21 "logs-m365_defender.event-*",
22 "logs-sentinel_one_cloud_funnel.*",
23]
24language = "eql"
25license = "Elastic License v2"
26name = "Potential Remote Desktop Shadowing Activity"
27references = [
28 "https://blog.bitsadmin.com/spying-on-users-using-rdp-shadowing",
29 "https://swarm.ptsecurity.com/remote-desktop-services-shadowing/",
30]
31risk_score = 73
32rule_id = "c57f8579-e2a5-4804-847f-f2732edc5156"
33severity = "high"
34tags = [
35 "Domain: Endpoint",
36 "OS: Windows",
37 "Use Case: Threat Detection",
38 "Tactic: Lateral Movement",
39 "Data Source: Elastic Endgame",
40 "Data Source: Elastic Defend",
41 "Data Source: Sysmon",
42 "Data Source: Microsoft Defender XDR",
43 "Data Source: SentinelOne",
44 "Resources: Investigation Guide",
45 "Noise: Medium",
46 "Performance: Normal",
47 "Rule Type: Event Correlation (EQL)",
48 "Platform: Windows",
49]
50timestamp_override = "event.ingested"
51type = "eql"
52
53query = '''
54/* Identifies the modification of RDP Shadow registry or
55 the execution of processes indicative of active shadow RDP session */
56
57any where host.os.type == "windows" and
58(
59 (event.category == "registry" and event.type == "change" and
60 registry.value : "Shadow" and
61 registry.path : (
62 "*\\Software\\Policies\\Microsoft\\Windows NT\\Terminal Services\\Shadow"
63 ) and
64 registry.data.strings : ("1", "0x00000001", "2", "0x00000002", "3", "0x00000003", "4", "0x00000004")
65
66 ) or
67 (event.category == "process" and event.type == "start" and
68 (
69 (process.name : ("RdpSaUacHelper.exe", "RdpSaProxy.exe") and process.parent.name : "svchost.exe") or
70 (?process.pe.original_file_name : "mstsc.exe" and process.args : "/shadow:*")
71 )
72 )
73)
74'''
75
76note = """## Triage and analysis
77
78### Investigating Potential Remote Desktop Shadowing Activity
79
80#### Possible investigation steps
81
82- Which RDP shadowing path fired?
83 - Focus: `event.category`, `process.name`, `process.command_line`, `registry.path`, `registry.data.strings`.
84 - Implication: escalate faster for active "mstsc.exe /shadow" use or a `Shadow` policy value that removes consent; lower suspicion only when alert-local evidence matches recognized helpdesk, training, or policy-setting activity with consent retained.
85- Do process identity and lineage fit RDP shadowing components?
86 - Focus: `process.executable`, `process.pe.original_file_name`, `process.code_signature.subject_name`, `process.code_signature.trusted`, `process.parent.command_line`.
87 - Hint: for registry alerts, recover same-process starts for lineage or command-line detail. $investigate_0
88 - Implication: escalate when "mstsc.exe", "RdpSaUacHelper.exe", or "RdpSaProxy.exe" runs from a user-writable path, has an unexpected signer, or has a parent inconsistent with Remote Desktop Services or a support launcher. A trusted Microsoft binary confirms identity, not authorization.
89- If the `Shadow` registry value fired, did the new setting remove consent or allow control?
90 - Focus: `registry.path`, `registry.data.strings` (decimal or hex: `1`/`0x00000001` = full control with consent, `2`/`0x00000002` = full control without consent, `3`/`0x00000003` = view only with consent, `4`/`0x00000004` = view only without consent), and `process.executable`.
91 - Implication: escalate when `registry.data.strings` is `2`/`0x00000002` (full control, no consent) or `4`/`0x00000004` (view, no consent) because these allow silent shadowing; treat `1`/`0x00000001` or `3`/`0x00000003` as weaker setup evidence because the user is prompted, unless active shadowing or unexplained lineage appears.
92- If a process event fired, does it show active session shadowing?
93 - Focus: `process.name`, `process.command_line`, `process.parent.name`, `process.parent.executable`.
94 - Hint: if `process.command_line` is truncated or normalized, verify "/shadow", "/control", and "/noConsentPrompt" boundaries with `process.args` before lowering suspicion.
95 - Implication: escalate when "mstsc.exe" includes "/shadow" with "/control" or "/noConsentPrompt". Treat "RdpSaUacHelper.exe" or "RdpSaProxy.exe" under a service host as active target-side shadowing that escalates when paired with no-consent/control, unexplained lineage, or unrecognized user-host context; a plain "mstsc.exe" launch without shadowing arguments is not enough.
96- Does user, host, and session context fit recognized support or training?
97 - Focus: `user.id`, `user.name`, `user.domain`, `host.id`, `process.Ext.session_info.logon_type`.
98 - Implication: escalate when `user.id` targets an unusual workstation, privileged session, or host with no matching shadow-support pattern; lower suspicion only when user-host pairing, session type, and branch evidence match the same recognized workflow.
99- Did the same actor prepare, persist, or extend the host-side shadowing activity?
100 - Focus: `user.id`, `process.entity_id`, `process.command_line`, `registry.path`, `registry.data.strings`.
101 - Hint: start with recovered same-process events; expand to same-host process and registry events only when local capability or context remains suspicious. $investigate_1
102 - Implication: escalate when the same user or lineage enumerates sessions, prepares alternate-token launch, changes Terminal Services or RDP state, launches admin tooling, or persists shadow settings; absent process or registry evidence narrows the case but does not clear the alert.
103- If local findings stay suspicious or unresolved, do related alerts expand scope?
104 - Focus: related alerts for the same `user.id` and `host.id`, especially remote-access, credential, remote-service, and persistence alerts.
105 - Hint: review same-user alerts when local branch and capability questions remain suspicious. $investigate_2
106 - Hint: review same-host alerts when host preparation or follow-on activity remains unresolved. $investigate_3
107 - Implication: broaden scope when related alerts show the same user or host in remote-access, credential, or persistence activity; keep scope narrow only when local evidence fits a recognized workflow and related alerts do not contradict it.
108
109- Using branch, capability, identity, lineage, user-host fit, host-side activity, and related alerts, escalate unauthorized no-consent/control shadowing or stealthy policy relaxation; close only when evidence binds to one recognized support, training, or policy workflow with no contradictions; if mixed or incomplete, preserve process and registry artifacts and escalate.
110
111### False positive analysis
112
113- Helpdesk support, training labs, and supervised administration can legitimately use "mstsc.exe /shadow" or target-side "RdpSa*" helpers. Confirm `process.command_line`, `process.name`, `process.parent.name`, `user.id`, `host.id`, and any `Shadow` value align with the same authorized workflow, without contradictory `process.command_line` or `registry.path` evidence. Without ticketing or support rosters, require telemetry-only recurrence of the same command pattern, user-host pairing, consent mode, and quiet follow-on profile before closing as benign.
114- Group Policy or endpoint management tooling can legitimately change `Shadow`. Confirm stable `process.executable`, `process.code_signature.subject_name`, `process.parent.command_line`, exact `registry.path`, and resulting `registry.data.strings` match the host class. Without change records or GPO inventories, require quiet recurrence of the same process and registry pattern for the same management scope before closing.
115- Before creating an exception, anchor it on the minimum confirmed workflow: `event.category`, exact `process.command_line` or `registry.path`, `registry.data.strings`, `user.id`, and `host.id`. Avoid exceptions on `process.name`, `registry.value`, or `Shadow` alone.
116
117### Response and remediation
118
119- If confirmed benign, reverse temporary containment and document the exact `event.category`, `process.command_line` or `registry.path`, `registry.data.strings`, `user.id`, and `host.id` that proved the support, training, or policy workflow. Create an exception only after the same narrow pattern recurs.
120- If suspicious but unconfirmed, preserve a case export with the process tree, `process.entity_id`, `process.command_line`, `process.parent.command_line`, `registry.path`, `registry.value`, `registry.data.strings`, affected `user.id`, affected `host.id`, and surrounding preparation or follow-on evidence before changing host state.
121- Apply reversible containment next: restore the `Shadow` policy to the pre-change value, disable shadowing with `0`, require consent with `1` or `3`, or restrict the involved account on the affected `host.id`. Escalate to host isolation only when shadowing is part of broader session abuse and the host role can tolerate isolation.
122- If confirmed malicious, isolate the host when feasible, then terminate active "mstsc.exe" or "RdpSa*" shadowing processes after recording their process identifiers and command lines. Revert unauthorized `Shadow` and related Terminal Services or RDP shadow permission changes after preservation.
123- Scope other hosts and users tied to the same `user.id`, `process.command_line`, `registry.path`, or `registry.data.strings` before removing artifacts or resetting access.
124- Remove malicious helper scripts or tooling found during scoping, revert unauthorized RDP service or policy changes, and reset credentials that may have been exposed in the shadowed session.
125- Post-incident hardening: keep `Shadow` at the least permissive accepted setting, restrict who can shadow sessions, review RDP-Tcp shadow permissions, and retain process and registry telemetry needed to distinguish support use from no-consent shadowing."""
126
127setup = """## Setup
128
129This 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.
130
131Setup instructions: https://ela.st/install-elastic-defend
132
133### Additional data sources
134
135This rule also supports the following third-party data sources. For setup instructions, refer to the links below:
136
137- [Microsoft Defender XDR](https://ela.st/m365-defender)
138- [SentinelOne Cloud Funnel](https://ela.st/sentinel-one-cloud-funnel)
139- [Sysmon Event ID 1 - Process Creation](https://ela.st/sysmon-event-1-setup)
140- [Sysmon Registry Events](https://ela.st/sysmon-event-reg-setup)
141"""
142
143[rule.investigation_fields]
144field_names = [
145 "@timestamp",
146 "event.category",
147 "host.id",
148 "user.id",
149 "process.entity_id",
150 "process.pid",
151 "process.executable",
152 "process.command_line",
153 "process.args",
154 "process.parent.name",
155 "process.pe.original_file_name",
156 "process.code_signature.trusted",
157 "registry.path",
158 "registry.value",
159 "registry.data.strings",
160]
161
162[transform]
163
164[[transform.investigate]]
165label = "Process events for the same process"
166description = ""
167providers = [
168 [
169 { excluded = false, field = "event.category", queryType = "phrase", value = "process", valueType = "string" },
170 { excluded = false, field = "host.id", queryType = "phrase", value = "{{host.id}}", valueType = "string" },
171 { excluded = false, field = "process.entity_id", queryType = "phrase", value = "{{process.entity_id}}", valueType = "string" }
172 ],
173 [
174 { excluded = false, field = "event.category", queryType = "phrase", value = "process", valueType = "string" },
175 { excluded = false, field = "host.id", queryType = "phrase", value = "{{host.id}}", valueType = "string" },
176 { excluded = false, field = "process.pid", queryType = "phrase", value = "{{process.pid}}", valueType = "string" }
177 ]
178]
179relativeFrom = "now-1h"
180relativeTo = "now"
181
182[[transform.investigate]]
183label = "Registry events on the host near the alert"
184description = ""
185providers = [
186 [
187 { excluded = false, field = "event.category", queryType = "phrase", value = "registry", valueType = "string" },
188 { excluded = false, field = "host.id", queryType = "phrase", value = "{{host.id}}", valueType = "string" }
189 ]
190]
191relativeFrom = "now-1h"
192relativeTo = "now"
193
194[[transform.investigate]]
195label = "Alerts associated with the user"
196description = ""
197providers = [
198 [
199 { excluded = false, field = "event.kind", queryType = "phrase", value = "signal", valueType = "string" },
200 { excluded = false, field = "user.id", queryType = "phrase", value = "{{user.id}}", valueType = "string" }
201 ]
202]
203relativeFrom = "now-48h/h"
204relativeTo = "now"
205
206[[transform.investigate]]
207label = "Alerts associated with the host"
208description = ""
209providers = [
210 [
211 { excluded = false, field = "event.kind", queryType = "phrase", value = "signal", valueType = "string" },
212 { excluded = false, field = "host.id", queryType = "phrase", value = "{{host.id}}", valueType = "string" }
213 ]
214]
215relativeFrom = "now-48h/h"
216relativeTo = "now"
217
218[[rule.threat]]
219framework = "MITRE ATT&CK"
220
221[[rule.threat.technique]]
222id = "T1021"
223name = "Remote Services"
224reference = "https://attack.mitre.org/techniques/T1021/"
225
226[[rule.threat.technique.subtechnique]]
227id = "T1021.001"
228name = "Remote Desktop Protocol"
229reference = "https://attack.mitre.org/techniques/T1021/001/"
230
231[[rule.threat.technique]]
232id = "T1563"
233name = "Remote Service Session Hijacking"
234reference = "https://attack.mitre.org/techniques/T1563/"
235
236[[rule.threat.technique.subtechnique]]
237id = "T1563.002"
238name = "RDP Hijacking"
239reference = "https://attack.mitre.org/techniques/T1563/002/"
240
241[rule.threat.tactic]
242id = "TA0008"
243name = "Lateral Movement"
244reference = "https://attack.mitre.org/tactics/TA0008/"
245
246[[rule.threat]]
247framework = "MITRE ATT&CK"
248
249[[rule.threat.technique]]
250id = "T1113"
251name = "Screen Capture"
252reference = "https://attack.mitre.org/techniques/T1113/"
253
254[rule.threat.tactic]
255id = "TA0009"
256name = "Collection"
257reference = "https://attack.mitre.org/tactics/TA0009/"
Triage and analysis
Investigating Potential Remote Desktop Shadowing Activity
Possible investigation steps
-
Which RDP shadowing path fired?
- Focus:
event.category,process.name,process.command_line,registry.path,registry.data.strings. - Implication: escalate faster for active "mstsc.exe /shadow" use or a
Shadowpolicy value that removes consent; lower suspicion only when alert-local evidence matches recognized helpdesk, training, or policy-setting activity with consent retained.
- Focus:
-
Do process identity and lineage fit RDP shadowing components?
- Focus:
process.executable,process.pe.original_file_name,process.code_signature.subject_name,process.code_signature.trusted,process.parent.command_line. - Hint: for registry alerts, recover same-process starts for lineage or command-line detail. $investigate_0
- Implication: escalate when "mstsc.exe", "RdpSaUacHelper.exe", or "RdpSaProxy.exe" runs from a user-writable path, has an unexpected signer, or has a parent inconsistent with Remote Desktop Services or a support launcher. A trusted Microsoft binary confirms identity, not authorization.
- Focus:
-
If the
Shadowregistry value fired, did the new setting remove consent or allow control?- Focus:
registry.path,registry.data.strings(decimal or hex:1/0x00000001= full control with consent,2/0x00000002= full control without consent,3/0x00000003= view only with consent,4/0x00000004= view only without consent), andprocess.executable. - Implication: escalate when
registry.data.stringsis2/0x00000002(full control, no consent) or4/0x00000004(view, no consent) because these allow silent shadowing; treat1/0x00000001or3/0x00000003as weaker setup evidence because the user is prompted, unless active shadowing or unexplained lineage appears.
- Focus:
-
If a process event fired, does it show active session shadowing?
- Focus:
process.name,process.command_line,process.parent.name,process.parent.executable. - Hint: if
process.command_lineis truncated or normalized, verify "/shadow", "/control", and "/noConsentPrompt" boundaries withprocess.argsbefore lowering suspicion. - Implication: escalate when "mstsc.exe" includes "/shadow" with "/control" or "/noConsentPrompt". Treat "RdpSaUacHelper.exe" or "RdpSaProxy.exe" under a service host as active target-side shadowing that escalates when paired with no-consent/control, unexplained lineage, or unrecognized user-host context; a plain "mstsc.exe" launch without shadowing arguments is not enough.
- Focus:
-
Does user, host, and session context fit recognized support or training?
- Focus:
user.id,user.name,user.domain,host.id,process.Ext.session_info.logon_type. - Implication: escalate when
user.idtargets an unusual workstation, privileged session, or host with no matching shadow-support pattern; lower suspicion only when user-host pairing, session type, and branch evidence match the same recognized workflow.
- Focus:
-
Did the same actor prepare, persist, or extend the host-side shadowing activity?
- Focus:
user.id,process.entity_id,process.command_line,registry.path,registry.data.strings. - Hint: start with recovered same-process events; expand to same-host process and registry events only when local capability or context remains suspicious. $investigate_1
- Implication: escalate when the same user or lineage enumerates sessions, prepares alternate-token launch, changes Terminal Services or RDP state, launches admin tooling, or persists shadow settings; absent process or registry evidence narrows the case but does not clear the alert.
- Focus:
-
If local findings stay suspicious or unresolved, do related alerts expand scope?
- Focus: related alerts for the same
user.idandhost.id, especially remote-access, credential, remote-service, and persistence alerts. - Hint: review same-user alerts when local branch and capability questions remain suspicious. $investigate_2
- Hint: review same-host alerts when host preparation or follow-on activity remains unresolved. $investigate_3
- Implication: broaden scope when related alerts show the same user or host in remote-access, credential, or persistence activity; keep scope narrow only when local evidence fits a recognized workflow and related alerts do not contradict it.
- Focus: related alerts for the same
-
Using branch, capability, identity, lineage, user-host fit, host-side activity, and related alerts, escalate unauthorized no-consent/control shadowing or stealthy policy relaxation; close only when evidence binds to one recognized support, training, or policy workflow with no contradictions; if mixed or incomplete, preserve process and registry artifacts and escalate.
False positive analysis
- Helpdesk support, training labs, and supervised administration can legitimately use "mstsc.exe /shadow" or target-side "RdpSa*" helpers. Confirm
process.command_line,process.name,process.parent.name,user.id,host.id, and anyShadowvalue align with the same authorized workflow, without contradictoryprocess.command_lineorregistry.pathevidence. Without ticketing or support rosters, require telemetry-only recurrence of the same command pattern, user-host pairing, consent mode, and quiet follow-on profile before closing as benign. - Group Policy or endpoint management tooling can legitimately change
Shadow. Confirm stableprocess.executable,process.code_signature.subject_name,process.parent.command_line, exactregistry.path, and resultingregistry.data.stringsmatch the host class. Without change records or GPO inventories, require quiet recurrence of the same process and registry pattern for the same management scope before closing. - Before creating an exception, anchor it on the minimum confirmed workflow:
event.category, exactprocess.command_lineorregistry.path,registry.data.strings,user.id, andhost.id. Avoid exceptions onprocess.name,registry.value, orShadowalone.
Response and remediation
- If confirmed benign, reverse temporary containment and document the exact
event.category,process.command_lineorregistry.path,registry.data.strings,user.id, andhost.idthat proved the support, training, or policy workflow. Create an exception only after the same narrow pattern recurs. - If suspicious but unconfirmed, preserve a case export with the process tree,
process.entity_id,process.command_line,process.parent.command_line,registry.path,registry.value,registry.data.strings, affecteduser.id, affectedhost.id, and surrounding preparation or follow-on evidence before changing host state. - Apply reversible containment next: restore the
Shadowpolicy to the pre-change value, disable shadowing with0, require consent with1or3, or restrict the involved account on the affectedhost.id. Escalate to host isolation only when shadowing is part of broader session abuse and the host role can tolerate isolation. - If confirmed malicious, isolate the host when feasible, then terminate active "mstsc.exe" or "RdpSa*" shadowing processes after recording their process identifiers and command lines. Revert unauthorized
Shadowand related Terminal Services or RDP shadow permission changes after preservation. - Scope other hosts and users tied to the same
user.id,process.command_line,registry.path, orregistry.data.stringsbefore removing artifacts or resetting access. - Remove malicious helper scripts or tooling found during scoping, revert unauthorized RDP service or policy changes, and reset credentials that may have been exposed in the shadowed session.
- Post-incident hardening: keep
Shadowat the least permissive accepted setting, restrict who can shadow sessions, review RDP-Tcp shadow permissions, and retain process and registry telemetry needed to distinguish support use from no-consent shadowing.
References
Related rules
- Lateral Movement via Startup Folder
- Local Account TokenFilter Policy Disabled
- Microsoft Exchange Server UM Spawning Suspicious Processes
- Mounting Hidden or WebDav Remote Shares
- Potential Remote Desktop Tunneling Detected