Detection rules › Kusto

Rouge RDP: Suspicious File Creation

Group by
DeviceId, InitiatingProcessFileName
Author
Cyb3rMonk
Source
github.com/Cyb3r-Monk/Threat-Hunting-and-Detection

Below query detects file creations of mstsc.exe where it also makes a network connection to a public IP address. This behavior is an indication of Rogue RDP.
False Positives: Copying files to the local machine over RDP may cause false positives.

MITRE ATT&CK coverage

References

Telemetry coverage

Rule body

// Author: Cyb3rMonk(https://twitter.com/Cyb3rMonk, https://mergene.medium.com)
// Description: Detect file creations of mstsc.exe where it also makes a network connection to a public IP address. This behavior is an indication of Rogue RDP. 
//
// Query parameters:
// there might be more file types that can be leveraged
// adjust file types to monitor
// consider DLL sideloading opportunities if you want to filter based on folders.
let file_types = dynamic([".dll", ".exe", ".cpl", ".pif", ".com", ".js", ".vbs", ".wsh", ".vbe", ".jse", ".bat", ".cmd", ".lnk", ".url", ".png", ".hta", ".svg"]);
let _query_period = 7d;
DeviceNetworkEvents
| where Timestamp > ago(_query_period)
| where ActionType in ("ConnectionSuccess")
| where InitiatingProcessFileName =~ "mstsc.exe"
| where RemoteIPType == "Public"
| project Timestamp, DeviceId, DeviceName, InitiatingProcessFileName=tolower(InitiatingProcessFileName), InitiatingProcessId, RemoteIP, RemoteUrl, RemotePort, NetworkTimestamp = Timestamp
| join kind=inner (
    DeviceFileEvents
    | where Timestamp > ago(_query_period)
    | where ActionType in ("FileCreated", "FileModified")
    | where InitiatingProcessFileName =~ "mstsc.exe" 
    | where FileName has_any (file_types)
    | extend InitiatingProcessFileName=tolower(InitiatingProcessFileName), FileTimestamp = Timestamp
    ) on InitiatingProcessFileName, DeviceId // InitiatingProcessId or InitiatingProcessUniqueId can be used as well but be mindful of multiple connections and telemetry sampling.
    // adjust time between RDP connection and file creation
    | where datetime_diff('minute', FileTimestamp, NetworkTimestamp) < 60

Stages and Predicates

Parameters

let file_types = dynamic([".dll", ".exe", ".cpl", ".pif", ".com", ".js", ".vbs", ".wsh", ".vbe", ".jse", ".bat", ".cmd", ".lnk", ".url", ".png", ".hta", ".svg"]);
let _query_period = 7d;

Stage 1: source

DeviceNetworkEvents

Stage 2: where

| where Timestamp > ago(_query_period)

Stage 3: where

| where ActionType in ("ConnectionSuccess")

Stage 4: where

| where InitiatingProcessFileName =~ "mstsc.exe"

Stage 5: where

| where RemoteIPType == "Public"

Stage 6: project

| project Timestamp, DeviceId, DeviceName, InitiatingProcessFileName=tolower(InitiatingProcessFileName), InitiatingProcessId, RemoteIP, RemoteUrl, RemotePort, NetworkTimestamp = Timestamp

Stage 7: join

| join kind=inner (
    DeviceFileEvents
    | where Timestamp > ago(_query_period)
    | where ActionType in ("FileCreated", "FileModified")
    | where InitiatingProcessFileName =~ "mstsc.exe" 
    | where FileName has_any (file_types)
    | extend InitiatingProcessFileName=tolower(InitiatingProcessFileName), FileTimestamp = Timestamp
    ) on InitiatingProcessFileName, DeviceId

Stage 8: where FileTimestamp - NetworkTimestamp < 1h

| where datetime_diff('minute', FileTimestamp, NetworkTimestamp) < 60

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
ActionTypein
  • ConnectionSuccess
  • FileCreated
  • FileModified
field:"ActionType" kind:in
FileNamematch
  • .bat transforms: term
  • .cmd transforms: term
  • .com transforms: term
  • .cpl transforms: term
  • .dll transforms: term
  • .exe transforms: term
  • .hta transforms: term
  • .js transforms: term
  • .jse transforms: term
  • .lnk transforms: term
  • .pif transforms: term
  • .png transforms: term
  • .svg transforms: term
  • .url transforms: term
  • .vbe transforms: term
  • .vbs transforms: term
  • .wsh transforms: term
field:"file_name" kind:match
InitiatingProcessFileNameeq
  • mstsc.exe
field:"parent_process_name" kind:eq value:"mstsc.exe"
RemoteIPTypeeq
  • Public
field:"RemoteIPType" kind:eq value:"Public"

Output fields

These fields are emitted when the rule matches.

FieldSource
DeviceIdproject
DeviceNameproject
InitiatingProcessFileNameproject
InitiatingProcessIdproject
NetworkTimestampproject
RemoteIPproject
RemotePortproject
RemoteUrlproject
Timestampproject