Article Banner

Storm-0940: ARTEX Agentic AI Drives a ConnectWise Supply Chain Compromise

Storm-0940, a China-linked threat group, turned a trusted software vendor into a doorway into hundreds of company accounts. The group abused a stolen login that belonged to a widely used backup application, then ran an automated attack tool to move faster than defenders could respond. Within minutes, it reached across thousands of business accounts at once.

Think of the attack like a burglar who steals a trusted contractor's master key, then hands that key to a tireless robot that tries every door in the building at the same time. The robot never slows down and works around the clock. Because the activity used a legitimate vendor's access, it blended in with normal business traffic and was hard to spot.

Organizations that rely on the affected application face unauthorized access to email, files, and administrator controls. In some cases the group gave itself top-level administrator rights and added secret passwords to other applications, creating hidden ways back in even after the first break-in was cleaned up. Companies across defense, finance, government, and technology were targeted, which makes a fast review of vendor access and account activity essential.

Hunting Controls & Observations

This campaign lives almost entirely in cloud identity and application activity, not on endpoints. Organizations can detect it through the following telemetry sources:

  • Identity & Access Controls: Microsoft Entra interactive and non-interactive sign-in logs, service principal sign-in logs, and Entra audit logs for directory role and application credential changes.
  • Cloud & SaaS Controls: Microsoft Graph activity logs, Microsoft Defender for Cloud Apps activity, and Microsoft Purview audit records for mail and file access.
  • Governance & Configuration Controls: OAuth application and service principal inventory, consent grants, and assigned API permissions for multi-tenant vendor applications.

Behavioral Indicators of Attack

Security teams should hunt for the following behaviors rather than static indicators alone:

  • A burst of failed sign-ins from a single hosting-provider address spread across many user accounts and tenants, consistent with password spraying at machine speed.
  • Non-interactive service principal sign-ins from new or unusual hosting infrastructure, using automation user agents such as Python or curl clients.
  • A single service principal authenticating into many customer tenants within a very short window, such as hundreds of sign-ins in a few minutes.
  • An enterprise application or service principal assigning itself, or another application, to a privileged directory role such as Global Administrator.
  • New client secrets or certificates added to enterprise applications, especially when a service principal performs the change instead of an administrator.
  • Vendor application activity that enumerates directory users, roles, and consent grants shortly after a role or credential change.
  • Time from first targeting to privileged access measured in hours rather than days, reflecting automated operation.

MITRE Enterprise ATT&CK Tactics and Techniques

Microsoft maps this campaign to the following techniques, listed in kill chain order. The password spraying mapping is inferred from the described behavior; the others are stated in the source report.

Controls' Observables

Identity & Access Controls

  • Failed-logon bursts from one address: High-volume authentication failures from a single hosting IP across many accounts and tenants.
    Related MITRE Techniques: T1110.003, T1078.004
    Detection Difficulty: MODERATE
  • Service principal sign-ins from new infrastructure: Successful non-interactive application sign-ins from unfamiliar autonomous systems and automation user agents.
    Related MITRE Techniques: T1078.004, T1528
    Detection Difficulty: MODERATE
  • Application self-assigns a privileged role: A service principal appears as the actor on an add-member-to-role event for an administrator role.
    Related MITRE Techniques: T1098.003
    Detection Difficulty: EASY
  • Application credential additions: New secrets or certificates added to enterprise applications, especially by a non-human actor.
    Related MITRE Techniques: T1098.001
    Detection Difficulty: EASY

Cloud & SaaS Controls

  • Cross-tenant token sweep: One application identity requesting Microsoft Graph tokens across many tenants in a short window.
    Related MITRE Techniques: T1528, T1078.004
    Detection Difficulty: MODERATE
  • Vendor application reconnaissance: A vendor application enumerating users, roles, and consent grants shortly after a role or credential change.
    Related MITRE Techniques: T1087.004, T1580
    Detection Difficulty: HARD

