RULE 23 M365 Share Point Anonymous Link Accessed
Query
// Rule : M365 - SharePoint / OneDrive Anonymous or Shared Link Accessed (Data Made Public)
// Severity: High
// Tactics : Exfiltration, InitialAccess
// MITRE : T1567.002 (Exfiltration Over Web Service),
// T1530 (Data from Cloud Storage)
// Freq : PT1H Period: PT1H
// Description: Detects USAGE of anonymous or shared links to access SharePoint/OneDrive
// content — distinct from link CREATION (covered by RULE-09). High access
// counts on anonymous links, especially to sensitive-named content or from
// diverse IPs, indicate that data has been made publicly accessible and is
// actively being harvested, either after an internal share or via a leaked link.
//==========================================================================================
let LookbackPeriod = 1h;
let AnonymousAccessThreshold = 10; // accesses per hour to trigger
let SensitiveSitePatterns = dynamic([
"hr", "legal", "finance", "exec", "security", "payroll",
"board", "audit", "compliance", "confidential", "restricted"
]);
OfficeActivity
| where TimeGenerated > ago(LookbackPeriod)
| where RecordType in ("SharePoint", "OneDrive")
| where Operation in (
"AnonymousLinkUsed",
"SecureLinkUsed",
"AnonymousLinkUpdated",
"AppAccessedFileViaSharingLink",
"FileAccessedAnonymously",
"PageViewedExtended")
| extend
SiteLower = tolower(SiteUrl),
AccessorIP = ClientIP,
IsAnonymousOp = Operation in ("AnonymousLinkUsed", "FileAccessedAnonymously", "AnonymousLinkUpdated")
| extend
IsSensitiveSite = SiteLower has_any (SensitiveSitePatterns),
// Detect access from multiple distinct IPs — indicates public leaked link
FileKey = strcat(SourceFileName, "|", SiteUrl)
| summarize
TotalAccesses = count(),
AnonymousAccesses = countif(IsAnonymousOp),
UniqueIPs = dcount(AccessorIP),
IPList = make_set(AccessorIP, 15),
FilesSeen = make_set(SourceFileName, 10),
SiteURLs = make_set(SiteUrl, 5),
IsSensitiveSite = any(IsSensitiveSite),
FirstAccess = min(TimeGenerated),
LastAccess = max(TimeGenerated)
by SourceFileName, SiteUrl
| where AnonymousAccesses >= AnonymousAccessThreshold
or (UniqueIPs >= 5 and AnonymousAccesses >= 3)
| extend AlertSeverity = case(
IsSensitiveSite and UniqueIPs >= 10, "Critical",
IsSensitiveSite, "High",
UniqueIPs >= 10, "High",
"Medium")
| project
TimeGenerated = LastAccess,
SourceFileName,
SiteUrl,
TotalAccesses,
AnonymousAccesses,
UniqueIPs,
IPList,
IsSensitiveSite,
FirstAccess,
AlertSeverityExplanation
This query is designed to detect potentially unauthorized access to SharePoint or OneDrive content through anonymous or shared links. Here's a simplified breakdown:
-
Purpose: The query identifies when files on SharePoint or OneDrive are accessed using anonymous or shared links, which could indicate that data is being made publicly accessible and potentially harvested.
-
Time Frame: It looks at activities within the last hour.
-
Thresholds:
- It triggers an alert if there are 10 or more anonymous accesses to a file within an hour.
- It also triggers if there are accesses from 5 or more unique IP addresses with at least 3 anonymous accesses, suggesting a public leak.
-
Sensitive Content: The query checks if the accessed content is from sites with names indicating sensitive information (e.g., "hr", "legal", "finance").
-
Data Collected: For each file accessed, it collects:
- Total number of accesses
- Number of anonymous accesses
- Number of unique IP addresses accessing the file
- List of up to 15 IP addresses
- List of up to 10 file names and 5 site URLs
- Whether the site is considered sensitive
- First and last access times
-
Alert Severity: The severity of the alert is determined based on:
- Whether the site is sensitive and accessed by 10 or more unique IPs (Critical)
- Whether the site is sensitive (High)
- Whether there are 10 or more unique IPs (High)
- Otherwise, it's marked as Medium.
-
Output: The final output includes details such as the file name, site URL, total accesses, anonymous accesses, unique IPs, and the severity of the alert.
