Detection rules › Kusto
Potential Remote Desktop Tunneling
This query detects remote desktop authentication attempts with a localhost source address, which can indicate a tunneled login. Ref: https://www.mandiant.com/resources/bypassing-network-restrictions-through-rdp-tunneling
MITRE ATT&CK coverage
| Tactic | Techniques |
|---|---|
| Command & Control | T1572 Protocol Tunneling |
Event coverage
| Provider | Event | Title |
|---|---|---|
| Security-Auditing | Event ID 4624 | An account was successfully logged on. |
| Security-Auditing | Event ID 4625 | An account failed to log on. |
Rule body kusto
id: d2e8fd50-8d66-11ec-b909-0242ac120002
name: Potential Remote Desktop Tunneling
description: |
'This query detects remote desktop authentication attempts with a localhost source address, which can indicate a tunneled login.
Ref: https://www.mandiant.com/resources/bypassing-network-restrictions-through-rdp-tunneling'
severity: Medium
status: Available
requiredDataConnectors:
- connectorId: SecurityEvents
dataTypes:
- SecurityEvent
- connectorId: WindowsSecurityEvents
dataTypes:
- SecurityEvent
queryFrequency: 1h
queryPeriod: 1h
triggerOperator: gt
triggerThreshold: 0
tactics:
- CommandAndControl
relevantTechniques:
- T1572
query: |
SecurityEvent
| where EventID in (4624,4625) and LogonType in (10) and IpAddress in ("::1","127.0.0.1")
| summarize StartTime = min(TimeGenerated), EndTime = max(TimeGenerated) by EventID, Computer, TargetUserName, TargetLogonId, LogonType, IpAddress
| extend Name=tostring(split(TargetUserName, "@")[0]), UPNSuffix=tostring(split(TargetUserName, "@")[1])
| extend HostName = iif(Computer has '.',substring(Computer,0,indexof(Computer,'.')),Computer) , DnsDomain = iif(Computer has '.',substring(Computer,indexof(Computer,'.')+1),'')
entityMappings:
- entityType: Account
fieldMappings:
- identifier: Name
columnName: Name
- identifier: UPNSuffix
columnName: UPNSuffix
- entityType: Host
fieldMappings:
- identifier: FullName
columnName: Computer
- identifier: HostName
columnName: HostName
- identifier: DnsDomain
columnName: DnsDomain
- entityType: IP
fieldMappings:
- identifier: Address
columnName: IpAddress
version: 1.0.4
kind: Scheduled
Stages and Predicates
Stage 1: source
SecurityEvent
Stage 2: where
| where EventID in (4624,4625) and LogonType in (10) and IpAddress in ("::1","127.0.0.1")
Stage 3: summarize
| summarize StartTime = min(TimeGenerated), EndTime = max(TimeGenerated) by EventID, Computer, TargetUserName, TargetLogonId, LogonType, IpAddress
Stage 4: extend
| extend Name=tostring(split(TargetUserName, "@")[0]), UPNSuffix=tostring(split(TargetUserName, "@")[1])
Stage 5: extend
| extend HostName = iif(Computer has '.',substring(Computer,0,indexof(Computer,'.')),Computer) , DnsDomain = iif(Computer has '.',substring(Computer,indexof(Computer,'.')+1),'')
Indicators
Each row is a field, operator, and value that the rule matches. The corpus column counts how many other rules in the catalog look for the same combination: high numbers point to widely-used, community-vetted indicators. Blank or 1 shows that the indicator is specific to this rule.
Output fields
Fields the rule emits when it matches. Chronicle authors list these in the outcome block; they appear on the detection and $risk_score drives alerting. Sentinel / Defender XDR rules build them up through project / summarize / extend stages. Sentinel maps these into alert fields via entityMappings and customDetails; Defender XDR custom detections surface them as alert fields directly.
| Field | Source |
|---|---|
Computer | summarize |
EndTime | summarize |
EventID | summarize |
IpAddress | summarize |
LogonType | summarize |
StartTime | summarize |
TargetLogonId | summarize |
TargetUserName | summarize |
Name | extend |
UPNSuffix | extend |
DnsDomain | extend |
HostName | extend |