Governance & Configuration Controls

  • Over-permissioned multi-tenant apps: Vendor applications holding broad Graph permissions and standing consent across the directory.
    Related MITRE Techniques: T1195, T1098.001
    Detection Difficulty: EASY
  • Unexpected consent and permission changes: Additions to application role assignments or API permissions outside a change window.
    Related MITRE Techniques: T1098.003, T1098.001
    Detection Difficulty: MODERATE

Insights and Recommendation

Organizations compromised in this campaign face unauthorized access to email and files through Microsoft Graph, self-granted Global Administrator rights, and hidden application credentials that persist after the initial access is removed. Microsoft reports that the group reached privileged access at many organizations in under three hours and targeted sectors including aerospace and defense, energy, financial services, government, legal, manufacturing, and technology. The presence of the affected application or a successful sign-in does not by itself confirm that data was accessed or exfiltrated, so scoped investigation matters.

Security teams should keep affected ConnectWise connections disabled until the vendor issues formal restoration guidance, and should preserve the enterprise applications rather than deleting them first so audit evidence survives. Review Entra audit logs from at least October 1, 2026 for directory role assignments and credential additions where the actor is a service principal (T1098.003, T1098.001), and revoke any unexpected secrets or certificates. Hunt service principal sign-in logs for authentication from the listed addresses and from unfamiliar autonomous systems and user agents (T1078.004), and investigate activity beyond the published indicators. Apply least privilege to multi-tenant application permissions and consent grants, and alert on any application that assigns itself a directory role.

As of October 22, 2026, AlienVault OTX links 144.172.64.99 and 144.172.64.128 to this campaign across 13 and 15 community threat reports, and GreyNoise shows neither address scanning the wider internet, consistent with targeted cloud authentication abuse rather than broad scanning.

Source and Credits

This summary is based on Microsoft Security's research article "Storm-0940 uses ARTEX agentic AI in ConnectWise supply chain compromise" published on October 21, 2026.

Live-status and network-ownership annotations in the indicator list, and the dark-web exposure note above, come from Darknet CTI corroboration (Focused Hunts), a secondary source drawn from AlienVault OTX, AbuseIPDB, and GreyNoise and checked on October 22, 2026.

Threat Hunting IOCs & Queries

Known Indicators of Compromise

The source report provides network and application indicators but no file hashes or domains. Infrastructure attribution is kept separate by source: network ownership (ASN) is from AlienVault OTX, and hosting-versus-residential usage type is from AbuseIPDB.

  • IP Addresses:
    • 144.172.64.99: password-spray source, matched to a ConnectWise indicator (AbuseIPDB 11% confidence, 2 reports, usage type Data Center/Web Hosting, ISP FranTech Solutions, as of 2026-10-22; AlienVault OTX 13 pulses and ASN AS8100 QuadraNet Enterprises LLC, as of 2026-10-22)
    • 144.172.64.128: cross-tenant sign-ins and Graph activity in customer tenants (AbuseIPDB 21% confidence, 5 reports, hostname 128.64.172.144.static.cloudzy.com, as of 2026-10-22; AlienVault OTX 15 pulses, as of 2026-10-22)
    • 144.172.64.60: related sign-in activity (AbuseIPDB 1% confidence, 1 report, as of 2026-10-22)
    • 187.15.88.186, 187.15.90.217, 187.15.89.186: VPN addresses (Packethub), transient, relevant to October 15 to 16 (AbuseIPDB 0 reports, as of 2026-10-22)
  • Automation User Agents: Python-urllib/3.12, python-requests/2.31.0, python-requests/2.34.2, curl/7.88.1, azure-toolkit/1.0. These are generic, so correlate them with the addresses above rather than alerting on them alone.
  • Affected Application IDs (legitimate ConnectWise apps that were abused): 506e08f9-6e9a-4da4-942b-a099a03644ae (ConnectWise Cloud Backup), 24205314-2b89-4e07-a2a4-579e898a5640 (ConnectWise - MS Teams), 0de14c77-b9b0-4137-9360-34878a929827 (ConnectWise - MS Graph).

