Back to Intelligence

ConnectWise Cloud Backup / SkyKick M365 Credential Abuse: OTX Detection Pack — Microsoft Graph Token Access Across Hundreds of Tenants

SA
Security Arsenal Team
October 19, 2026
9 min read

Excerpt

OTX flags compromised ConnectWise/SkyKick vendor M365 API credentials used from 144.172.64.128 for Graph access across hundreds of tenants; high urgency for MSP and M365 defenders.

Threat Summary

AlienVault OTX pulse reporting indicates that a Microsoft 365 API credential belonging to ConnectWise Cloud Backup, formerly SkyKick, was compromised and used to authenticate into customer Microsoft 365 environments. The activity is attributed to an unknown actor and is significant because it abuses trusted vendor plumbing rather than commodity endpoint malware. On October 15, the actor authenticated from 144.172.64.128 and obtained Microsoft Graph access tokens across hundreds of tenants. The report notes movement through tenants in sorted GUID order, which strongly suggests scripted enumeration, credential replay, and automated tenant selection rather than manual intrusion.

The likely attack chain is: compromise or disclosure of a vendor-held API credential, use of that credential to request application or delegated Graph tokens, authentication against Microsoft identity endpoints, normalized API access through Microsoft Graph, and bulk traversal of customer tenants that trust the ConnectWise/SkyKick application. The objective is consistent with credential and data access at cloud scale: read backup catalogs, enumerate users and mailboxes, collect sensitive M365 data, discover recovery objects, and potentially stage follow-on extortion, BEC, or persistence through additional app credentials. Because the actor rides legitimate SaaS control planes, traditional malware-only detections will miss most of the intrusion.

Threat Actor / Malware Profile

No named malware family is present in the pulse, and no endpoint payload is required for the core intrusion. The profile is better described as cloud credential abuse against an MSP/vendor backup integration. Distribution is supply-chain trust: customers granted the vendor application access for backup, recovery, migration, or management, and the attacker inherits that trust after stealing or replaying the credential. Payload behavior is API-driven: token acquisition, tenant enumeration, service principal usage, Graph reads, and possible changes to application secrets, consent grants, or backup job configuration if privileges allow.

Command-and-control is effectively Microsoft Graph and Microsoft Entra ID. The actor communicates with login.microsoftonline.com and graph.microsoft.com using valid OAuth flows, which makes the traffic look like normal SaaS administration unless defenders baseline app IDs, source IPs, tenant IDs, token audience, and call volume. Persistence is not a Run key or scheduled task on an endpoint; it is the continued validity of the vendor credential, any newly added service principal secrets or certificates, excessive app roles, and surviving consent grants. Anti-analysis techniques include blending into approved vendor automation, using infrastructure clustered around 144.172.64.60, 144.172.64.99, and 144.172.64.128, moving in sorted GUID order to simplify automation, avoiding noisy endpoint implants, and staying inside API rate limits where possible.

IOC Analysis

The indicator set is small but high value: IPv4 addresses 144.172.64.99, 144.172.64.128, and 144.172.64.60, plus CVE-2025-11371. Treat the addresses as suspect authentication or egress sources for Microsoft identity and Graph activity, not merely as blocklist entries. A simple firewall block may not stop cloud token replay if the actor changes hosts, but network telemetry can still reveal impossible travel, unexpected vendor app sign-ins, and authentication sources outside normal ConnectWise/SkyKick operating ranges. The CVE should be handled as a separate exposure-validation task: confirm whether any reachable ConnectWise, SkyKick, backup, M365 integration, or adjacent component matches the affected product and version before assuming exploitability.

SOC teams should operationalize the indicators by joining the IPs to Microsoft Entra sign-in logs, service principal sign-in logs, audit logs, Microsoft Graph activity where available, Exchange Online audit, Azure AD workload identity events, CASB logs, and proxy/ZTNA egress. Enrich with app ID, app display name, service principal ID, tenant ID, user agent, token audience, grant type, and success/failure reason. Useful tooling includes Microsoft Sentinel, Defender XDR advanced hunting, Entra ID Protection, Microsoft Purview audit, Graph PowerShell for app and consent review, and Sigma pipelines that convert cloud detections into the analytics stack used by the SOC.

Detection Engineering

YAML
---
title: Suspect OTX Infrastructure Authenticating To Microsoft Cloud
id: 9b5f8d0e-6b1d-4db4-9f25-ctwskykick001
status: experimental
description: Detects successful or failed authentication activity to Microsoft cloud services from OTX-listed IPs tied to ConnectWise/SkyKick credential abuse.
author: Security Arsenal
date: 2026/10/19
references:
  - 'https://www.huntress.com/blog/vendor-credential-enables-unauthorized-access'
