# ConnectWise (SkyKick) Vendor Credentials Abused in M365 Attacks

Stolen ConnectWise/SkyKick app credential used to mint Graph tokens across 300+ M365 tenants, self-grant Global Admin, and plant secrets on other apps.

- Payout: Real-world hack
- Severity: critical
- Program: ConnectWise SkyKick
- Credited: Huntress
- Disclosed: 2026-10-16
- Write-up quality: 8/10
- Original: https://www.huntress.com/blog/vendor-credential-enables-unauthorized-access
- Library page: https://bugbountylibrary.com/r/blog%3Ahuntress-com-blog-vendor-credential-enables-unauthorized-access
- Tags: domain:cloud impact:data-leak impact:internal-access kind:incident platform:threat-intel sev:critical tech:azure tech:oauth technique:recon technique:source-review vuln:privilege-escalation vuln:secrets-leak

**Target:** Microsoft Entra service principal / OAuth client assertion for ConnectWise Cloud Backup app
**Root cause:** The vendor's client assertion credential for the multi-tenant backup app was compromised, letting the attacker authenticate as the app from arbitrary infrastructure and inherit its broad Graph permissions in every consenting tenant.
**Steps:**
1. Obtain the ConnectWise Cloud Backup app client assertion (506e08f9-6e9a-4da4-942b-a099a03644ae).
2. POST OAuth2 client_assertion grant to Entra token endpoint for each target tenant to get Graph tokens; observed from `144.172.64[.]128` between 06:13-08:34 UTC Oct 15.
3. Iterate tenants in sorted GUID order a few seconds apart (scripted target list).
4. In one tenant, ConnectWise Cloud Management - MS Teams app (24205314-...) added itself to Global Administrator role via `Add member to role`.
5. Run `Python-urllib/3.12` script issuing `Update application` / `Add service principal credentials` to plant client secrets (expiring 2028) on an MSP management app and Huntress Security Platform app.
6. Use planted secrets for app-only sign-in (no MFA) to persist.
**How found:** Huntress noticed app sign-ins from a hosting-provider IP (144.172.64[.]128) instead of the app's normal Azure private IPv6 egress, and distinguished actor vs vendor activity by User-Agent (kiota-dotnet for vendor SDK vs Python-urllib/3.12 and curl/7.88.1 for attacker).
**Exploitation:** Attacker held the vendor's client assertion, minted Graph tokens per tenant from a hosting IP, then in at least one tenant escalated the Teams management app to Global Administrator and planted long-lived client secrets on other privileged applications to retain access independent of the original credential.
**Escalation:** Self-assigned Global Administrator via the Cloud Management Teams app, then added credentials to MSP management and security-tool applications that are often consented into downstream customer tenants, potentially extending reach beyond the initial tenant.
**Insight:** For multi-tenant SaaS integrations, baseline the egress IP range and User-Agent of the vendor's service principal; any app-only sign-in from outside that range is a stolen-credential signal, and audit `Add service principal credentials` events where the initiating app differs from the vendor SDK UA.
