McKesson / ShinyHunters Vishing and SaaS Data-Theft Tradecraft

Threat Overview

McKesson disclosed on August 28, 2026 that it discovered a cybersecurity incident on August 25 involving unauthorized access to third-party applications and data exfiltration. McKesson has not publicly identified the applications, initial-access method, stolen data set, or attacker. Its SEC filing states that the investigation remains in early stages and that it had not determined the incident to be material at filing time.

BleepingComputer reported that the ShinyHunters extortion group claimed responsibility and said it used voice phishing against multiple employees, compromised multiple Okta SSO accounts, then accessed Salesforce and Snowflake. The actor claimed roughly 1 TB of data was exfiltrated between August 21 and August 25 and that about 284 million patient-related records were taken. These platform, access-method, volume, and record-count details are threat-actor claims and are not confirmed by McKesson. BleepingComputer also reported the lookalike domain mckesson.claims.

References

Impacted Systems

Confirmed affected organizationMcKesson Corporation
Confirmed affected surfaceThird-party applications; unauthorized access and data exfiltration confirmed
Confirmed discovery dateAugust 25, 2026
Threat-actor claimed initial accessVoice phishing / vishing against multiple employees
Threat-actor claimed identity platformOkta SSO
Threat-actor claimed downstream SaaSSalesforce and Snowflake
Threat-actor claimed exfiltration windowAugust 21–25, 2026
Threat-actor claimed volumeApproximately 1 TB
Threat-actor claimed record countApproximately 284 million raw records, not unique patients
Reported lookalike domainmckesson.claims
Known activityConfirmed data-exfiltration incident; ShinyHunters attribution and detailed tradecraft remain unverified claims

Why this matters

This incident maps directly to a recurring MSSP risk: attackers bypass vulnerability management by abusing help-desk trust, identity recovery, and federated SaaS access. The same behaviors can affect organizations using Entra ID, Okta, Salesforce, Snowflake, Microsoft 365, or other SSO-connected platforms.

Exploitation Status

McKesson confirms unauthorized third-party application access and exfiltration. ShinyHunters claims responsibility, vishing-based Okta compromise, Salesforce/Snowflake access, the mckesson.claims domain, and the exfiltration volume. Those actor-specific details are not confirmed by McKesson.

What this hunt looks for

Unusual sign-in geography and IP changes, sign-ins after authentication-method changes, rare device/browser combinations, high-volume cloud-app activity, suspicious identity changes, lookalike-domain access, and non-interactive session anomalies.

Required logs

  • SigninLogs
  • AADNonInteractiveUserSignInLogs
  • AuditLogs
  • CloudAppEvents where supported
  • CommonSecurityLog or equivalent proxy/DNS telemetry
  • Vendor-specific Okta logs when ingested

Hunt 1 — First-Pass: New IP and Country for Successful Entra Sign-Ins

let Baseline = SigninLogs
| where TimeGenerated between (ago(30d) .. ago(7d))
| where ResultType == 0
| summarize by UserPrincipalName, IPAddress, Location;
SigninLogs
| where TimeGenerated >= ago(7d)
| where ResultType == 0
| join kind=leftanti Baseline on UserPrincipalName, IPAddress, Location
| project TimeGenerated, UserPrincipalName, IPAddress, Location, AppDisplayName, ClientAppUsed, DeviceDetail, AuthenticationRequirement, ConditionalAccessStatus
| sort by TimeGenerated desc

Hunt 2 — Multiple Users Authenticating From the Same IP

SigninLogs
| where TimeGenerated >= ago(7d)
| where ResultType == 0
| summarize Users=dcount(UserPrincipalName), UserList=make_set(UserPrincipalName,50), Apps=make_set(AppDisplayName,30), FirstSeen=min(TimeGenerated), LastSeen=max(TimeGenerated) by IPAddress, Location
| where Users >= 3
| sort by Users desc

