T1584.003 Microsoft Sentinel · KQL

Detect Virtual Private Server in Microsoft Sentinel

Adversaries may compromise third-party Virtual Private Servers (VPSs) to use as operational infrastructure. By taking over VPS instances purchased by legitimate third parties at providers such as DigitalOcean, Linode, Vultr, Hetzner, or OVH, adversaries gain infrastructure that carries the reputation of trusted cloud providers while obscuring the true origin of their operations. Compromised VPS infrastructure is typically leveraged for Command and Control, staging payloads, proxying traffic, or exfiltrating data. Notable examples include Volt Typhoon compromising VPS nodes to proxy C2 traffic through legitimate-appearing cloud infrastructure, and Turla reusing compromised Iranian threat actor VPS infrastructure. Detection must pivot from the adversary's external preparatory action (compromising the VPS itself, which is unobservable from the victim network) to the observable USAGE patterns: beaconing connections to VPS provider IP space, C2-characteristic network behavior such as regular connection intervals with low data volume, and threat intelligence matches against known-compromised VPS nodes.

MITRE ATT&CK

Tactic
Resource Development
Technique
T1584 Compromise Infrastructure
Sub-technique
T1584.003 Virtual Private Server
Canonical reference
https://attack.mitre.org/techniques/T1584/003/

KQL Detection Query

Microsoft Sentinel (KQL)
kusto
// T1584.003 — Compromised VPS C2 Detection
// Detects beaconing patterns and connections to VPS provider IP ranges
// consistent with adversaries using compromised third-party VPS infrastructure
let VPSProviderRanges = dynamic([
  "104.16.", "104.17.", "104.18.", "104.19.",    // Cloudflare (often abused)
  "64.225.", "143.198.", "157.245.", "167.71.",  // DigitalOcean
  "45.33.", "45.56.", "45.79.", "50.116.",       // Linode/Akamai
  "45.63.", "45.76.", "45.77.",                  // Vultr
  "5.9.", "5.161.", "23.88.", "49.12.", "65.21.", "88.99.", "95.216.", "116.202.", "128.140.", "135.181.", "138.201.", "157.90.", "159.69.", "162.55.", "176.9.", "178.63.", "188.34.", "195.201.", "213.239.", // Hetzner
  "51.38.", "51.68.", "51.75.", "51.77.", "54.36.", "54.38.", "87.98." // OVH
]);
let BeaconWindow = 24h;
let MinConnections = 10;
let MaxJitterPct = 0.15;  // ≤15% jitter indicates automated beaconing
// Step 1: Find repeated outbound connections to VPS provider ranges
let VPSConnections = DeviceNetworkEvents
| where Timestamp > ago(BeaconWindow)
| where ActionType in ("ConnectionSuccess", "ConnectionAttempt")
| where RemoteIPType == "Public"
| where RemotePort in (80, 443, 8080, 8443, 4443, 4444, 1080, 1194, 8888, 8889, 9001, 9030)
    or (RemotePort between (49152 .. 65535))  // High ports also used for C2
| where RemoteIP has_any (VPSProviderRanges)
| project Timestamp, DeviceName, DeviceId, AccountName, LocalIP, RemoteIP, RemotePort,
          InitiatingProcessFileName, InitiatingProcessCommandLine,
          InitiatingProcessParentFileName, BytesSent, BytesReceived;
// Step 2: Calculate inter-connection intervals per device+IP pair for beacon detection
VPSConnections
| summarize
    ConnectionCount = count(),
    FirstSeen = min(Timestamp),
    LastSeen = max(Timestamp),
    TotalBytesSent = sum(BytesSent),
    TotalBytesReceived = sum(BytesReceived),
    UniqueProcesses = dcount(InitiatingProcessFileName),
    ProcessNames = make_set(InitiatingProcessFileName, 5),
    CommandLines = make_set(InitiatingProcessCommandLine, 3)
    by DeviceName, AccountName, RemoteIP, RemotePort
