← Back to SOC feed Coverage →

Rare RDP Connections

kql MEDIUM Azure-Sentinel
T1021
SecurityEventWindowsEvent
microsoftofficial
This rule was pulled from an open-source repository and enriched with AI. Validate in a test environment before deploying to production.
View original rule at Azure-Sentinel →
Retrieved: 2026-04-18T16:05:06Z · Confidence: medium

Hunt Hypothesis

Adversaries may use rare RDP connections to establish persistent access or exfiltrate data undetected by mimicking legitimate user behavior. SOC teams should proactively hunt for this behavior in Azure Sentinel to identify potential lateral movement or command and control activities that evade traditional detection methods.

KQL Query

let starttime = 14d;
let endtime = 1d;
(union isfuzzy=true
(SecurityEvent
| where TimeGenerated >= ago(endtime)
| where EventID == 4624 and LogonType == 10
| summarize StartTime = min(TimeGenerated), EndTime = max(TimeGenerated), ConnectionCount = count()
by Account = tolower(Account), Computer = toupper(Computer), IpAddress, AccountType, Activity, LogonTypeName, ProcessName
// use left anti to exclude anything from the previous 14 days that is not rare
),
(WindowsEvent
| where TimeGenerated >= ago(endtime)
| where EventID == 4624 and EventData has ("10")
| extend LogonType = tostring(EventData.LogonType)
| where  LogonType == 10
| extend Account = strcat(tostring(EventData.TargetDomainName),"\\", tostring(EventData.TargetUserName))
| extend ProcessName = tostring(EventData.ProcessName)
| extend IpAddress = tostring(EventData.IpAddress)
| extend TargetUserSid = tostring(EventData.TargetUserSid)
| extend AccountType=case(Account endswith "$" or TargetUserSid in ("S-1-5-18", "S-1-5-19", "S-1-5-20"), "Machine", isempty(TargetUserSid), "", "User")
| extend Activity="4624 - An account was successfully logged on."
| extend LogonTypeName="10 - RemoteInteractive"
| summarize StartTime = min(TimeGenerated), EndTime = max(TimeGenerated), ConnectionCount = count()
by Account = tolower(Account), Computer = toupper(Computer), IpAddress, AccountType, Activity, LogonTypeName, ProcessName
))
| join kind=leftanti (
(union isfuzzy=true
(SecurityEvent
| where TimeGenerated between (ago(starttime) .. ago(endtime))
| where EventID == 4624
| summarize by Computer = toupper(Computer), IpAddress, Account = tolower(Account)
),
( WindowsEvent
| where TimeGenerated between (ago(starttime) .. ago(endtime))
| where EventID == 4624
| extend IpAddress = tostring(EventData.IpAddress)
| extend Account = strcat(tostring(EventData.TargetDomainName),"\\", tostring(EventData.TargetUserName))
| summarize by Computer = toupper(Computer), IpAddress, Account = tolower(Account)
))
) on Account, Computer
| summarize StartTime = min(StartTime), EndTime = max(EndTime), ConnectionCount = sum(ConnectionCount)
by Account, Computer, IpAddress, AccountType, Activity, LogonTypeName, ProcessName
| extend HostName = tostring(split(Computer, ".")[0]), DomainIndex = toint(indexof(Computer, '.'))
| extend HostNameDomain = iff(DomainIndex != -1, substring(Computer, DomainIndex + 1), Computer)
| extend AccountName = tostring(split(Account, @"\")[1]), AccountNTDomain = tostring(split(Account, @"\")[0])
| project-away DomainIndex

Analytic Rule Definition

id: 45b903c5-6f56-4969-af10-ae62ac709718
name: Rare RDP Connections
description: |
  'Identifies when an RDP connection is new or rare related to any logon type by a given account today compared with the previous 14 days.
  RDP connections are indicated by the EventID 4624 with LogonType = 10'
severity: Medium
requiredDataConnectors:
  - connectorId: SecurityEvents
    dataTypes:
      - SecurityEvent
  - connectorId: WindowsSecurityEvents
    dataTypes:
      - SecurityEvent
  - connectorId: WindowsForwardedEvents
    dataTypes:
      - WindowsEvent
queryFrequency: 1d
queryPeriod: 14d
triggerOperator: gt
triggerThreshold: 0
tactics:
  - LateralMovement
relevantTechniques:
  - T1021
query: |
  let starttime = 14d;
  let endtime = 1d;
  (union isfuzzy=true
  (SecurityEvent
  | where TimeGenerated >= ago(endtime)
  | where EventID == 4624 and LogonType == 10
  | summarize StartTime = min(TimeGenerated), EndTime = max(TimeGenerated), ConnectionCount = count()
  by Account = tolower(Account), Computer = toupper(Computer), IpAddress, AccountType, Activity, LogonTypeName, ProcessName
  // use left anti to exclude anything from the previous 14 days that is not rare
  ),
  (WindowsEvent
  | where TimeGenerated >= ago(endtime)
  | where EventID == 4624 and EventData has ("10")
  | extend LogonType = tostring(EventData.LogonType)
  | where  LogonType == 10
  | extend Account = strcat(tostring(EventData.TargetDomainName),"\\", tostring(EventData.TargetUserName))
  | extend ProcessName = tostring(EventData.ProcessName)
  | extend IpAddress = tostring(EventData.IpAddress)
  | extend TargetUserSid = tostring(EventData.TargetUserSid)
  | extend AccountType=case(Account endswith "$" or TargetUserSid in ("S-1-5-18", "S-1-5-19", "S-1-5-20"), "Machine", isempty(TargetUserSid), "", "User")
  | extend Activity="4624 - An account was successfully logged on."
  | extend LogonTypeName="10 - RemoteInteractive"
  | summarize StartTime = min(TimeGenerated), EndTime = max(TimeGenerated), ConnectionCount = count()
  by Account = tolower(Account), Computer = toupper(Computer), IpAddress, AccountType, Activity, LogonTypeName, ProcessName
  ))
  | join kind=leftanti (
  (union isfuzzy=true
  (SecurityEvent
  | where TimeGenerated between (ago(starttime) .. ago(endtime))
  | where EventID == 4624
  | summarize by Computer = toupper(Computer), IpAddress, Account = tolower(Account)
  ),
  ( WindowsEvent
  | where TimeGenerated between (ago(starttime) .. ago(endtime))
  | where EventID == 4624
  | extend IpAddress = tostring(EventData.IpAddress)
  | extend Account = strcat(tostring(EventData.TargetDomainName),"\\", tostring(EventData.TargetUserName))
  | summarize by Computer = toupper(Computer), IpAddress, Account = tolower(Account)
  ))
  ) on Account, Computer
  | summarize StartTime = min(StartTime), EndTime = max(EndTime), ConnectionCount = sum(ConnectionCount)
  by Account, Computer, IpAddress, AccountType, Activity, LogonTypeName, ProcessName
  | extend HostName = tostring(s

Required Data Sources

Sentinel TableNotes
SecurityEventEnsure this data connector is enabled
WindowsEventEnsure this data connector is enabled

MITRE ATT&CK Context

References

False Positive Guidance

Original source: https://github.com/Azure/Azure-Sentinel/blob/main/Detections/SecurityEvent/RDP_RareConnection.yaml