/cards/ once it crosses the publish bar. Status: draft. Supersedes version 1.Storm-0940/UNC7228 ARTEX agentic intrusions: ConnectWise M365 abuse plus wider on-prem and cloud TTPs
Stolen ConnectWise Cloud Backup app credentials were used against 2,250+ M365 tenants from Oct 15. GTIG links the same ARTEX tooling to intrusions with confirmed data theft since late August. Today: hunt the ConnectWise app identities and the Entra audit log back to Oct 1, then run the MySQL-webshell and webhook.site egress hunts.
Triage: Microsoft and Huntress confirm privileged access in M365 tenants via a vendor app identity in under three hours [S2][S4]. Any tenant that used ConnectWise Cloud Backup should treat a hit as an active compromise.
Microsoft [S2] and GTIG/Mandiant [S1] are primary sources for the core claims, and Huntress [S4] corroborates from its own telemetry. Two newer reports (CrowdStrike on Vapor Panda; WorkOS) arrived only as truncated change notes and are not folded in.
Changed since version 1
- Did not fold in the CrowdStrike Vapor Panda report (200+ organizations, forged admin tokens; change note 2026-11-02). It arrived truncated without a numbered source, so it is in open_questions and reenter_when.
- Did not fold in the WorkOS ARTEX report (CRM and customer communication data accessed; change note 2026-11-03). It is unsourced and post-dates the brief, so it is in open_questions and reenter_when.
- Flagged the published card's Sophos claim (ex-customers affected) as unsourced in this thread; moved to open_questions.
- Replaced the prior coverage-status list with per-category coverage_checks; no coverage claims are made.
- Added an eradicate section and AD CS enrollment monitoring from [S1].
- Detect, verify, scope, contain and triage are unchanged.
What happened
- Microsoft attributes the ConnectWise Cloud Backup supply chain compromise to China-aligned Storm-0940, which used the ARTEX agentic AI framework [S2].
- The actor password-sprayed with 151,000+ failures between Oct 10 and 14. From Oct 15 it used stolen ConnectWise app identities to authenticate to 2,250+ M365 tenants [S2].
- Follow-on Graph activity included reconnaissance, app credential additions for persistence, and privileged role changes, including an app self-assigning Global Administrator [S2].
- Huntress saw the activity across ~1,000 monitored tenants. The Teams service principal assigned itself Global Administrator, roles were granted to sibling principals and the original principal was deleted. Privileged access was reached in under three hours [S4].
- GTIG/Mandiant report that PRC-nexus UNC7228 (overlaps Storm-0940) and financially motivated groups have used ARTEX, PentAGI, CAIRN and Hexstrike in real intrusions since late August 2026, with confirmed compromise and data theft [S1].
- With supplied valid credentials, ARTEX probed Azure/AWS permissions, turned MySQL general_log into JSP webshells, abused Kudu APIs, ran Kerberoasting and DCSync, and posted output to rotating webhook.site URLs via curl [S1].
Timeline
| 2026-08 (late) | Agentic-framework intrusions, including ARTEX, begin per GTIG S1 |
| 2026-10-10 to 2026-10-14 | Password spray against ConnectWise (151,000+ failures) S2 |
| 2026-10-15 | Stolen ConnectWise app identities authenticate to 2,250+ M365 tenants S2 |
| 2026-10-15 | Huntress observes privilege escalation in ~1,000 monitored tenants in under three hours S4 |
| 2026-10-21 | Microsoft publishes Storm-0940 / ARTEX attribution S2 |
| 2026-11-02 | GTIG/Mandiant publish wider ARTEX, PentAGI and CAIRN intrusion TTPs S1 |
Detect
Entra app credential, role and principal changes · Entra ID directory audit logs
index=* earliest="10/01/2026:00:00:00" operationName IN ("Add service principal credentials","Update application – Certificates and secrets management","Add member to role","Add app role assignment to service principal","Remove service principal","Consent to application") | stats count min(_time) as first max(_time) as last values(operationName) as ops by initiatedBy.app.displayName, initiatedBy.app.servicePrincipalId | sort - countFROM logs-* | WHERE @timestamp >= "2026-10-01T00:00:00Z" AND event.action IN ("Add service principal credentials", "Update application – Certificates and secrets management", "Add member to role", "Add app role assignment to service principal", "Remove service principal", "Consent to application") | STATS count = COUNT(*), first = MIN(@timestamp), last = MAX(@timestamp), ops = VALUES(event.action) BY azure.auditlogs.properties.initiated_by.app.displayName, azure.auditlogs.properties.initiated_by.app.servicePrincipalId | SORT count DESCA hit means: A service principal added credentials, granted roles (including to itself) or deleted a principal. A vendor or Teams principal assigning itself Global Administrator matches the pattern in [S2][S4].
Vendor app sign-ins with scripted user agents or listed IPs · Entra service principal sign-in logs; Microsoft Graph activity logs
index=* earliest="10/01/2026:00:00:00" (userAgent="Python-urllib/3.12*" OR userAgent="curl/7.88.1*" OR userAgent="python-requests/2.31*" OR ipAddress="144.172.64.*") | stats count min(_time) as first max(_time) as last values(userAgent) as ua values(ipAddress) as ip by appId, servicePrincipalName
FROM logs-* | WHERE @timestamp >= "2026-10-01T00:00:00Z" AND (user_agent.original LIKE "Python-urllib/3.12*" OR user_agent.original LIKE "curl/7.88.1*" OR user_agent.original LIKE "python-requests/2.31*" OR TO_STRING(source.ip) LIKE "144.172.64.*") | STATS count = COUNT(*), first = MIN(@timestamp), last = MAX(@timestamp), ua = VALUES(user_agent.original), ip = VALUES(source.ip) BY azure.signinlogs.properties.app_id, azure.signinlogs.properties.service_principal_name
A hit means: An app identity authenticated or called Graph with tooling other than the ConnectWise baseline (kiota-dotnet), or from the reported IP range [S4]. Check the appId against the ConnectWise IDs in [S2].
MySQL general_log webshell and ARTEX artifacts · MySQL general/query log; web server access log; EDR file creation
index=* ("SET GLOBAL general_log_file" OR "cl1217.jsp" OR "f1219a.jsp" OR "z1219.jsp" OR "artex-probe-" OR "ArtexProbe") | stats count min(_time) as first max(_time) as last values(source) as sources by hostFROM logs-* | WHERE message LIKE "*SET GLOBAL general_log_file*" OR message LIKE "*cl1217.jsp*" OR message LIKE "*f1219a.jsp*" OR message LIKE "*z1219.jsp*" OR message LIKE "*artex-probe-*" OR message LIKE "*ArtexProbe*" OR url.path LIKE "*cl1217.jsp*" OR url.path LIKE "*f1219a.jsp*" OR url.path LIKE "*z1219.jsp*" OR file.path LIKE "*cl1217.jsp*" OR file.path LIKE "*f1219a.jsp*" OR file.path LIKE "*z1219.jsp*" OR file.path LIKE "*artex-probe-*" OR process.command_line LIKE "*ArtexProbe*" OR process.command_line LIKE "*artex-probe-*" | STATS count = COUNT(*), first = MIN(@timestamp), last = MAX(@timestamp), sources = VALUES(log.file.path) BY host.name
A hit means: The MySQL log was redirected to a file, a reported webshell name was requested, or ARTEX naming artifacts were created. Any of these warrants host-level investigation [S1].
Server egress to webhook.site · Proxy, DNS, network flow
index=* ("webhook.site" OR query="*webhook.site" OR url="*webhook.site*") | stats count dc(url) as distinct_urls values(http_user_agent) as ua min(_time) as first max(_time) as last by srcFROM logs-* | WHERE message LIKE "*webhook.site*" OR dns.question.name LIKE "*webhook.site" OR url.full LIKE "*webhook.site*" OR url.domain LIKE "*webhook.site" OR destination.domain LIKE "*webhook.site" | STATS count = COUNT(*), distinct_urls = COUNT_DISTINCT(url.full), ua = VALUES(user_agent.original), first = MIN(@timestamp), last = MAX(@timestamp) BY source.ip
A hit means: A host contacted webhook.site. Many distinct URLs from a server, especially with a curl user agent, matches the C2 and exfil pattern in [S1].
Verify
- Confirm the appId belongs to a ConnectWise Cloud Backup identity listed in [S2], and that the activity is not a ConnectWise-initiated change on record.
- Benign look-alike: admins or automation adding app secrets during routine rotation. Check the initiator, ticket and timing.
- Benign look-alike: developers or CI jobs using curl or Python against Graph or webhook.site for testing. A server or database host doing this is not routine.
- Benign look-alike: DBAs enabling general_log for troubleshooting. A log file path ending in .jsp in a web-served directory is not benign [S1].
- For short bursts of cloud API calls (GTIG cites 27 events in 23 seconds), compare against known scanners and IaC pipelines [S1].
Scope
Affected
- M365 tenants where ConnectWise Cloud Backup app identities were present [S2][S4]
- Environments where an attacker holds valid credentials: accounts, SAS tokens, service principals, Kudu publishing credentials, IAM keys [S1]
Only if
- Attacker holds valid credentials or a vendor app credential [S1][S2]
- Internet-exposed management interfaces (e.g., Azure Kudu/SCM) or application SQL APIs [S1]
Not affected if
None stated by the sources.
Enumerate
- All service principals and app registrations tied to ConnectWise, including credentials added since Oct 1 [S2]
- Every role assignment granted to a service principal since Oct 13 [S2][S4]
- Principals deleted since Oct 13; Huntress saw the original principal removed [S4]
- Internet-facing MySQL-backed web apps and Azure App Service/Kudu endpoints [S1]
- AWS key pairs, Elastic IPs and t3.micro instances created outside change records [S1]
- AD accounts created or reset with ArtexProbe-style names [S1]
Contain
- Preserve Entra sign-in, audit and Graph activity logs and CloudTrail before making changes. Default retention may not reach back to Oct 1.
- Disable or remove ConnectWise app identities and revoke their credentials and consents [S2]. Consent can be re-added later, but rotated secrets cannot be restored.
- Remove privileged roles from service principals that self-assigned or received them since Oct 13 [S4].
- Block server egress to webhook.site [S1].
- Image, then isolate, hosts with JSP webshells or ArtexProbe artifacts [S1].
- If DCSync is suspected, plan a double krbtgt reset [S1]. It invalidates Kerberos tickets domain-wide and cannot be undone.
Eradicate
- Remove app secrets and certificates added to application identities by the actor [S2][S4].
- Remove JSP webshells written via MySQL general_log, and reset general_log settings [S1].
- Delete ArtexProbe-named accounts and reset passwords the actor changed [S1].
- Delete actor-created AWS key pairs, Elastic IPs, instances and volumes [S1].
- Remove scripts staged via Kudu, and rotate Kudu publishing credentials [S1].
- Rotate credentials for Kerberoasted service accounts [S1].
Recover
- Before re-enabling any vendor app, confirm it has no added credentials and only the permissions the vendor documents.
- Validate role assignments against a known-good baseline.
- Monitor service principal sign-ins for non-baseline user agents and IPs [S4].
- Monitor control-plane API bursts, credential additions, account creation bursts and new webhook/OAST egress [S1].
- Monitor AD CS enrollment for privileged users or unexpected requesters [S1].
Re-enter the loop when
- CrowdStrike's Vapor Panda reporting (200+ organizations, forged admin tokens) is confirmed and adds new tokens, appIds or IoCs.
- WorkOS or another vendor confirms ARTEX use against SaaS apps holding customer data.
- Microsoft or ConnectWise updates the list of affected app IDs or the tenant count.
- GTIG publishes further IoCs or names additional exploited products beyond Weaver OA, Kudu and MySQL [S1].
- Any hunt hits on a tenant or host outside the ConnectWise footprint.
Debrief
- Record which ConnectWise identities existed, when they were removed, and the earliest and latest suspicious activity.
- Record log retention gaps that limited the lookback to Oct 1.
- Gap: the sources do not say how the ConnectWise app credential was first obtained beyond the password spray.
- Gap: the sources do not give remediation steps from ConnectWise itself.
- Gap: GTIG states UNC7228/Storm-0940 as overlap, not identity [S1].
Detection coverage — checked automatically
| Category | Source | Status |
|---|---|---|
| Vendor | Impacted vendor / CERT advisory | published — primary source among the thread's sources: https://www.microsoft.com/en-us/security/blog/2026/10/21/storm-0940-uses-artex-agentic-ai-connectwise-supply-chain-compromise/ |
| Government | CISA KEV | not checkable — no CVE: the catalog is keyed by CVE |
| EDR / endpoint VM | CrowdStrike blog | nothing found — no post names it among the feed's 10 newest items |
| EDR / endpoint VM | Microsoft Security blog | published — ARTEX abuse expands as cybercriminals target financial sector · Threat actors use agentic AI tooling to find and abuse exposed secrets (names ARTEX in the title; the feed text carries no CVE id) |
| EDR / endpoint VM | SentinelOne blog | published — The Good, the Bad and the Ugly in Cybersecurity - Week 43 (2026) (names the campaign in the title; the feed text carries no CVE id) |
| EDR / endpoint VM | SentinelOne Labs | nothing found — no post names it among the feed's 10 newest items |
| WAF / edge | Akamai blog | published — What ARTEX Reveals About Overlooked Attack Surfaces (names ARTEX in the title; the feed text carries no CVE id) |
| WAF / edge | Cloudflare WAF managed-ruleset changelog | nothing found — no post names it among the feed's 139 newest items |
| Cloud / container | Wiz blog | published — ARTEX in the Wild: Storm-0940 Expands Targeting of IT and Software Vendors (names ARTEX / Storm-0940 in the title; the feed text carries no CVE id) |
| IDS / research | Cisco Talos blog | published — Appraisal by AI: Model-driven victim prioritization in the VOLTA infostealer · NIK C2: The new AI-enabled command-and-control framework (names the campaign in the title; the feed text carries no CVE id) |
| Detection content | Elastic detection rules | published — 22 files name ARTEX / ConnectWise: rules/integrations/azure/discovery_graph_application_directory_reconnaissance.toml, rules/integrations/azure/credential_access_key_vault_secret_burst_by_application.toml, rules/_deprecated/exfiltration_rds_snapshot_export.toml, rules/integrations/aws/exfiltration_rds_snapshot_export.toml |
| Detection content | Elastic Security Labs | nothing found — no post names it among the feed's 102 newest items |
| Detection content | SigmaHQ rules | published — 18 files name ARTEX / ConnectWise: rules-compliance/other/netflow_cleartext_protocols.yml, rules/network/firewall/net_firewall_cleartext_protocols.yml, deprecated/windows/file_event_win_access_susp_teams.yml, rules/windows/file/file_event/file_event_win_hktl_nppspy.yml |
| Detection content | Splunk ESCU | published — 15 files name ARTEX / ConnectWise: stories/use_of_cleartext_protocols.yml, detections/network/protocols_passing_authentication_in_cleartext.yml, removed/investigations/get_notable_history.yml, removed/investigations/get_process_information_for_port_activity.yml |
| MSSP / IR firms | Arctic Wolf blog | nothing found — no post names it among the feed's 10 newest items |
| MSSP / IR firms | Huntress blog | published — AI, Scripts, Operator: Inside the ConnectWise Attack · ConnectWise (SkyKick) Vendor Credentials Abused in M365 Attacks · Inside an AhsayCBS Intrusion: Hidden Webshells, a CryptoMiner, and a C2 Implant (names ConnectWise in the title; the feed text carries no CVE id) |
| MSSP / IR firms | Rapid7 blog | published — Rapid7 Analysis: NetScaler intrusions chaining CVE-2026-88771 and CVE-2026-88779 (names the campaign in the title; the feed text carries no CVE id) |
| MSSP / IR firms | Sophos threat research | published — ConnectWise Cloud Backup application abused in cross-tenant token sweep (names ConnectWise in the title; the feed text carries no CVE id) |
| Research | Unit 42 | nothing found — no post names it among the feed's 15 newest items |
Checked automatically 2026-11-10 18:12Z from public sources: 12 published, 6 nothing found, 1 not machine-checkable, 0 failed. "Nothing found" means the public source answered and had nothing, as of that moment; a feed covers only its newest posts. Re-checked daily.
What a person would still look up (6)
| Identity / cloud (Entra, M365) | Whether the identity product alerts on service principal self-assignment of privileged roles and on credential additions to third-party apps. |
| EDR / endpoint | Whether the vendor has published detections for ARTEX artifacts, JSP webshells spawned by a Java servlet container, and curl download cradles on database servers. |
| Cloud / container | Whether CSPM/CDR content covers AWS DryRun permission-probe bursts, Kudu command execution and unexpected key pair or EIP creation. |
| WAF / edge | Whether managed rules flag requests to newly created .jsp files and high-volume directory fuzzing. |
| Proxy / DNS | Whether webhook.site and OAST domains are categorised and blockable for server segments. |
| Detection content (Sigma, Splunk ESCU, Elastic) | Read the matched rules themselves; keyword hits on ARTEX or ConnectWise may be unrelated. |
Exposure queries — generated automatically
No CVE in this campaign: nothing an internet scanner keys on. Scope by product in your own tool.
Banner spellings: a model read 2 from the NVD names and this card's text (former and marketing names, console titles); 0 matched something on Shodan and are shown above, the rest were dropped.
Scope every query in your own tool, never in a shared document: Shodan `net:<your_ranges>`, `org:"<your_org>"` or `hostname:<your_domain>` (or a Shodan Monitor network alert, which applies the scope for you); Censys `host.ip: <your_ranges>` or `host.dns.names: <your_domain>`. Then compare the banner version with the affected range. Generated automatically 2026-11-10 18:12Z from the CVE ids and NVD's CPE configurations, each Shodan query counted against Shodan itself; re-built daily with the coverage check.
Open questions
- CrowdStrike reports a Vapor Panda campaign using ARTEX against 200+ organizations with forged admin tokens. The note reached the pipeline truncated and unnumbered. Is Vapor Panda the same cluster as Storm-0940/UNC7228, and what are its IoCs?
- WorkOS reportedly says an attacker used ARTEX against an internal sales app, accessing CRM contacts and customer communication summaries. That note is dated 2026-11-03, after the brief date; confirm its date and content.
- The published card says ex-customers are affected too, per Sophos. No Sophos source is in this thread; confirm before keeping that line.
- Has ConnectWise published its own advisory or remediation guidance?
- Did GTIG observe ARTEX against financial-sector targets outside Asia?
Sources
- [S1] https://cloud.google.com/blog/topics/threat-intelligence/artex-and-friends-enter-agentic-offensive-frameworks/ · Google Cloud Blog
- [S2] https://www.microsoft.com/en-us/security/blog/2026/10/21/storm-0940-uses-artex-agentic-ai-connectwise-supply-chain-compromise/ · Microsoft
- [S3] https://thehackernews.com/2026/10/china-linked-hackers-use-artex-ai.html · The Hacker News
- [S4] https://www.huntress.com/blog/connectwise-attack-ai · Huntress
Public OSINT only. AI-generated by the pipeline; structure follows the DAIR model from Dynamic Incident Response (Joshua Wright). Published automatically once it crosses the publish bar.