SOC Prime Bias: High

20 May 2026 22:10 UTC

How Storm-2949 turned a compromised identity into a cloud-wide breach

Author Photo
SOC Prime Team linkedin icon Follow
How Storm-2949 turned a compromised identity into a cloud-wide breach
shield icon

Detection stack

  • AIDR
  • Alert
  • ETL
  • Query

Summary

Storm-2949 used social engineering and abuse of Self-Service Password Reset to compromise Microsoft Entra ID accounts. After obtaining privileged access, the threat actor used Azure management-plane actions to reach App Services, Key Vaults, Storage accounts, and SQL databases. Data was then exfiltrated from Microsoft 365, Azure storage, and other cloud resources. The intrusion later progressed to deployment of the ScreenConnect remote access tool on virtual machines to support further reconnaissance and credential theft.

Investigation

Microsoft analysts observed the attackers enumerating users and applications through the Microsoft Graph API with custom Python tooling. They retrieved publishing profiles from Azure App Services, extracted secrets from Key Vaults, changed firewall rules, and used the VMAccess extension to create local administrator accounts on virtual machines. In a later stage, a PowerShell script installed ScreenConnect, cleared logs, and disguised services to reduce visibility. The investigation linked this activity to three attacker-controlled IP addresses.

Mitigation

Organizations should enable MFA and require phishing-resistant authentication for privileged accounts. Azure RBAC permissions should be tightly restricted and monitored, especially Owner-level access to Key Vaults and App Services. Unnecessary Azure VM extensions should be disabled, and logging should be enforced for Run Command and VMAccess activity. Microsoft Defender for Cloud and Defender for Endpoint should also be enabled with tamper protection and block mode.

Response

Defenders should immediately block the identified malicious IP addresses and revoke compromised credentials. Passwords and MFA registrations for affected accounts should be reset, and all secrets stored in Key Vaults should be rotated. Security teams should also perform a full review of Azure RBAC assignments and remove excessive privileges. Detection rules should be updated to identify suspicious publishing profile requests, Key Vault secret access, and unexpected VM extension activity.

"graph TB %% Class definitions classDef action fill:#99ccff classDef tool fill:#ffcc99 classDef operator fill:#ff9900 %% Nodes u2013 Attack Steps action_phishing["<b>Action</b> – <b>T1566 Phishing</b><br/><b>Description</b>: Threat actor delivered targeted phishing messages that abused selfu2011service password reset to persuade users to approve MFA prompts and reveal valid credentials."] class action_phishing action action_valid_accounts["<b>Action</b> – <b>T1078 Valid Accounts</b><br/><b>Description</b>: Compromised credentials were used to sign in to Microsoft Entra ID and Azure subscriptions."] class action_valid_accounts action action_account_manipulation["<b>Action</b> – <b>T1098 Account Manipulation</b><br/><b>Description</b>: Attacker reset user passwords, removed existing MFA factors and enrolled a malicious authenticator to maintain persistence."] class action_account_manipulation action action_cloud_role_add["<b>Action</b> – <b>T1098.003 Additional Cloud Roles</b><br/><b>Description</b>: Privileged Azure RBAC roles were added to the compromised accounts."] class action_cloud_role_add action action_cloud_account_discovery["<b>Action</b> – <b>T1087.004 Cloud Account Discovery</b><br/><b>Description</b>: Microsoft Graph API was leveraged to enumerate users, applications and service principals."] class action_cloud_account_discovery action action_cloud_group_discovery["<b>Action</b> – <b>T1069.003 Cloud Groups Discovery</b><br/><b>Description</b>: Groups and role assignments were listed to map privileged memberships."] class action_cloud_group_discovery action action_cloud_service_discovery["<b>Action</b> – <b>T1526 Cloud Service Discovery</b><br/><b>Description</b>: Enumeration of Azure services such as App Service, Key Vault, Storage and SQL was performed."] class action_cloud_service_discovery action action_storage_object_discovery["<b>Action</b> – <b>T1619 Cloud Storage Object Discovery</b><br/><b>Description</b>: Blob containers in Azure Storage accounts were enumerated to locate data of interest."] class action_storage_object_discovery action action_keyvault_secret_access["<b>Action</b> – <b>T1555.006 Credentials from Password Stores</b><br/><b>Description</b>: Secrets were extracted from Azure Key Vaults, providing access to additional credentials."] class action_keyvault_secret_access action action_remote_services["<b>Action</b> – <b>T1021.007 Remote Services: Cloud Services</b><br/><b>Description</b>: Legitimate credentials were used to connect to Azure resources via native management interfaces."] class action_remote_services action tool_screenconnect["<b>Tool</b> – <b>Name</b>: ScreenConnect (ConnectWise Control)<br/><b>Description</b>: Remoteu2011access software deployed on compromised virtual machines to enable persistent control."] class tool_screenconnect tool action_automated_collection["<b>Action</b> – <b>T1119 Automated Collection</b><br/><b>Description</b>: Python scripts downloaded large numbers of files from OneDrive, SharePoint and Azure Storage."] class action_automated_collection action action_scripting_interpreter["<b>Action</b> – <b>T1059 Command and Scripting Interpreter</b><br/><b>Subu2011techniques</b>: Python (T1059.006), Windows Command Shell (T1059.003), Unix Shell (T1059.004)<br/><b>Description</b>: Scripts executed via Azure VM extensions to run commands, access instance metadata and exfiltrate data."] class action_scripting_interpreter action action_indicator_removal["<b>Action</b> – <b>T1070 Indicator Removal</b><br/><b>Description</b>: Windows event logs were cleared and temporary files deleted to hide activity."] class action_indicator_removal action action_file_deletion["<b>Action</b> – <b>T1070.004 File Deletion</b><br/><b>Description</b>: Artifacts on compromised VMs were removed to impede forensic analysis."] class action_file_deletion action action_obfuscation["<b>Action</b> – <b>T1027.005 Obfuscated Files or Information</b><br/><b>Description</b>: Security tooling was modified or obfuscated to evade detection mechanisms."] class action_obfuscation action action_defeat_defenses["<b>Action</b> – <b>T1562.008 Impair Defenses: Disable or Modify Cloud Logs</b><br/><b>Description</b>: Microsoft Defender AV was disabled on virtual machines and cloud logging was tampered with."] class action_defeat_defenses action %% Sequential connections action_phishing –>|leads_to| action_valid_accounts action_valid_accounts –>|leads_to| action_account_manipulation action_account_manipulation –>|leads_to| action_cloud_role_add action_cloud_role_add –>|leads_to| action_cloud_account_discovery action_cloud_account_discovery –>|leads_to| action_cloud_group_discovery action_cloud_group_discovery –>|leads_to| action_cloud_service_discovery action_cloud_service_discovery –>|leads_to| action_storage_object_discovery action_storage_object_discovery –>|leads_to| action_keyvault_secret_access action_keyvault_secret_access –>|leads_to| action_remote_services action_remote_services –>|uses| tool_screenconnect tool_screenconnect –>|enables| action_automated_collection action_automated_collection –>|uses| action_scripting_interpreter action_scripting_interpreter –>|enables| action_indicator_removal action_indicator_removal –>|includes| action_file_deletion action_file_deletion –>|includes| action_obfuscation action_obfuscation –>|supports| action_defeat_defenses %% Styling assignments class action_phishing,action_valid_accounts,action_account_manipulation,action_cloud_role_add,action_cloud_account_discovery,action_cloud_group_discovery,action_cloud_service_discovery,action_storage_object_discovery,action_keyvault_secret_access,action_remote_services,action_automated_collection,action_scripting_interpreter,action_indicator_removal,action_file_deletion,action_obfuscation,action_defeat_defenses action class tool_screenconnect tool "

