A supply-chain attack against ConnectWise — one of the most widely deployed MSP/TSP platforms in the managed services ecosystem — has confirmed impact across hundreds of downstream customers. According to reporting from CyberScoop, attackers obtained a sensitive ConnectWise API secret and used it to access connected Microsoft 365 applications without tripping the usual authentication barriers. There was no phish, no password spray, no brute force. The attackers simply walked in the front door using a legitimate, trusted credential.
This is the nightmare scenario for every organization that delegates management plane access to a third-party MSP tool: the blast radius of one vendor's credential compromise extends directly into your tenant. If your organization uses ConnectWise — particularly its cloud backup or M365-integrated offerings — or if your MSP does, you should treat this as an active incident requiring immediate verification, not a news item to read and file away.
Technical Analysis
What Happened
The attack chain, as described in the reporting, follows a pattern we have seen repeatedly in SaaS supply-chain incidents and that maps directly to MITRE ATT&CK techniques T1550 (Use Alternate Authentication Material) and T1528 (Steal Application Access Token):
- Credential compromise at the vendor layer. Attackers obtained a sensitive ConnectWise API secret — a long-lived credential used by ConnectWise services to authenticate to customer Microsoft 365 tenants via registered enterprise applications/service principals.
- Trusted-path access. Because M365-integrated backup and management platforms operate through OAuth app consent and service principals with broad Graph API permissions (commonly
Mail.Read,Sites.ReadWrite.All,Directory.Read.All, or fullfull_access_as_appfor Exchange), possession of the secret allowed attackers to authenticate as the legitimate application. No MFA prompt, no conditional access challenge for user sign-ins, no impossible travel alert — daemon/app-only authentication flows are explicitly designed to run unattended. - Unimpeded access to connected tenants. With app-only tokens minted using the stolen secret, attackers could access the data and workloads the ConnectWise application was consented to touch: mailboxes, SharePoint/OneDrive content, directory data, and potentially backup stores.
Why App-Only OAuth Abuse Is So Dangerous
From a defender's perspective, this attack class has three properties that make it brutal:
- Legitimate-looking telemetry. The service principal doing the reading is the ConnectWise app you approved. Without baseline behavioral analytics on what that app normally does, malicious use of its own credentials looks identical to normal operation in most log schemas.
- No interactive sign-in events. App-only token acquisition against
login.microsoftonline.comwith a client secret generatesServicePrincipalSignIn/ non-interactive events that many tenants do not alert on, and downstream Graph API calls surface primarily in audit data (Unified Audit Log, MicrosoftGraphActivityLogs) rather than classic identity detections. - Broad, pre-consented scope. Attackers inherit whatever permissions the app was granted. Backup platforms routinely hold some of the most permissive consent grants in an entire tenant.
Exploitation Status
This is confirmed active exploitation in the wild, with hundreds of ConnectWise customers confirmed impacted per the CyberScoop reporting. No CVE has been assigned — this is a credential/secret compromise, not a software vulnerability — so there is no CISA KEV entry and no patch in the traditional sense. The remediation is credential revocation, permission review, and tenant-level forensic validation. Organizations should monitor ConnectWise's official security advisories and trust center for confirmed scope, affected product lines, and vendor-directed rotation procedures.
Detection & Response
Your detection strategy here rests on four pillars: (1) auditing the service principals in your tenant and their consent grants, (2) hunting for anomalous app-only authentication and Graph API activity attributed to the ConnectWise app or any service principal you don't recognize, (3) reviewing mailbox and SharePoint access for exfiltration patterns, and (4) validating that no new credentials or permissions were added to the app registration during the exposure window.
Sigma Rules
---
title: Suspicious App-Only Token Acquisition by Third-Party Service Principal
id: 8b3f2e41-5c7a-4d19-bf62-9a1c4e7d3f08
status: experimental
description: Detects non-interactive service principal sign-ins from unusual network locations or ASNs, consistent with abuse of a stolen API secret or client credential as seen in the ConnectWise supply-chain incident.
references:
- https://cyberscoop.com/connectwise-cloud-backup-supply-chain-attack/
- https://attack.mitre.org/techniques/T1550/
- https://attack.mitre.org/techniques/T1528/
author: Security Arsenal
date: 2026/04/10
tags:
- attack.initial_access
- attack.t1550
- attack.t1528
logsource:
product: azure
service: signinlogs
detection:
selection:
signInLogs.properties.authenticationProtocol|contains: 'none'
signInLogs.properties.isInteractive: 'false'
filter_known_asn:
signInLogs.properties.networkLocationDetails|contains:
- 'KNOWN_MSP_ASN_1'
- 'KNOWN_MSP_ASN_2'
condition: selection and not filter_known_asn
falsepositives:
- Legitimate third-party service principals authenticating from new datacenter egress ranges
- MSP infrastructure migration to new hosting providers
level: high
---
title: New Credential or Permission Added to Enterprise Application
id: 2c9d7f06-3a51-4e84-9d5b-6f1a8c2e4b77
status: experimental
description: Detects additions of client secrets, certificates, or app role assignments to service principals, a common follow-on action after compromising an MSP-integrated M365 application to establish persistence independent of the original vendor credential.
references:
- https://cyberscoop.com/connectwise-cloud-backup-supply-chain-attack/
- https://attack.mitre.org/techniques/T1098.001/
author: Security Arsenal
date: 2026/04/10
tags:
- attack.persistence
- attack.t1098.001
- attack.privilege_escalation
logsource:
product: azure
service: auditlogs
detection:
selection:
auditLogs.operationName|contains:
- 'Add service principal credentials'
- 'Add app role assignment to service principal'
- 'Consent to application'
- 'Update application - Certificates and secrets management'
condition: selection
falsepositives:
- Legitimate application onboarding and consent workflows
- Scheduled credential rotation by IT or the vendor
level: high
---
title: Mass Mailbox or SharePoint Access by Application Identity
id: 4e1b8a92-7f3d-4c56-a890-1d6f3e9b5a24
status: experimental
description: Detects bulk MailItemsAccessed or FileSyncDownloadedFull operations attributed to application identities, indicative of data collection or exfiltration through a compromised backup/management application.
references:
- https://cyberscoop.com/connectwise-cloud-backup-supply-chain-attack/
- https://attack.mitre.org/techniques/T1530/
author: Security Arsenal
date: 2026/04/10
tags:
- attack.collection
- attack.t1530
- attack.exfiltration
- attack.t1567
logsource:
product: azure
service: auditlogs
detection:
selection:
auditLogs.operationName|contains:
- 'MailItemsAccessed'
- 'FileSyncDownloadedFull'
- 'SearchQueryPerformed'
auditLogs.logonType: '0'
condition: selection
falsepositives:
- Legitimate backup application indexing and synchronization jobs
- eDiscovery operations performed through third-party tooling
level: medium
KQL — Microsoft Sentinel / Defender
The highest-value hunt for this incident is baseline deviation on service principal behavior: which tenants the app touches, from where, and at what volume. Run these against the last 30–90 days and compare against your known ConnectWise integration footprint.
// Hunt 1: App-only sign-ins by service principals from anomalous IPs/ASNs
// Compare against your documented ConnectWise/MSP egress ranges
let KnownMSPRanges = dynamic(["203.0.113.0/24", "198.51.100.0/24"]); // REPLACE with actual vendor ranges
SigninLogs
| where TimeGenerated > ago(30d)
| where IsInteractive == false
| where AppDisplayName has_any ("ConnectWise", "backup", "msp") or AppId in (/* your consented app IDs */ dynamic([]))
| extend IPinKnownRange = ipv4_is_in_any_range(IPAddress, KnownMSPRanges)
| where IPinKnownRange == false
| summarize SignInCount = count(), FirstSeen = min(TimeGenerated), LastSeen = max(TimeGenerated),
Locations = make_set(Location), UserAgents = make_set(UserAgent)
by AppDisplayName, AppId, IPAddress
| order by SignInCount desc;
// Hunt 2: New credentials or consent grants on service principals during exposure window
AuditLogs
| where TimeGenerated > ago(90d)
| where OperationName has_any ("Add service principal credentials", "Consent to application",
"Add app role assignment to service principal", "Update application")
| mv-expand TargetResources
| extend AppName = tostring(TargetResources.displayName)
| where AppName has_any ("ConnectWise") or OperationName has "Add service principal credentials"
| project TimeGenerated, OperationName, AppName, InitiatedBy = tostring(InitiatedBy.user.userPrincipalName),
IPAddress = tostring(InitiatedBy.user.ipAddress), Result
| order by TimeGenerated desc;
// Hunt 3: Abnormal Graph API / mailbox access volume by application identity
// Requires MicrosoftGraphActivityLogs and/or OfficeActivity (MailItemsAccessed)
MicrosoftGraphActivityLogs
| where TimeGenerated > ago(30d)
| summarize RequestCount = count(), DistinctResources = dcount(tostring(RequestUri)),
Verbs = make_set(RequestMethod) by AppId, bin(TimeGenerated, 1h)
| join kind=leftouter (
MicrosoftGraphActivityLogs
| where TimeGenerated between (ago(90d) .. ago(30d))
| summarize BaselineAvg = avg(RequestCount) by AppId, bin(TimeGenerated, 1h)
) on AppId
| where RequestCount > BaselineAvg * 5
| order by RequestCount desc;
Velociraptor VQL
For MSP environments where ConnectWise tooling (agents, ScreenConnect instances, backup service accounts) runs on endpoints, hunt for credential material exposure and unexpected processes interacting with the ConnectWise installation — a common secondary move once tenant access is established.
-- Hunt for processes accessing ConnectWise configuration and credential stores,
-- plus suspicious child processes spawned by ConnectWise services
SELECT Pid, Ppid, Name, CommandLine, Exe, Username, CreateTime
FROM pslist()
WHERE CommandLine =~ '(?i)(client_secret|apikey|api_key|clientsecret|secret)'
OR (Name =~ '(?i)(ScreenConnect|ConnectWise|CWAutomate|LabTech)'
AND Ppid NOT IN (
SELECT Pid FROM pslist() WHERE Name =~ '(?i)(services|svchost|ScreenConnect)'
))
OR Exe =~ '(?i)\\\\(temp|appdata\\\\local\\\\temp|programdata)\\\\.*\\\\.(exe|ps1|bat)'
Also consider a file hunt over ConnectWise installation directories for recently modified configuration files that may contain or reference the API secret:
-- Enumerate recently modified ConnectWise config files that may hold secrets
SELECT FullPath, Size, Mtime, Ctime
FROM glob(globs=['C:/Program Files*/ConnectWise*/**/*.config',
'C:/Program Files*/ConnectWise*/**/*.json',
'C:/ProgramData/ConnectWise*/**/*.config'],
accessor='ntfs')
WHERE Mtime > now() - (90 * 24 * 3600)
ORDER BY Mtime DESC
Remediation / Hardening Script
This PowerShell script (requires the Microsoft Graph PowerShell SDK with Application.Read.All, AuditLog.Read.All) audits your tenant for ConnectWise-related service principals, enumerates their credentials and permission grants, and flags secrets older than 90 days — your rotation candidates.
# ConnectWise M365 Tenant Audit & Hardening Script
# Run as Global Admin / Cloud App Admin. Requires: Microsoft.Graph module
Connect-MgGraph -Scopes "Application.Read.All","Directory.Read.All","AuditLog.Read.All"
# 1. Locate ConnectWise-related service principals in the tenant
$spns = Get-MgServicePrincipal -All | Where-Object {
$_.DisplayName -match 'ConnectWise|ScreenConnect|Automate|Continuum' -or
$_.PublisherName -match 'ConnectWise'
}
$spns | Select-Object DisplayName, AppId, CreatedDateTime,
@{N='SecretCount';E={($_.PasswordCredentials).Count}},
@{N='CertCount';E={($_.KeyCredentials).Count}} | Format-Table -AutoSize
# 2. Flag aging secrets and expired/near-expiry credentials for rotation
foreach ($sp in $spns) {
foreach ($cred in $sp.PasswordCredentials) {
$ageDays = ((Get-Date) - $cred.StartDateTime).Days
if ($ageDays -gt 90) {
Write-Warning "$($sp.DisplayName): secret aged $ageDays days (KeyId $($cred.KeyId)) - ROTATE/REVOKE"
}
}
}
# 3. Enumerate app role assignments (consented Graph permissions) per SP
foreach ($sp in $spns) {
Get-MgServicePrincipalAppRoleAssignment -ServicePrincipalId $sp.Id |
Select-Object @{N='SP';E={$sp.DisplayName}}, AppRoleId, ResourceDisplayName, CreatedDateTime
}
# 4. Revoke a compromised secret (UNCOMMENT after coordinating with ConnectWise)
# Remove-MgServicePrincipalPassword -ServicePrincipalId <SP_OBJECT_ID> -KeyId <KEY_ID>
# 5. Harden: restrict who can consent to apps going forward
$params = @{ defaultUserRolePermissions = @{ permissionGrantPoliciesAssigned = @() } }
Update-MgPolicyAuthorizationPolicy -BodyParameter $params
Write-Host "User consent disabled. Require admin consent workflow for new app grants." -ForegroundColor Green
Remediation
If your organization — or your MSP — uses ConnectWise with Microsoft 365 integrations, execute the following in priority order:
- Confirm exposure with the vendor. Monitor ConnectWise's official security advisories and trust center for the definitive list of affected products, the exposure window, and whether your tenant's credential material was in scope. Do not rely solely on press reporting for scoping.
- Revoke and rotate the compromised credential immediately. Remove the suspect client secret from the affected enterprise application/service principal in Entra ID and complete ConnectWise's re-pairing/re-authorization procedure. A stolen secret that remains valid is an open door even after the vendor-side incident is closed.
- Audit consent grants on the affected application. Review every app role assignment on the ConnectWise service principal. Apply least privilege: if the integration does not require
Sites.ReadWrite.Allor full Exchange application access, downgrade the grant. Backup tooling is chronically over-permissioned. - Review audit logs across the exposure window. In the Unified Audit Log / Entra audit logs, look for:
Add service principal credentials, unexpectedConsent to applicationevents,MailItemsAccessedat abnormal volume, and service principal sign-ins from IP ranges not attributable to ConnectWise infrastructure. Assume read access to everything the app could touch and scope your data exposure assessment accordingly. - Hunt for persistence beyond the original credential. Sophisticated actors who obtain app secrets often add their own credential (certificate or second secret) to the same app registration so access survives vendor-driven rotation. Step 2 of the audit script above is designed to catch exactly this.
- Enforce admin consent workflows and credential hygiene tenant-wide. Disable user consent, require admin approval for new OAuth grants, set maximum secret lifetimes, and migrate high-privilege app integrations to certificate-based credentials stored in an HSM or managed identity where supported.
- Reassess third-party management plane risk. Every MSP tool with a service principal in your tenant is a potential blast-radius multiplier. Maintain an inventory of all consented enterprise applications, their permission scopes, and their vendor's security posture — and require contractual notification SLAs for credential compromise events.
There is no patch version to deploy and no CISA KEV deadline attached to this incident — the fix is operational: revoke, rotate, audit, and reduce standing privilege. Treat any credential that crossed a vendor boundary as compromised until proven otherwise.
Related Resources
Security Arsenal Penetration Testing Services AlertMonitor Platform Book a SOC Assessment vulnerability-management Intel Hub
Is your security operations ready?
Get a free SOC assessment or see how AlertMonitor cuts through alert noise with automated triage.