| where ConnectionCount >= MinConnections
| extend SessionDurationHours = datetime_diff('minute', LastSeen, FirstSeen) / 60.0
| extend AvgIntervalMinutes = iif(ConnectionCount > 1, SessionDurationHours * 60 / (ConnectionCount - 1), 0.0)
| extend AvgBytesPerConnection = iif(ConnectionCount > 0, (TotalBytesSent + TotalBytesReceived) / ConnectionCount, 0)
// Low bytes-per-connection with high connection count = C2 beacon pattern
| extend LowVolumeBeacon = iff(AvgBytesPerConnection < 5000 and ConnectionCount > 20, true, false)
// Regular interval suggests automated callback (not human browsing)
| extend RegularInterval = iff(AvgIntervalMinutes > 0 and AvgIntervalMinutes < 60, true, false)
| where LowVolumeBeacon == true or RegularInterval == true or ConnectionCount > 50
| project-reorder DeviceName, AccountName, RemoteIP, RemotePort, ConnectionCount,
    AvgIntervalMinutes, AvgBytesPerConnection, LowVolumeBeacon, RegularInterval,
    ProcessNames, FirstSeen, LastSeen, TotalBytesSent, TotalBytesReceived
high severity medium confidence

Detects potential C2 beaconing over compromised VPS infrastructure by combining two detection signals: (1) outbound connections to known VPS provider IP ranges (DigitalOcean, Linode, Vultr, Hetzner, OVH) on ports commonly used for C2, and (2) beaconing characteristics — high connection count with low bytes-per-connection (automated check-in pattern) or regular connection intervals. Targets DeviceNetworkEvents in Microsoft Defender for Endpoint. Volt Typhoon and Turla both used compromised VPS nodes for C2; this query looks for the network behavior those nodes produce in victim telemetry.

Data Sources

Network Traffic: Network Connection CreationNetwork Traffic: Network Traffic FlowMicrosoft Defender for Endpoint

Required Tables

DeviceNetworkEvents

False Positives & Tuning

  • Cloud-hosted SaaS applications and business tools (Slack, Zoom, Datadog agents) that make frequent small HTTPS connections to cloud provider IP ranges
  • Software update services (OS updates, antivirus definitions) that poll VPS-hosted CDN endpoints on regular intervals
  • Developer workstations with personal VPS instances for legitimate remote work, CI/CD pipelines, or side projects hosted at the listed providers
  • VPN clients and corporate proxy configurations that route traffic through VPS-hosted endpoints at the listed providers
  • Telemetry and monitoring agents that beacon regularly to cloud-hosted collection infrastructure (e.g., Elastic Agents, Splunk UFs reporting to cloud-hosted indexers)
Download portable Sigma rule (.yml)

Other platforms for T1584.003


Testing Methodology

Validate this detection against 4 adversary techniques from Atomic Red Team. Each test below lists the behaviour to exercise and the telemetry you should expect to see. Executable commands and cleanup steps are available with Pro.

  1. Test 1Simulate C2 Beacon to VPS Provider IP Range

    Expected signal: Sysmon Event ID 3: 20 Network Connection events with Image=curl.exe (or the parent PowerShell/cmd.exe), DestinationIp=143.198.0.1, DestinationPort=80. Events will be spaced approximately 60 seconds apart. Firewall/proxy logs will show 20 outbound connections to 143.198.0.1:80 from the test host.

  2. Test 2Resolve and Connect to Known VPS-Hosted Domain (DNS + Network Correlation)

    Expected signal: Sysmon Event ID 22: DNS query for ipinfo.io resolving to an IP in cloud provider space. Sysmon Event ID 3: Network connection to the resolved IP on port 80 within seconds of the DNS query. Both events will share the same PID (powershell.exe) allowing correlation. The DNS event will contain the resolved IP in QueryResults.

  3. Test 3Linux Beacon Simulation to VPS IP Range

    Expected signal: auditd SYSCALL records for connect() syscalls to 95.216.0.1:80, or syslog entries if auditd is configured to capture network calls. On hosts with Sysmon for Linux: Event ID 3 (Network Connection) with DestinationIp=95.216.0.1. Firewall/proxy session logs show repeated connections from the source host at ~30s intervals.

  4. Test 4Cobalt Strike Default JA3 Fingerprint Simulation via Custom TLS Client Hello

    Expected signal: Sysmon Event ID 3: Network connection to 143.198.0.1:443 initiated by python.exe. If TLS fingerprinting is deployed at the network layer (Zeek bro:ssl:json or similar), the JA3 field will contain the fingerprint value matching or approximating Cobalt Strike's default. MDE DeviceNetworkEvents will record the connection with TlsFingerprint field populated.

Unlock Pro Content

Get the full detection package for T1584.003 including response playbook, investigation guide, and atomic red team tests.

Response PlaybookInvestigation GuideHunting QueriesAtomic Red Team TestsTuning Guidance

Related Detections