Indicators are current as of the source report dated October 21, 2026. Live-status and network annotations reflect darknet MCP corroboration on October 22, 2026, a second source distinct from the cited report. Threat actors rotate infrastructure often, so the behavioral queries below are the durable detection.

Password-Spray Burst From a Single Address

Priority: High - observed in this campaign, Credential Access impact, Tier 1 identity telemetry.
Behavior Targeted: A single hosting address generating a burst of failed sign-ins across many distinct user accounts, the signature of machine-speed password spraying.
MITRE ATT&CK: T1110.003, T1078.004
Telemetry Required: Microsoft Entra sign-in logs (SigninLogs). For app-based spraying, repeat against AADNonInteractiveUserSignInLogs.
Platform: Microsoft Defender XDR / Sentinel only. Entra sign-in telemetry lives in Microsoft's cloud, so there is no Splunk counterpart unless these logs are separately forwarded.
Expected Results: One or a few hosting addresses with high failure counts spanning dozens of accounts in a short window.
False Positive Likelihood: MEDIUM - misconfigured clients, VPN egress points, and legacy authentication can also cause failure bursts.
Tuning Guidance: Raise or lower the DistinctUsers and FailedAttempts thresholds to match tenant size, and exclude known corporate egress addresses. Widen the time window during active incident review.

Microsoft KQL Query (Defender/Sentinel)

SigninLogs
| where TimeGenerated > ago(14d)
| where ResultType != "0"
| summarize FailedAttempts = count(), DistinctUsers = dcount(UserPrincipalName), FirstSeen = min(TimeGenerated), LastSeen = max(TimeGenerated) by IPAddress, AutonomousSystemNumber
| where DistinctUsers >= 20 and FailedAttempts >= 100
| order by FailedAttempts desc

Application Self-Assigns a Privileged Directory Role

Priority: High - observed in this campaign, Privilege Escalation, and an application acting as the role-assignment actor is rarely benign.
Behavior Targeted: A service principal appears as the actor that adds a member to a privileged directory role such as Global Administrator.
MITRE ATT&CK: T1098.003
Telemetry Required: Microsoft Entra audit logs (AuditLogs), directory role management events.
Platform: Microsoft Defender XDR / Sentinel only. Entra directory audit events are Microsoft cloud telemetry with no Splunk-native source.
Expected Results: Role additions where the initiating actor is an application rather than a user, targeting an administrator role.
False Positive Likelihood: LOW - most legitimate role assignments are performed by users or by governance tools you can allowlist.
Tuning Guidance: Allowlist approved identity-governance service principals, and broaden the RoleAdded match to include any role your tenant treats as privileged.

Microsoft KQL Query (Defender/Sentinel)

AuditLogs
| where TimeGenerated > ago(14d)
| where OperationName in ("Add member to role", "Add eligible member to role", "Add member to role in PIM requested (permanent)")
| where Result == "success"
| extend ActorApp = tostring(InitiatedBy.app.displayName), ActorAppId = tostring(InitiatedBy.app.appId)
| where isnotempty(ActorApp)
| mv-expand TargetResources
| extend RoleAdded = tostring(TargetResources.displayName)
| where RoleAdded has_any ("Administrator", "Global Administrator", "Privileged Role Administrator", "Application Administrator")
| project TimeGenerated, OperationName, ActorApp, ActorAppId, RoleAdded, Result
| order by TimeGenerated desc

Application Credential Additions as a Backdoor

Priority: High - observed in this campaign, Persistence, and a durable backdoor that outlives the initial access.
Behavior Targeted: New client secrets or certificates added to applications or service principals, especially when the actor is an application rather than an administrator.
MITRE ATT&CK: T1098.001
Telemetry Required: Microsoft Entra audit logs (AuditLogs), application and service principal credential events.
Platform: Microsoft Defender XDR / Sentinel only. Application credential changes are recorded only in Entra audit telemetry.
Expected Results: Credential-add events on enterprise applications, with the actor and target application surfaced for review.
False Positive Likelihood: MEDIUM - routine administrator secret rotation and CI/CD automation also add credentials.
Tuning Guidance: Focus first on rows where ActorApp is populated, allowlist known automation accounts, and compare target applications against an approved inventory.

