T1583 Sumo Logic CSE · Sumo

Detect Acquire Infrastructure in Sumo Logic CSE

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.

MITRE ATT&CK

Tactic
Resource Development
Technique
T1583 Acquire Infrastructure
Canonical reference
https://attack.mitre.org/techniques/T1583/

Sumo Detection Query

Sumo Logic CSE (Sumo)
sql
_sourceCategory="windows/security" ("EventCode=4624" OR "EventCode=4625" OR "EventCode=4648")
| parse "EventCode=*\n" as event_code
| parse "Account Name:\t*\n" as account_name nodrop
| parse "Account Name:\t\t*\n" as account_name nodrop
| parse "Network Information:\n\t\tWorkstation Name:\t*\n" as workstation_name nodrop
| parse "Network Information:\n\t\tSource Network Address:\t*\n" as src_ip nodrop
| parse "Source Network Address:\t*\n" as src_ip nodrop
| where src_ip != "-" AND src_ip != "127.0.0.1" AND src_ip != "::1" AND !isNull(src_ip)
| where !(src_ip matches "10.*" OR src_ip matches "192.168.*" OR src_ip matches "172.16.*" OR src_ip matches "172.17.*" OR src_ip matches "172.18.*" OR src_ip matches "172.19.*" OR src_ip matches "172.20.*" OR src_ip matches "172.21.*" OR src_ip matches "172.22.*" OR src_ip matches "172.23.*" OR src_ip matches "172.24.*" OR src_ip matches "172.25.*" OR src_ip matches "172.26.*" OR src_ip matches "172.27.*" OR src_ip matches "172.28.*" OR src_ip matches "172.29.*" OR src_ip matches "172.30.*" OR src_ip matches "172.31.*")
| eval infra_category = if(src_ip matches "185.220.*" OR src_ip matches "185.209.*" OR src_ip matches "45.83.*", "known_tor_exit_or_proxy",
    if(src_ip matches "167.71.*" OR src_ip matches "104.248.*" OR src_ip matches "68.183.*" OR src_ip matches "159.65.*" OR src_ip matches "138.197.*", "digitalocean",
    if(src_ip matches "95.217.*" OR src_ip matches "116.202.*" OR src_ip matches "135.181.*" OR src_ip matches "65.109.*" OR src_ip matches "5.9.*", "hetzner",
    if(src_ip matches "51.77.*" OR src_ip matches "51.68.*" OR src_ip matches "178.32.*" OR src_ip matches "54.36.*" OR src_ip matches "141.95.*", "ovh",
    if(src_ip matches "45.32.*" OR src_ip matches "66.175.*" OR src_ip matches "104.156.*" OR src_ip matches "207.246.*", "vultr",
    if(src_ip matches "194.5.*" OR src_ip matches "93.115.*" OR src_ip matches "92.223.*", "m247_bulletproof", "unknown"))))))
| where infra_category != "unknown"
| eval event_desc = if(event_code == "4624", "Successful Logon",
    if(event_code == "4625", "Failed Logon",
    if(event_code == "4648", "Explicit Credential Logon", "Unknown")))
| eval threat_score = if(infra_category == "known_tor_exit_or_proxy", 9,
    if(infra_category == "m247_bulletproof", 8,
    if(infra_category == "digitalocean", 6,
    if(infra_category == "hetzner", 6,
    if(infra_category == "ovh", 5,
    if(infra_category == "vultr", 5, 3))))))
| stats count as event_count,
    values(event_desc) as event_types,
    values(src_ip) as source_ips,
    min(_messageTime) as first_seen,
    max(_messageTime) as last_seen
    by account_name, infra_category, workstation_name, threat_score
| where event_count >= 1 AND account_name != "ANONYMOUS LOGON" AND !isNull(account_name)
| sort by threat_score desc, event_count desc
| formatDate(toLong(first_seen), "yyyy-MM-dd HH:mm:ss") as first_seen_fmt
| formatDate(toLong(last_seen), "yyyy-MM-dd HH:mm:ss") as last_seen_fmt
| fields account_name, infra_category, event_count, source_ips, event_types, threat_score, first_seen_fmt, last_seen_fmt, workstation_name
high severity medium confidence

Sumo Logic query detecting Windows authentication events (successful logon 4624, failed logon 4625, explicit credential use 4648) originating from external IP ranges associated with known adversary-acquired infrastructure. Parses Windows Security Event Log fields for source IPs and classifies them against hosting provider prefix lists covering Tor exit nodes, M247 bulletproof hosting, DigitalOcean, Hetzner, OVH, and Vultr. Assigns threat scores by provider risk tier and surfaces accounts authenticating from these ranges.

Data Sources

Sumo Logic Cloud SIEMWindows Security Event Logs collected via Sumo Logic Installed Collector or Windows Event Log SourceActive Directory domain controller security logsSumo Logic CSE normalized authentication schema

Required Tables

_sourceCategory=windows/security

False Positives & Tuning

  • Employees using commercial VPN services with exit nodes in DigitalOcean or Hetzner ranges — particularly prevalent among staff in regions with internet censorship or those using privacy tools for legitimate personal security.
  • Automated backup or synchronization agents deployed on cloud VPS instances that authenticate to on-premises Active Directory to access shared file resources or databases.
  • Software-as-a-Service vendors whose integration platforms are hosted on OVH or Vultr and authenticate against customer directories using SAML federation or OAuth — the source IP may appear as a VPS range.

Other platforms for T1583


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 1 Simulate 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 2 Simulate 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 3 Cloud 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

Related Techniques

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