logsource:
  product: azure
  service: signinlogs
detection:
  selection_ip:
    IPAddress:
      - '144.172.64.60'
      - '144.172.64.99'
      - '144.172.64.128'
  selection_cloud:
    AppDisplayName|contains:
      - 'ConnectWise'
      - 'SkyKick'
      - 'Cloud Backup'
      - 'Microsoft Graph'
  condition: selection_ip or (selection_ip and selection_cloud)
falsepositives:
  - Vendor SOC, backup orchestration hosts, or customer egress NAT may coincidentally use adjacent infrastructure; verify ASN, tenant ID, app ID, and service principal ID before containment.
level: high
tags:
  - attack.initial_access
  - attack.t1078
  - attack.t1550
---
title: Service Principal Credential Or Consent Change After Cloud Backup Access
id: 7e1d5a35-0b8c-4f67-a2b8-ctwskykick002
status: experimental
description: Detects additions of app secrets, certificates, federated credentials, or admin consent around the same window as suspicious Microsoft Graph access by backup or MSP applications.
author: Security Arsenal
date: 2026/10/19
logsource:
  product: azure
  service: auditlogs
detection:
  selection_ops:
    OperationName|contains:
      - 'Add service principal credentials'
      - 'Update application'
      - 'Consent to application'
      - 'Add app role assignment'
      - 'Add delegated permission grant'
      - 'Add federated credentials'
  selection_target:
    TargetResources|contains:
      - 'ConnectWise'
      - 'SkyKick'
      - 'Cloud Backup'
      - 'backup'
      - 'msp'
  condition: selection_ops and selection_target
falsepositives:
  - Scheduled certificate rotation by the vendor; require change ticket, initiator, source IP, and correlation to unusual token activity.
level: critical
tags:
  - attack.persistence
  - attack.t1098
  - attack.t1136
  - attack.t1550
---
title: Bulk Multi Tenant Microsoft Graph Token Or Read Pattern
id: 1e2c734d-93b4-4b0b-a320-ctwskykick003
status: experimental
description: Identifies high-volume Graph token issuance or API reads across many tenants by a single app, service principal, or IP, consistent with sorted GUID tenant traversal.
author: Security Arsenal
date: 2026/10/19
logsource:
  category: cloud
detection:
  selection_graph:
    resource|contains:
      - 'graph.microsoft.com'
      - 'login.microsoftonline.com'
  selection_vendor_context:
    app_display_name|contains:
      - 'ConnectWise'
      - 'SkyKick'
      - 'Cloud Backup'
      - 'backup'
  condition: selection_graph and selection_vendor_context
falsepositives:
  - Legitimate nightly backup windows can be broad; alert when tenant count, token count, source ASN, or time-of-day deviates from the vendor baseline.
level: medium
tags:
  - attack.collection
  - attack.t1530
  - attack.t1213
  - attack.t1550
KQL — Microsoft Sentinel / Defender
let iocs = dynamic(['144.172.64.60','144.172.64.99','144.172.64.128']);
let lookback = 14d;
let VendorHits = union isfuzzy=true
    (SigninLogs
    | where TimeGenerated >= ago(lookback)
    | where IPAddress in (iocs) or AppDisplayName has_any ('ConnectWise','SkyKick','Cloud Backup')
    | project TimeGenerated, IPAddress, AppDisplayName, AppId, ServicePrincipalId, TenantId, UserPrincipalName, ResultType, ResultDescription, AuthenticationRequirement, ClientAppUsed, UserAgent),
    (AADServicePrincipalSignInLogs
    | where TimeGenerated >= ago(lookback)
    | where IPAddress in (iocs) or ServicePrincipalName has_any ('ConnectWise','SkyKick','Cloud Backup')
    | project TimeGenerated, IPAddress, ServicePrincipalName, ServicePrincipalId, AppId, TenantId, ResultType, ResultDescription),
    (AuditLogs
    | where TimeGenerated >= ago(lookback)
    | where OperationName has_any ('Add service principal credentials','Consent to application','Update application','Add app role assignment','Add delegated permission grant','Add federated credentials')
    | where tostring(TargetResources) has_any ('ConnectWise','SkyKick','backup','Cloud Backup') or InitiatedBy has_any ('ConnectWise','SkyKick')
    | project TimeGenerated, OperationName, InitiatedBy, TargetResources, Result, IPAddress=tostring(parse_json(InitiatedBy).user.ipAddress), CorrelationId);
