T1583

Acquire Infrastructure

Resource Development Last updated:

This detection identifies indicators that adversaries have acquired or are leveraging external infrastructure for attack operations — including virtual private servers, bulletproof hosting providers, anonymizing VPN services, and residential proxy networks. Because T1583 is a PRE-ATT&CK technique occurring outside direct victim visibility, detection focuses on observable artifacts within the target environment: authentication events originating from known hosting ASNs and VPN exit nodes, DNS resolution of anonymization service domains, and network connection patterns consistent with adversary use of acquired proxy or VPN infrastructure. High-confidence signals include privileged account sign-ins from hosting provider IP ranges (M247, Hetzner, OVH, DigitalOcean), automated tooling user-agents accessing organizational resources from VPS IPs, and connections to infrastructure linked to threat actor campaigns such as Kimsuky, Sea Turtle, and Agrius.

What is T1583 Acquire Infrastructure?

Acquire Infrastructure (T1583) maps to the Resource Development tactic — the adversary is trying to establish resources they can use to support operations in MITRE ATT&CK.

This page provides production-ready detection logic for Acquire Infrastructure, covering the data sources and telemetry it touches: Azure Active Directory, Microsoft Entra ID. The queries below are rated high severity at medium confidence, and ship for 7 SIEM platforms — KQL, SPL, Elastic, QRadar, Sumo, YARA-L, LogScale.

MITRE ATT&CK

Tactic
Resource Development
Technique
T1583 Acquire Infrastructure
Canonical reference
https://attack.mitre.org/techniques/T1583/
Microsoft Sentinel / Defender
kusto
let HostingProviderASNs = dynamic([
    9009,   // M247 Europe SRL - frequently abused bulletproof hosting
    202448, // MVPS - known bulletproof hosting
    16276,  // OVH SAS
    14061,  // DigitalOcean LLC
    63949,  // Akamai Connected Cloud (Linode)
    24940,  // Hetzner Online GmbH
    51167,  // Contabo GmbH
    47583,  // Hostinger International
    60068,  // Datacamp Limited - residential proxy
    174,    // Cogent Communications
    3257    // GTT Communications
]);
let VPNKeywords = dynamic(["vpn", "tor", "proxy", "anonymizer", "hosting", "datacenter"]);
AADSignInLogs
| where TimeGenerated >= ago(24h)
| where ResultType == "0"
| where AutonomousSystemNumber in (HostingProviderASNs)
    or NetworkLocationDetails has_any (VPNKeywords)
    or RiskEventTypes_V2 has_any ("anonymizedIPAddress", "maliciousIPAddress")
| where IPAddress !in ("127.0.0.1", "::1", "0.0.0.0")
| summarize
    SignInCount = count(),
    UniqueSourceIPs = dcount(IPAddress),
    TargetApps = make_set(AppDisplayName, 10),
    ClientApps = make_set(ClientAppUsed, 5),
    LocationDetails = make_set(tostring(LocationDetails), 5),
    FirstSeen = min(TimeGenerated),
    LastSeen = max(TimeGenerated)
    by UserPrincipalName, AutonomousSystemNumber, NetworkLocationDetails
| extend RiskScore = case(
    TargetApps has_any ("Azure Portal", "Microsoft Azure Management", "Azure Active Directory"), 9,
    UniqueSourceIPs > 5, 8,
    UniqueSourceIPs > 2, 6,
    SignInCount > 10, 5,
    4)
| where RiskScore >= 5
| project TimeGenerated = LastSeen, UserPrincipalName, RiskScore, SignInCount,
    UniqueSourceIPs, AutonomousSystemNumber, TargetApps, NetworkLocationDetails,
    FirstSeen, LastSeen
| sort by RiskScore desc, SignInCount desc

Detects successful Azure AD sign-in events originating from autonomous system numbers (ASNs) associated with known VPS/bulletproof hosting providers and anonymizing proxy services. Elevated risk score when privileged management applications (Azure Portal) are targeted or multiple source IPs share the same ASN, indicating adversary use of acquired infrastructure to access organizational resources.

high severity medium confidence