Attack Flow

Simulation Execution

Prerequisite: The Telemetry & Baseline Pre‑flight Check must have passed.

  • Attack Narrative & Commands:

    An adversary who has obtained a valid Azure AD account (or default service principal) wants to exfiltrate application source code and database snapshots. The attacker performs the following steps entirely via Azure CLI, generating the exact operationName events the rule watches:

    1. Publish Web App XML – extracts the Web App configuration (including deployment credentials).
    2. Create a new Storage Account – provides a container for staging exfiltrated data.
    3. Add a firewall rule to the SQL server – opens the server to the attacker’s IP range, enabling direct data copy.

    Each step produces an Activity Log entry with operationName matching the rule’s whitelist, thereby triggering the detection.

  • Regression Test Script:

    #!/usr/bin/env bash
    # Prerequisite: az CLI is logged in with a compromised/valid Azure AD principal.
    set -euo pipefail
    
    # Variables – modify as needed for the test tenant
    RG="test-rg-$(date +%s)"
    WEBAPP="test-webapp-$RANDOM"
    STORAGE="teststorage$RANDOM"
    LOCATION="eastus"
    SQLSERVER="testsql$RANDOM"
    MY_IP=$(curl -s https://api.ipify.org)
    
    echo "=== Create resource group ==="
    az group create --name "$RG" --location "$LOCATION"
    
    echo "=== Deploy a dummy Web App ==="
    az appservice plan create --name "${WEBAPP}Plan" --resource-group "$RG" --sku B1 --is-linux
    az webapp create --resource-group "$RG" --plan "${WEBAPP}Plan" --name "$WEBAPP"
    
    echo "=== Publish XML configuration (triggers detection) ==="
    az webapp config backup create 
        --resource-group "$RG" 
        --webapp-name "$WEBAPP" 
        --backup-name "xmlbackup-$(date +%s)" 
        --output none
    
    echo "=== Create a Storage Account (triggers detection) ==="
    az storage account create 
        --name "$STORAGE" 
        --resource-group "$RG" 
        --location "$LOCATION" 
        --sku Standard_LRS 
        --kind StorageV2 
        --output none
    
    echo "=== Create a SQL Server (required for firewall rule) ==="
    az sql server create 
        --name "$SQLSERVER" 
        --resource-group "$RG" 
        --location "$LOCATION" 
        --admin-user "sqladmin" 
        --admin-password "P@ssw0rd1234!" 
        --output none
    
    echo "=== Add firewall rule to SQL Server (triggers detection) ==="
    az sql server firewall-rule create 
        --resource-group "$RG" 
        --server "$SQLSERVER" 
        --name "AllowMyIP" 
        --start-ip-address "$MY_IP" 
        --end-ip-address "$MY_IP" 
        --output none
    
    echo "=== Simulation complete. Check Azure Sentinel for alerts. ==="
  • Cleanup Commands:

    #!/usr/bin/env bash
    set -euo pipefail
    
    # Variables must match those used in the simulation script
    RG="test-rg-..."
    # If you kept the exact names from the earlier run, replace the placeholders accordingly.
    
    echo "=== Delete resource group and all contained resources ==="
    az group delete --name "$RG" --yes --no-wait
    echo "Cleanup initiated."