Adversaries may be sharing sensitive files with external users to exfiltrate data or establish a foothold. SOC teams should proactively hunt for this behavior in Azure Sentinel to identify potential data leakage or compromise early.
KQL Query
let usefulExtn= pack_array('csv', 'doc', 'docm', 'docx', 'dot', 'dotx', 'eml', 'pdf', 'pot', 'potm', 'potx', 'ppam', 'pps', 'ppsm', 'ppsx', 'ppt', 'pptm', 'pptx',
'psd', 'pst', 'pub', 'ppk', 'rar', 'rtf', 'txt', 'vsd', 'vsdm', 'vsdx', 'vss', 'vssm', 'vst', 'vstm', 'vstx', 'xla', 'xlam', 'xll', 'xlm', 'xls', 'xlsm', 'xlsx', 'xlt',
'xltm', 'xltx', 'xps', 'zip', 'xsl');
let sharingPerms= pack_array("AnonymousLinkCreated", "SharingInvitationCreated", "SharingSet");
let relevantAppIds = pack_array(int(20892), int(15600)); // App Ids for SharePoint and OneDrive
let timeWindow = 24h;
let timeNow = now();
//
let riskyUsers= // Look for users with risky sign-ins
EntraIdSignInEvents
| where Timestamp between ((timeNow - timeWindow) .. (timeNow))
| where isnotempty(AccountObjectId) and isnotempty(RequestId) // In EntraIdSignInEvents, the SessionId column has inaccurate data and instead the RequestId has the actual Session identifier
| where ErrorCode == 0
| where RiskLevelDuringSignIn >=80
| project RiskLevelDuringSignIn, AccountObjectId, Timestamp, SessionId=RequestId
;
let hasUsers = isnotempty(toscalar(riskyUsers));
//
CloudAppEvents // look for file sharing activity and scope it to risky users
| where hasUsers
| where Timestamp between ((timeNow - timeWindow) .. (timeNow))
| where ApplicationId in (relevantAppIds)
| where AccountObjectId in (riskyUsers)
| where ActionType in (sharingPerms)
| extend SourceFileExtension = tostring(RawEventData.SourceFileExtension), SourceFileName=tostring(RawEventData.SourceFileName), TargetGroup=tostring(RawEventData.TargetUserOrGroupType)
| where SourceFileExtension has_any (usefulExtn)
| where TargetGroup == "Guest"
//
| summarize Count = countif(isnotempty( SourceFileName)), (Timestamp, ReportId)=arg_min(Timestamp, ReportId) ,FileNames = make_set(SourceFileName, 10) ,FileExt = make_set(SourceFileExtension, 10) by AccountObjectId, AccountDisplayName, ApplicationId, ActionType, Time = bin(Timestamp, 10m)
| summarize TotalCount = countif(Count > 10) , (Timestamp, ReportId)=arg_min(Timestamp, ReportId) by AccountObjectId, AccountDisplayName, ApplicationId
| where TotalCount > 1
id: bafc1446-1cc4-4f6d-ad76-1250b8c3b60c
name: Unusual volume of file sharing with external user.
description: |
This query looks for users sharing access to files with external users.
This applies to SharePoint and OneDrive users.
Audit event and Cloud application identifier references.
Reference - https://learn.microsoft.com/microsoft-365/compliance/audit-log-sharing?view=o365-worldwide
Reference - https://learn.microsoft.com/azure/sentinel/entities-reference#cloud-application-identifiers
requiredDataConnectors:
- connectorId: MicrosoftThreatProtection
dataTypes:
- CloudAppEvents
- EntraIdSignInEvents
tactics:
- Exfiltration
query: |
let usefulExtn= pack_array('csv', 'doc', 'docm', 'docx', 'dot', 'dotx', 'eml', 'pdf', 'pot', 'potm', 'potx', 'ppam', 'pps', 'ppsm', 'ppsx', 'ppt', 'pptm', 'pptx',
'psd', 'pst', 'pub', 'ppk', 'rar', 'rtf', 'txt', 'vsd', 'vsdm', 'vsdx', 'vss', 'vssm', 'vst', 'vstm', 'vstx', 'xla', 'xlam', 'xll', 'xlm', 'xls', 'xlsm', 'xlsx', 'xlt',
'xltm', 'xltx', 'xps', 'zip', 'xsl');
let sharingPerms= pack_array("AnonymousLinkCreated", "SharingInvitationCreated", "SharingSet");
let relevantAppIds = pack_array(int(20892), int(15600)); // App Ids for SharePoint and OneDrive
let timeWindow = 24h;
let timeNow = now();
//
let riskyUsers= // Look for users with risky sign-ins
EntraIdSignInEvents
| where Timestamp between ((timeNow - timeWindow) .. (timeNow))
| where isnotempty(AccountObjectId) and isnotempty(RequestId) // In EntraIdSignInEvents, the SessionId column has inaccurate data and instead the RequestId has the actual Session identifier
| where ErrorCode == 0
| where RiskLevelDuringSignIn >=80
| project RiskLevelDuringSignIn, AccountObjectId, Timestamp, SessionId=RequestId
;
let hasUsers = isnotempty(toscalar(riskyUsers));
//
CloudAppEvents // look for file sharing activity and scope it to risky users
| where hasUsers
| where Timestamp between ((timeNow - timeWindow) .. (timeNow))
| where ApplicationId in (relevantAppIds)
| where AccountObjectId in (riskyUsers)
| where ActionType in (sharingPerms)
| extend SourceFileExtension = tostring(RawEventData.SourceFileExtension), SourceFileName=tostring(RawEventData.SourceFileName), TargetGroup=tostring(RawEventData.TargetUserOrGroupType)
| where SourceFileExtension has_any (usefulExtn)
| where TargetGroup == "Guest"
//
| summarize Count = countif(isnotempty( SourceFileName)), (Timestamp, ReportId)=arg_min(Timestamp, ReportId) ,FileNames = make_set(SourceFileName, 10) ,FileExt = make_set(SourceFileExtension, 10) by AccountObjectId, AccountDisplayName, ApplicationId, ActionType, Time = bin(Timestamp, 10m)
| summarize TotalCount = countif(Count > 10) , (Timestamp, ReportId)=arg_min(Timestamp, ReportId) by AccountObjectId, AccountDisplayName, ApplicationId
| where TotalCount > 1
entityMappings:
- entityType: Account
fieldMappings:
- identifier: AadUserId
| Sentinel Table | Notes |
|---|---|
CloudAppEvents | Ensure this data connector is enabled |
Scenario: Scheduled Backup Job Sharing Files with External User
Description: A scheduled backup job runs daily and temporarily shares files with an external user for data transfer.
Filter/Exclusion: Exclude file shares initiated by system accounts or scheduled tasks (e.g., runas /user:NT AUTHORITY\SYSTEM or Task Scheduler job names).
Scenario: Admin Task to Share Files with External Partner
Description: An admin shares a folder with an external partner for collaboration on a project, which is a legitimate business activity.
Filter/Exclusion: Exclude file shares initiated by admin users (e.g., UserPrincipalName containing [email protected] or ITAdmins group).
Scenario: OneDrive Sync Client Sharing Files with External User
Description: A user’s OneDrive sync client shares files with an external user during a sync process, which is a normal part of file synchronization.
Filter/Exclusion: Exclude file shares originating from the OneDrive sync client (e.g., ClientAppId equals OneDriveSyncClient or Microsoft.OneDrive.Sync).
Scenario: SharePoint Site Migration with External User Access
Description: A SharePoint site is being migrated, and temporary access is granted to an external user for data transfer.
Filter/Exclusion: Exclude file shares where the external user is part of a migration team or has a role like Site Collection Administrator or MigrationUser.
Scenario: User Shares Files with External User for Collaboration
Description: A user shares files with an external user for a legitimate business purpose, such as a client collaboration or vendor access.
Filter/Exclusion: Exclude file shares where the external user is in a trusted list (e.g., ExternalTrustedUsers group) or has a known business relationship.