Hunt 3 — Authentication Method Changes Followed by Sign-In

let Changes = AuditLogs
| where TimeGenerated >= ago(14d)
| where OperationName has_any ("authentication method","password","MFA","security info","registered device")
| mv-expand TargetResources
| extend TargetUPN=tostring(TargetResources.userPrincipalName)
| where isnotempty(TargetUPN)
| project TargetUPN, ChangeTime=TimeGenerated, OperationName, InitiatedBy;
SigninLogs
| where TimeGenerated >= ago(14d)
| where ResultType == 0
| join kind=inner Changes on $left.UserPrincipalName == $right.TargetUPN
| where TimeGenerated between (ChangeTime .. ChangeTime + 2h)
| project ChangeTime, TimeGenerated, UserPrincipalName, OperationName, IPAddress, Location, AppDisplayName, ClientAppUsed, ConditionalAccessStatus, InitiatedBy
| sort by ChangeTime desc

Hunt 4 — Rare Cloud App Activity by User

CloudAppEvents
| where TimeGenerated >= ago(30d)
| summarize Events=count(), FirstSeen=min(TimeGenerated), LastSeen=max(TimeGenerated), IPs=make_set(IPAddress,20), Actions=make_set(ActionType,30) by AccountDisplayName, Application
| where Events <= 5
| sort by LastSeen desc

Hunt 5 — High-Volume Cloud App Activity

CloudAppEvents
| where TimeGenerated >= ago(7d)
| summarize Events=count(), Actions=dcount(ActionType), Objects=dcount(ObjectName), FirstSeen=min(TimeGenerated), LastSeen=max(TimeGenerated) by AccountDisplayName, Application, IPAddress, bin(TimeGenerated,15m)
| where Events >= 100 or Objects >= 50
| sort by Events desc

Hunt 6 — Same User Across Multiple Countries

SigninLogs
| where TimeGenerated >= ago(7d)
| where ResultType == 0
| summarize Countries=make_set(LocationDetails.countryOrRegion,10), CountryCount=dcount(LocationDetails.countryOrRegion), IPs=make_set(IPAddress,20), Apps=make_set(AppDisplayName,20) by UserPrincipalName, bin(TimeGenerated,1h)
| where CountryCount >= 2
| sort by TimeGenerated desc

Hunt 7 — Reported Lookalike Domain

CommonSecurityLog
| where TimeGenerated >= ago(30d)
| where RequestURL has "mckesson.claims" or DestinationHostName has "mckesson.claims" or Message has "mckesson.claims"
| project TimeGenerated, SourceIP, DestinationIP, DestinationHostName, RequestURL, DeviceAction, RequestClientApplication, Message
| sort by TimeGenerated asc

Hunt 8 — Non-Interactive Sign-Ins From Newly Seen IPs

let Baseline = AADNonInteractiveUserSignInLogs
| where TimeGenerated between (ago(30d) .. ago(7d))
| where ResultType == 0
| summarize by UserPrincipalName, IPAddress;
AADNonInteractiveUserSignInLogs
| where TimeGenerated >= ago(7d)
| where ResultType == 0
| join kind=leftanti Baseline on UserPrincipalName, IPAddress
| project TimeGenerated, UserPrincipalName, IPAddress, AppDisplayName, ResourceDisplayName, ClientAppUsed, ConditionalAccessStatus, DeviceDetail
| sort by TimeGenerated desc

Detection Notes

  • Do not treat the ShinyHunters attribution, Okta/Salesforce/Snowflake details, 1 TB figure, or 284 million record count as confirmed by McKesson.
  • Highest-value hunts are identity changes followed by sign-ins, new IP/country combinations, and high-volume SaaS access.
  • CloudAppEvents coverage varies by connected application and licensing.
  • The mckesson.claims IOC is specific to the reported campaign and is not the only possible infrastructure.
  • Vishing can leave little endpoint evidence when valid credentials and normal browser sessions are used.

Leave a comment