Data Sources

Azure Active Directory Microsoft Entra ID

Required Tables

AADSignInLogs

False Positives

  • Employees legitimately connecting via corporate-approved VPN services that share ASNs with commercial hosting providers
  • Remote developers or contractors using DigitalOcean, Hetzner, or OVH hosted jump boxes for legitimate administrative access
  • Automated service accounts or CI/CD pipelines running in cloud-hosted environments that authenticate to organizational APIs
  • Security researchers or penetration testers operating from known hosting providers during authorized engagements
  • Employees traveling internationally who use commercial VPN services that route through hosting provider IP ranges

Sigma rule & cross-platform mapping

The detection logic for Acquire Infrastructure (T1583) above is provided in a vendor-neutral form so you can deploy it on any SIEM. The same logic is shipped here as native KQL (Microsoft Sentinel / Defender), SPL (Splunk), Elastic (Elastic Security (EQL)), QRadar (IBM QRadar (AQL)), Sumo (Sumo Logic CSE), YARA-L (Google Chronicle / SecOps), LogScale (CrowdStrike LogScale (CQL)) queries. In Sigma terms, this detection targets the following logsource:

logsource:
  product: azure

Browse the community-maintained Sigma rules for this technique:


Testing Methodology

Validate this detection against 3 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 VPN Infrastructure Use - DNS Enumeration of Anonymization Services

    Expected signal: Sysmon Event ID 22 (DnsQuery) entries for each queried domain showing QueryName, QueryResults, and the initiating PowerShell process. Also visible in DeviceNetworkEvents (ActionType: DnsQueryResponse) in Microsoft Defender for Endpoint.

  2. Test 2Simulate Authentication from VPS Infrastructure via Proxied HTTP Request

    Expected signal: Network connection event from the endpoint to the proxy IP. If authentication proceeds through the proxy, AADSignInLogs will record the VPS IP as the source. Sysmon Event 3 (NetworkConnect) visible for the outbound proxy connection.

  3. Test 3Cloud Infrastructure Provisioning via Azure CLI (Adversary Infrastructure Simulation)

    Expected signal: Azure Activity Log entries: Microsoft.Compute/virtualMachines/write, Microsoft.Network/publicIPAddresses/write, Microsoft.Resources/deployments/write. Visible in AzureActivity table in Sentinel and azure:activity sourcetype in Splunk. Also triggers Azure Security Center alerts if Defender for Cloud is enabled.


Response Playbook