VendorHits
| summarize Events=count(), DistinctTenants=dcount(TenantId), First=min(TimeGenerated), Last=max(TimeGenerated) by IPAddress, AppDisplayName, ServicePrincipalId, TenantId, OperationName
| where IPAddress in (iocs) or DistinctTenants > 10 or OperationName has_any ('Add service principal credentials','Consent to application')
| sort by Events desc, DistinctTenants desc;
PowerShell
$ErrorActionPreference = 'SilentlyContinue'
$Iocs = @('144.172.64.60','144.172.64.99','144.172.64.128')
$Report = @()
Get-NetTCPConnection | Where-Object { $Iocs -contains $_.RemoteAddress -or $_.RemotePort -in 443,4443 } | ForEach-Object {
  $p = Get-Process -Id $_.OwningProcess
  $Report += [pscustomobject]@{Type='Network'; Local=$_.LocalAddress; Remote=$_.RemoteAddress; State=$_.State; Process=$p.ProcessName; Path=$p.Path; PID=$_.OwningProcess}
}
Get-DnsClientCache | Where-Object { $_.Data -and ($Iocs | Where-Object { $_ -eq $_.Data }) } | ForEach-Object {
  $Report += [pscustomobject]@{Type='DNSCache'; Name=$_.Name; Data=$_.Data}
}
$RunKeys = @('HKCU:\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run','HKLM:\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run')
foreach ($k in $RunKeys) { Get-ItemProperty $k | ForEach-Object { $_.PSObject.Properties | Where-Object { $_.Value -match 'connectwise|skykick|backup|graph|login.microsoftonline' } | ForEach-Object { $Report += [pscustomobject]@{Type='RunKey'; Key=$k; Name=$_.Name; Value=$_.Value} } } }
Get-ScheduledTask | Where-Object { $_.TaskName -match 'connectwise|skykick|backup|graph' -or ($_.Actions.Arguments -match 'login.microsoftonline|graph.microsoft.com') } | ForEach-Object {
  $Report += [pscustomobject]@{Type='ScheduledTask'; Name=$_.TaskName; Path=$_.TaskPath; Action=($_.Actions | Out-String)}
}
Get-WinEvent -FilterHashtable @{LogName='Security'; Id=4688; StartTime=(Get-Date).AddDays(-14)} | Where-Object { $_.Message -match '144.172.64|graph.microsoft.com|login.microsoftonline|ConnectWise|SkyKick' } | ForEach-Object {
  $Report += [pscustomobject]@{Type='ProcessStart'; Time=$_.TimeCreated; Message=($_.Message -replace '\\s+',' ').Substring(0,[Math]::Min(500,$_.Message.Length))}
}
$Report | Export-Csv -NoTypeInformation -Path "$env:TEMP\\skykick_m365_hunt.csv"
$Report | Format-Table -AutoSize

Response Priorities

Immediate: add the three IPv4 indicators to SIEM watchlists, EDR network IOC feeds, CASB/session controls, proxy alerting, and Entra sign-in detections; do not rely on egress blocking alone because token replay can move hosts. Search for successful and failed sign-ins involving ConnectWise, SkyKick, Cloud Backup, or unknown service principals using these IPs, and revoke sessions, refresh tokens, app secrets, certificates, and federated credentials tied to the affected vendor app after vendor coordination. Capture exact app IDs, tenant IDs, service principal object IDs, grant types, user agents, and Graph resources before rotating credentials so scoping is not destroyed.

24 hours: treat this as credential-theft-grade identity exposure even though no stealer binary is named. Force password resets and MFA re-proofing for admins whose sessions, mailboxes, backup roles, or consent rights were touched; review Entra ID Protection risk events, Conditional Access policy evaluations, Exchange mailbox auditing, Teams and SharePoint access, and any OAuth grants created after October 15. Validate whether customers use the same vendor integration across production, government, and technology tenants, and notify procurement, legal, and the vendor through incident channels rather than ad hoc email.

1 week: harden the architecture around vendor trust. Require dedicated customer-owned app registrations where feasible, least-privilege Graph scopes, certificate-based auth with short lifetime, IP/location allowlists for workload identities where supported, Continuous Access Evaluation, token theft binding where available, alerting on multi-tenant fan-out, separation between backup control plane and restore approval, and break-glass procedures that do not depend on the compromised vendor path. Add detections for service principal credential additions, abnormal tenant-count fan-out, sorted enumeration patterns, and consent changes during backup windows.

Related Resources

Security Arsenal Incident Response Managed SOC & MDR Services AlertMonitor Threat Detection From The Dark Side Intel Hub

Is your security operations ready?

Get a free SOC assessment or see how AlertMonitor cuts through alert noise with automated triage.