Why RDP Lateral Movement Is Still a Core Detection Problem
Remote Desktop Protocol has been around since Windows NT 4.0. It’s also the lateral movement technique defenders encounter most often in ransomware intrusions, nation-state operations, and red team engagements. MITRE ATT&CK catalogs it as T1021.001 and for good reason: RDP is built into every Windows installation, it provides full interactive GUI access, it blends with legitimate admin traffic on most enterprise networks, and it’s almost never completely disabled.
The challenge for detection engineers isn’t identifying that RDP exists — it’s distinguishing malicious lateral movement from the hundreds of legitimate helpdesk, IT admin, and remote work connections that fire every day. This guide focuses on the telemetry that separates those cases and the rules that catch the malicious ones.
How Attackers Use RDP for Lateral Movement
Standard RDP lateral movement means an attacker with valid credentials on a compromised host opens an RDP session to another host in the network — typically moving from a workstation or DMZ server toward domain controllers, file servers, or backup infrastructure.
Several techniques augment basic credential use:
Restricted Admin Mode (Pass-the-Hash RDP): Windows supports an RDP mode where the session authenticates using NTLM hash rather than a password. An attacker who has dumped hashes but not cracked them can use mstsc.exe /restrictedAdmin to authenticate. This is effective against unpatched systems or systems where Credential Guard isn’t enforced. The key characteristic: logon type 10 without network credentials being forwarded to the remote host.
RDP over Port Forwarding: Attackers who can’t reach a target directly often tunnel RDP through an existing compromised host using tools like Chisel, Ligolo-ng, or native SSH port forwarding. The RDP traffic itself is identical — what changes is the routing path.
SharpRDP and FreeRDP: Tooling like SharpRDP executes commands on remote hosts via the MSRDP ActiveX control without spawning a visible desktop, making it useful for non-interactive remote execution under the radar of endpoint tools that flag mstsc.exe.
Key Telemetry Sources
Windows Security Event Log
These event IDs are the foundation of RDP detection:
Event ID 4624 — Logon Success
- Logon Type 10 = RemoteInteractive (RDP with session creation)
- Logon Type 3 = Network (RDP reconnect or NLA pre-authentication)
- Pay attention to: source IP (
IpAddressfield), account name, and workstation name
Event ID 4625 — Logon Failure
- Repeated failures from unexpected source IPs suggest credential spraying over RDP
- Logon Type 10 failures are particularly interesting
Event ID 4648 — Explicit Credential Logon
- Fires when
runasor an application explicitly supplies credentials - Relevant when an attacker uses a different account to initiate the RDP session
Event ID 4778 / 4779 — Session Connect / Disconnect
- Tracks RDP session lifecycle on the target host
- Useful for reconstructing attacker dwell time
Sysmon
Event ID 1 (Process Create): mstsc.exe spawning from unusual parent processes (e.g., cmd.exe, powershell.exe, a web shell process) is a strong signal. Legitimate use: explorer.exe, Citrix receiver processes.
Event ID 3 (Network Connection): Outbound connections on port 3389 from non-management hosts. Any workstation initiating RDP to another workstation is suspicious in most enterprise environments.
Windows System Event Log
Event ID 21, 24, 25 (TerminalServices-LocalSessionManager): Session logon, disconnect, and reconnect events. These fire on the target host and are useful for correlating with Security log events.
Sigma Rules
Outbound RDP from Non-Admin Hosts
title: Outbound RDP Connection from Workstation
id: a4b1c2d3-e4f5-6789-abcd-ef0123456789
status: experimental
description: Detects RDP connections initiated from workstation-class hosts, which is unusual in most environments
author: SOC Analyst Hub
date: 2026/07/07
logsource:
product: windows
category: network_connection
detection:
selection:
EventID: 3
DestinationPort: 3389
Initiated: 'true'
filter_servers:
Image|contains:
- '\mstsc.exe'
condition: selection and not filter_servers
filter_admin:
SourceHostname|contains:
- 'JUMP'
- 'MGMT'
- 'ADMIN'
condition: selection and not (filter_admin)
falsepositives:
- Jump server management tools
- Legitimate admin RDP workflows
level: medium
tags:
- attack.lateral_movement
- attack.t1021.001
RDP Login from New Source IP
title: RDP Logon from Unusual Source
id: b5c2d3e4-f5a6-789b-cdef-012345678901
status: experimental
description: Detects successful RDP logons (type 10) from source IPs with no prior authentication history
author: SOC Analyst Hub
date: 2026/07/07
logsource:
product: windows
service: security
detection:
selection:
EventID: 4624
LogonType: 10
filter_local:
IpAddress:
- '127.0.0.1'
- '-'
- '::1'
condition: selection and not filter_local
falsepositives:
- New admin workstations
- VPN IP pool changes
level: medium
tags:
- attack.lateral_movement
- attack.t1021.001
Restricted Admin RDP (Pass-the-Hash via RDP)
title: RDP Restricted Admin Mode Usage
id: c6d3e4f5-a6b7-890c-def0-123456789012
status: experimental
description: Detects use of RDP Restricted Admin mode, which allows pass-the-hash authentication
author: SOC Analyst Hub
date: 2026/07/07
logsource:
product: windows
service: security
detection:
selection:
EventID: 4624
LogonType: 10
LogonProcessName: 'NtLmSsp'
AuthenticationPackageName: 'NTLM'
filter_legitimate:
SubjectUserName|endswith: '$'
condition: selection and not filter_legitimate
falsepositives:
- Older systems where NLA is not enforced
level: high
tags:
- attack.lateral_movement
- attack.t1021.001
- attack.credential_access
- attack.t1550.002
Anomalous mstsc.exe Parent Process
title: mstsc.exe Spawned from Suspicious Parent
id: d7e4f5a6-b7c8-901d-ef01-234567890123
status: experimental
description: Detects mstsc.exe launched from unusual parent processes indicating potential attacker-initiated RDP
author: SOC Analyst Hub
date: 2026/07/07
logsource:
product: windows
category: process_creation
detection:
selection:
Image|endswith: '\mstsc.exe'
filter_normal:
ParentImage|endswith:
- '\explorer.exe'
- '\taskmgr.exe'
- '\ctfmon.exe'
condition: selection and not filter_normal
falsepositives:
- Automation frameworks
- IT management tooling
level: medium
tags:
- attack.lateral_movement
- attack.t1021.001
KQL Detection Rules (Microsoft Sentinel)
Successful RDP Logon Outside Business Hours
SecurityEvent
| where EventID == 4624
| where LogonType == 10
| where TimeGenerated between (todatetime("00:00") .. todatetime("06:00"))
or TimeGenerated between (todatetime("20:00") .. todatetime("23:59"))
| where IpAddress !in ("127.0.0.1", "-", "::1")
| where AccountType == "User"
| project TimeGenerated, Account, IpAddress, WorkstationName, Computer
| order by TimeGenerated desc
RDP Lateral Movement Chain (Multiple Hops)
let rdp_logons = SecurityEvent
| where EventID == 4624 and LogonType == 10
| where IpAddress !in ("127.0.0.1", "-", "::1")
| project LogonTime=TimeGenerated, TargetHost=Computer,
SourceIP=IpAddress, Account=Account;
// Find hosts that appeared as both source and target within a sliding window
rdp_logons
| join kind=inner (rdp_logons) on $left.TargetHost == $right.SourceIP
| where $right.LogonTime > LogonTime and $right.LogonTime < LogonTime + 2h
| project FirstHop=TargetHost, SecondHop=$right.TargetHost, Account,
FirstLogon=LogonTime, SecondLogon=$right.LogonTime
| order by FirstLogon desc
RDP Brute Force Detection
SecurityEvent
| where EventID == 4625 and LogonType == 10
| where TimeGenerated > ago(1h)
| summarize FailureCount = count(), Accounts = make_set(TargetUserName)
by IpAddress, bin(TimeGenerated, 5m)
| where FailureCount > 10
| order by FailureCount desc
High-Value Target RDP Access
let high_value = datatable(Host:string) ["DC01", "DC02", "BACKUP01", "FILESERVER01"];
SecurityEvent
| where EventID == 4624 and LogonType == 10
| where Computer has_any (high_value)
| where IpAddress !in ("10.0.1.5", "10.0.1.6") // Adjust for your jump server IPs
| project TimeGenerated, Account, IpAddress, Computer
| order by TimeGenerated desc
Baseline and Tuning Guidance
These rules will generate significant false positives without baselining:
Jump servers: Build an allowlist of your legitimate RDP management hosts. Any detection rule that doesn’t filter on jump server source IPs will fire constantly in environments with a managed jump host infrastructure.
IT admin accounts: Service accounts used by endpoint management tools (SCCM, Intune MDM, etc.) may initiate RDP connections programmatically. Identify these and add them to filter lists.
VPN IP ranges: If your VPN assigns user IPs from a known range, those shouldn’t trigger RDP-from-unknown-IP alerts. If it’s dynamic, consider flagging connections where the source IP changes significantly within a short window for the same account.
Time-of-day baselines: In environments where legitimate after-hours administration is common (global organisations, 24/7 ops teams), time-based rules need adjustment or suppression for specific account groups.
Correlation with Known Attacker TTPs
RDP lateral movement rarely appears in isolation. Correlate RDP detections with:
- Credential dumping preceding the logon — if LSASS access events (Sysmon Event ID 10 on the source host) preceded the RDP connection, that’s a high-confidence chain
- New account creation following the RDP logon — attackers establishing persistence after achieving RDP access
- Ransomware deployment tools —
rclone.exe,wevtutil.exe(log clearing),vssadmin delete shadowsoccurring in the same session window as the RDP logon
T1021.001 combined with T1003 (credential dumping), T1136 (account creation), or T1490 (inhibit system recovery) represents a high-confidence ransomware pre-deployment pattern.