Triage

  1. Step 1: Identify the source IP(s) and look up their ASN, hosting provider, geolocation, and reputation via threat intelligence platforms (VirusTotal, Shodan, AbuseIPDB). Determine if the IP is a known Tor exit node, VPN endpoint, or bulletproof hosting range.
  2. Step 2: Check the authenticating account's baseline behavior — compare source IP history, typical geographic locations, and normal sign-in times using AADSignInLogs spanning the prior 30 days. A VPS IP sign-in is high-risk if the user has never authenticated from that geography or ASN.
  3. Step 3: Review what resources the account accessed during the session — focus on Azure Portal, Azure AD admin, Exchange Online, SharePoint, or privileged service APIs. Admin-panel access from hosting IPs is an escalation trigger regardless of other signals.
  4. Step 4: Check for concurrent sign-ins — did the same account authenticate from a legitimate location (user's home/office IP) within the same time window? Concurrent authentication from disparate geographies (impossible travel) confirms account compromise.
  5. Step 5: Inspect the user agent string from the sign-in event. Automated tooling (curl, python-requests, go-http-client) combined with a hosting provider IP indicates scripted access, not human use of a VPN.
  6. Step 6: Search for the same source IP across all accounts in the tenant — if multiple accounts authenticated from the same hosting IP in a short window, this indicates a credential spray or phishing campaign using acquired infrastructure.

Containment

  1. Revoke all active sessions for the affected account immediately using Azure AD: `Revoke-AzureADUserAllRefreshToken -ObjectId <UPN>` or via the Entra portal.
  2. Enforce re-authentication with MFA for the affected account and require compliant device sign-in via Conditional Access policies.
  3. Block the specific source IP or CIDR range at the network perimeter or via Azure AD Named Locations if it is confirmed adversary infrastructure and has no legitimate organizational use.
  4. If the account is privileged (Global Admin, Exchange Admin, Security Admin), disable the account immediately and perform emergency credential reset: reset password, rotate all API tokens and service principal secrets associated with the account.
  5. If cloud resource provisioning activity (VM creation, storage container access, role assignments) is detected from the compromised account, audit and roll back unauthorized changes using Azure Activity Log.
  6. Notify the account owner out-of-band (phone, in-person) — do not use email if the inbox may be compromised.

Evidence Collection

  1. Export the complete AADSignInLogs for the affected account for 30 days prior to the alert, including all IP addresses, ASNs, user agents, conditional access results, and risk scores.
  2. Pull Azure Activity Log (AuditLogs) for the account to identify all resource creation, deletion, role assignment, or permission modification events during the suspicious session.
  3. Collect OfficeActivity logs to identify any email forwarding rules, inbox rule creation, calendar sharing, or SharePoint/OneDrive data access during the period.
  4. Capture full network flow logs from perimeter devices (firewall, proxy) for traffic to and from the identified source IP during the incident window.
  5. Export Azure AD Risky Users and Risk Detections from Identity Protection for the affected account — these contain Microsoft's threat intelligence on the sign-in.
  6. Document the full hosting provider details: ASN, IP WHOIS data, reverse DNS, any historical abuse reports — this supports threat intelligence sharing and law enforcement referral.
  7. If endpoint access occurred, collect Windows Security event logs (4624/4625/4648), Sysmon logs, and network connection records from the authenticating workstation.

Escalation Criteria

  • ! Escalate immediately if a privileged account (Global Admin, Security Admin, Exchange Admin, or any account with Azure RBAC Owner role) authenticated from hosting provider infrastructure.
  • ! Escalate if the adversary accessed administrative interfaces (Azure Portal, Exchange Admin Center, Microsoft 365 Admin) or modified security policies, conditional access rules, or MFA settings.
  • ! Escalate if multiple accounts authenticated from the same hosting IP — this indicates a coordinated attack using acquired infrastructure for credential stuffing or account takeover at scale.
  • ! Escalate if cloud resource provisioning was detected — adversary may be extending their acquired infrastructure within the victim's own cloud tenant.
  • ! Escalate if the source IP matches known threat actor infrastructure from current threat intelligence feeds (CISA advisories, ISAC sharing, Mandiant/CrowdStrike reporting) for active campaigns targeting your sector.
  • ! Escalate if lateral movement indicators are present after initial authentication from the hosting IP (access to additional systems, new OAuth app consent grants, service principal creation).

Investigation Guide

Forensic Artifacts

  • > Azure AD sign-in logs (AADSignInLogs) — source IP, ASN, geolocation, user agent, conditional access evaluation results, risk level
  • > Azure Activity Log (AuditLogs) — resource provisioning, role assignments, policy changes made during suspicious sessions
  • > OfficeActivity logs — email rule creation, forwarding rules, file access, Teams activity during the incident window
  • > Network perimeter logs (firewall, web proxy) — full connection records including bytes transferred, session duration, and protocol details for source IPs
  • > Windows Security Event Log — 4624/4625/4648/4672 logon events from hosting provider IPs on internal systems
  • > Sysmon Event 22 (DNS queries) — DNS lookups to VPN providers, anonymization services, or known C2 infrastructure
  • > Sysmon Event 3 (Network connections) — outbound connections from internal hosts to hosting provider IP ranges
  • > IP reputation intelligence — WHOIS records, ASN ownership, historical abuse database entries for source IPs
  • > Cloud provider audit trails — AWS CloudTrail, Azure Activity Log, GCP Cloud Audit Logs for adversary-provisioned infrastructure actions

Tuning Guidance

The primary source of false positives is legitimate remote work and VPN usage. To reduce noise: (1) Maintain a Named Locations allowlist in Azure AD for approved corporate VPN exit node IP ranges and exclude these from alerting. (2) Create an exception list for known contractor and vendor IP ranges verified by procurement. (3) Filter out service accounts and non-interactive sign-in categories (ServicePrincipal, ManagedIdentity) which are expected to run from cloud-hosted environments. (4) Tune ASN thresholds by reviewing your organization's legitimate cloud vendor footprint — if developers routinely use DigitalOcean or Hetzner for work, adjust confidence accordingly and add secondary conditions (e.g., also require unusual user agent OR impossible travel). (5) For the DNS hunting query, whitelist known-approved VPN client software (corporate VPN agents) by process path. (6) Consider integrating commercial threat intelligence feeds that maintain current Tor exit node and residential proxy IP lists for higher-fidelity matching than static IP ranges.


Hunting Queries

Hunts for credential spray attacks using acquired VPS infrastructure — identifies single IP addresses authenticating against 3+ accounts in a one-hour window, indicating distributed tooling rather than legitimate VPN use.

Hunting — KQL
kql
// Hunt: Multiple accounts authenticating from same hosting provider IP
// Finds credential spray or phishing campaigns using acquired VPS infrastructure
AADSignInLogs
| where TimeGenerated >= ago(7d)
| where ResultType == "0"
| where IPAddress !in ("127.0.0.1", "::1")
| summarize
    UniqueAccounts = dcount(UserPrincipalName),
    AccountList = make_set(UserPrincipalName, 20),
    SignInCount = count(),
    AppList = make_set(AppDisplayName, 5)
    by IPAddress, AutonomousSystemNumber, bin(TimeGenerated, 1h)
| where UniqueAccounts >= 3
| join kind=leftouter (
    AADSignInLogs
    | where TimeGenerated >= ago(7d)
    | summarize FailedAttempts = countif(ResultType != "0") by IPAddress
) on IPAddress
| extend SprayScore = case(
    UniqueAccounts > 10, 10,
    UniqueAccounts > 5, 7,
    FailedAttempts > UniqueAccounts, 8,
    5)
| sort by SprayScore desc, UniqueAccounts desc
| project TimeGenerated, IPAddress, AutonomousSystemNumber, UniqueAccounts,
    SignInCount, FailedAttempts, SprayScore, AccountList, AppList
Hunting — SPL
spl
index=windows sourcetype="WinEventLog:Security"
(EventCode=4624 OR EventCode=4625)
| eval src_ip=coalesce(IpAddress, Source_Network_Address)
| where src_ip != "-" AND src_ip != "127.0.0.1" AND isnotnull(src_ip)
| where NOT match(src_ip, "^(10\.|192\.168\.|172\.(1[6-9]|2[0-9]|3[01])\.)")
| stats dc(Account_Name) as unique_accounts,
    values(Account_Name) as accounts,
    count as total_events,
    sum(eval(if(EventCode=="4625",1,0))) as failed_count,
    sum(eval(if(EventCode=="4624",1,0))) as success_count
    by src_ip, span(_time, 1h)
| where unique_accounts >= 3
| eval spray_score=case(unique_accounts > 10, 10, failed_count > success_count, 8, unique_accounts > 5, 7, 5)
| sort -spray_score
| table src_ip, unique_accounts, accounts, total_events, failed_count, success_count, spray_score

Hunts for DNS resolution of known VPN and anonymization service domains from internal endpoints — differs from main detection by focusing on Sysmon DNS telemetry and the client side of VPN enumeration rather than authentication events.

Hunting — KQL
kql
// Hunt: Sysmon DNS lookups to known VPN and anonymization service domains
// Identifies endpoints resolving anonymization infrastructure potentially used for C2 or exfil staging
let AnonymizationDomains = dynamic([
    "surfshark.com", "protonvpn.com", "nordvpn.com", "expressvpn.com",
    "ivpn.net", "mullvad.net", "privateinternetaccess.com", "hidemyass.com",
    "cyberghostvpn.com", "ipvanish.com", "torproject.org", "tails.boum.org",
    "anonfiles.com", "1984.is", "cryptostorm.is", "perfect-privacy.com"
]);
DeviceNetworkEvents
| where TimeGenerated >= ago(7d)
| where ActionType in ("DnsQueryResponse", "ConnectionSuccess")
| where RemoteUrl has_any (AnonymizationDomains)
    or RemoteUrl matches regex @"(?i)(\.onion|tor-exit|torproject|vpn-|\-vpn\.)"
| summarize
    LookupCount = count(),
    UniqueDestinations = dcount(RemoteUrl),
    QueryList = make_set(RemoteUrl, 10),
    ProcessList = make_set(InitiatingProcessFileName, 5),
    CommandLines = make_set(InitiatingProcessCommandLine, 3)
    by DeviceName, InitiatingProcessAccountName, bin(TimeGenerated, 1d)
| extend ThreatLevel = case(
    QueryList has "torproject.org", "critical",
    UniqueDestinations > 3, "high",
    LookupCount > 10, "medium",
    "low")
| where ThreatLevel != "low"
| sort by ThreatLevel asc, LookupCount desc
Hunting — SPL
spl
index=windows sourcetype="XmlWinEventLog:Microsoft-Windows-Sysmon/Operational" EventCode=22
| rename QueryName as dns_query, Image as process_image, User as username
| where match(dns_query, "(?i)(surfshark\.com|protonvpn\.com|nordvpn\.com|expressvpn\.com|ivpn\.net|mullvad\.net|privateinternetaccess\.com|cyberghostvpn\.com|ipvanish\.com|torproject\.org|\.onion|tor-exit|perfect-privacy\.com|cryptostorm\.is)")
| stats count as lookup_count,
    dc(dns_query) as unique_domains,
    values(dns_query) as queried_domains,
    values(process_image) as processes
    by Computer, username
| eval threat_level=case(
    match(mvjoin(queried_domains," "), "(?i)(torproject|\.onion)"), "critical",
    unique_domains > 3, "high",
    lookup_count > 5, "medium",
    "low")
| where threat_level != "low"
| sort -lookup_count
| table Computer, username, lookup_count, unique_domains, queried_domains, processes, threat_level

Hunts for adversary infrastructure provisioning within victim cloud tenants — detects VM creation, public IP allocation, NSG modifications, and role assignments that may indicate an adversary expanding acquired infrastructure footprint inside the victim environment after initial access.

Hunting — KQL
kql
// Hunt: Azure resource provisioning from unexpected locations suggesting adversary infrastructure setup
// Targets VM creation, public IP allocation, and NSG rule changes from hosting provider ASNs
AzureActivity
| where TimeGenerated >= ago(14d)
| where OperationNameValue in (
    "Microsoft.Compute/virtualMachines/write",
    "Microsoft.Network/publicIPAddresses/write",
    "Microsoft.Network/networkSecurityGroups/write",
    "Microsoft.Authorization/roleAssignments/write",
    "Microsoft.Compute/virtualMachines/runCommand/action")
| where ActivityStatusValue == "Success"
| extend CallerIpAddress = tostring(Properties.requestBody)
| where Caller !endswith ".onmicrosoft.com" or Properties has "runCommand"
| summarize
    OperationCount = count(),
    Operations = make_set(OperationNameValue, 10),
    Resources = make_set(ResourceId, 10),
    CallerIPs = make_set(CallerIpAddress, 5)
    by Caller, ResourceGroup, SubscriptionId, bin(TimeGenerated, 1h)
| where OperationCount >= 2
| where Operations has_any ("virtualMachines/write", "publicIPAddresses/write", "runCommand")
| sort by OperationCount desc
Hunting — SPL
spl
index=azure sourcetype="azure:activity"
operationName IN ("Create or Update Virtual Machine", "Create or Update Public Ip Address", "Create or Update Network Security Group", "Create role assignment")
status="Succeeded"
| stats count as op_count,
    values(operationName) as operations,
    values(resourceId) as resources,
    dc(operationName) as unique_ops
    by caller, resourceGroup, subscriptionId, span(_time, 1h)
| where op_count >= 2 AND unique_ops >= 2
| sort -op_count
| table caller, resourceGroup, subscriptionId, op_count, unique_ops, operations, resources

Atomic Red Team Tests

Test 1 Simulate VPN Infrastructure Use - DNS Enumeration of Anonymization Services
windows

Generates DNS lookups to known VPN and anonymization service domains, simulating reconnaissance or infrastructure selection activity observable via Sysmon Event 22 DNS query telemetry.

Command

powershell
foreach ($domain in @('surfshark.com','protonvpn.com','nordvpn.com','mullvad.net','ivpn.net','torproject.org')) { Resolve-DnsName $domain -Type A -ErrorAction SilentlyContinue | Select-Object Name, IPAddress; Start-Sleep -Milliseconds 500 }

Cleanup

powershell
Clear-DnsClientCache

Expected Telemetry

Sysmon Event ID 22 (DnsQuery) entries for each queried domain showing QueryName, QueryResults, and the initiating PowerShell process. Also visible in DeviceNetworkEvents (ActionType: DnsQueryResponse) in Microsoft Defender for Endpoint.

Expected Detection

DNS hunting query should flag the workstation resolving 5+ anonymization service domains in a single session. Main detection may not fire unless HTTP connections follow the DNS queries.

Test 2 Simulate Authentication from VPS Infrastructure via Proxied HTTP Request
windows

Simulates an adversary using acquired VPS infrastructure by making authenticated HTTP requests through a local proxy, generating authentication events with non-corporate source IP context. Requires a SOCKS proxy or HTTP proxy on a cloud-hosted system.

Command

powershell
# Requires proxy endpoint — substitute with actual proxy IP:port
$ProxyAddress = "http://YOUR_CLOUD_VPS_IP:8080"
$Proxy = New-Object System.Net.WebProxy($ProxyAddress, $true)
$WebClient = New-Object System.Net.WebClient
$WebClient.Proxy = $Proxy
$WebClient.Headers.Add('User-Agent', 'python-requests/2.28.0')
try { $result = $WebClient.DownloadString('https://login.microsoftonline.com') } catch { $_.Exception.Message }

Cleanup

powershell
$WebClient.Dispose()

Expected Telemetry

Network connection event from the endpoint to the proxy IP. If authentication proceeds through the proxy, AADSignInLogs will record the VPS IP as the source. Sysmon Event 3 (NetworkConnect) visible for the outbound proxy connection.

Expected Detection

If the VPS IP falls within a known hosting ASN (DigitalOcean, Hetzner, etc.), the KQL query will flag the authentication. The automated user agent 'python-requests' also elevates suspicion score.

Test 3 Cloud Infrastructure Provisioning via Azure CLI (Adversary Infrastructure Simulation)
linux

Simulates adversary provisioning of attack infrastructure within a cloud environment using Azure CLI. Creates a small Linux VM in a non-primary region with a public IP address, mirroring Kimsuky/APT29-style infrastructure setup. Requires Azure CLI authenticated to a test subscription.

Command

bash
# Run from a cloud-hosted test system to simulate infrastructure acquisition
az group create --name argus-infra-test-rg --location eastus2 --output none
az vm create \
  --resource-group argus-infra-test-rg \
  --name argus-test-vps \
  --image Ubuntu2204 \
  --size Standard_B1s \
  --admin-username testadmin \
  --generate-ssh-keys \
  --public-ip-sku Standard \
  --output table
az vm show --resource-group argus-infra-test-rg --name argus-test-vps --show-details --query publicIps -o tsv

Cleanup

bash
az group delete --name argus-infra-test-rg --yes --no-wait

Expected Telemetry

Azure Activity Log entries: Microsoft.Compute/virtualMachines/write, Microsoft.Network/publicIPAddresses/write, Microsoft.Resources/deployments/write. Visible in AzureActivity table in Sentinel and azure:activity sourcetype in Splunk. Also triggers Azure Security Center alerts if Defender for Cloud is enabled.

Expected Detection

Azure resource provisioning hunting query should identify VM creation and public IP allocation from the same caller within a short window. If provisioning occurs from a non-corporate IP (e.g., personal laptop or cloud shell), correlates with T1583.003 VPS acquisition pattern.

Related Detections