Microsoft KQL Query (Defender/Sentinel)

AuditLogs
| where TimeGenerated > ago(14d)
| where Result == "success"
| where OperationName has_any ("Add service principal credentials", "certificates and secrets", "Update service principal", "Add service principal")
| extend ActorApp = tostring(InitiatedBy.app.displayName), ActorUser = tostring(InitiatedBy.user.userPrincipalName)
| mv-expand TargetResources
| extend TargetApp = tostring(TargetResources.displayName)
| project TimeGenerated, OperationName, ActorApp, ActorUser, TargetApp, Result
| order by TimeGenerated desc

Service Principal Sign-Ins From New Infrastructure

Priority: Medium - observed in this campaign, Initial Access through a trusted identity, and strong fan-out signal across resources.
Behavior Targeted: An address driving many successful service principal sign-ins across multiple resources, the pattern of an automated cross-tenant token sweep.
MITRE ATT&CK: T1078.004, T1528
Telemetry Required: Microsoft Entra service principal sign-in logs (AADServicePrincipalSignInLogs).
Platform: Microsoft Defender XDR / Sentinel only. Service principal sign-in logs are Entra cloud telemetry with no Splunk-native equivalent.
Expected Results: Hosting addresses with high successful sign-in counts spanning several resources in a short period.
False Positive Likelihood: MEDIUM - legitimate vendor integrations and backup services also sign in broadly; baseline their addresses first.
Tuning Guidance: Adjust the SignIns and DistinctResources thresholds to tenant scale, and exclude the autonomous systems of sanctioned SaaS vendors.

Microsoft KQL Query (Defender/Sentinel)

AADServicePrincipalSignInLogs
| where TimeGenerated > ago(14d)
| where ResultType == "0"
| summarize SignIns = count(), DistinctResources = dcount(ResourceDisplayName), Apps = make_set(ServicePrincipalName, 10), FirstSeen = min(TimeGenerated), LastSeen = max(TimeGenerated) by IPAddress, AutonomousSystemNumber
| where SignIns >= 50 and DistinctResources >= 5
| order by SignIns desc

IOC Sweep: Storm-0940 ConnectWise Infrastructure

Priority: Medium - direct indicator match for triage, kept distinct from the behavioral hunts above.
Behavior Targeted: Any sign-in, user or service principal, from the addresses attributed to this campaign.
MITRE ATT&CK: T1078.004
Telemetry Required: Microsoft Entra sign-in logs (SigninLogs) and service principal sign-in logs (AADServicePrincipalSignInLogs).
Platform: Microsoft Defender XDR / Sentinel only. Both sign-in tables are Entra cloud telemetry with no Splunk-native source.
Expected Results: Any authentication from the listed addresses, which warrants immediate scoping.
False Positive Likelihood: LOW - these are dedicated hosting addresses attributed to the campaign, though infrastructure is rotated.
Tuning Guidance: Add new addresses as they are published, and extend the window to match the retention of your sign-in logs.

Microsoft KQL Query (Defender/Sentinel)

let attackerIPs = dynamic(["144.172.64.99", "144.172.64.60", "144.172.64.128"]);
union
  (SigninLogs | where TimeGenerated > ago(14d) | where IPAddress in (attackerIPs) | extend Source = "SigninLogs", Principal = UserPrincipalName, App = AppDisplayName),
  (AADServicePrincipalSignInLogs | where TimeGenerated > ago(14d) | where IPAddress in (attackerIPs) | extend Source = "AADServicePrincipalSignInLogs", Principal = ServicePrincipalName, App = ResourceDisplayName)
| project TimeGenerated, Source, IPAddress, Principal, App, ResultType
| order by TimeGenerated desc

Note: These queries were generated with AI assistance and are a starting point for threat hunting and detection rule considerations.

Back to Hunting off the Red