EXT-06: Tracking External Sharing Links

Overview

External sharing links in SharePoint and OneDrive can expose sensitive data if not properly monitored and managed. Anonymous links are particularly risky as they can be forwarded to anyone. This guide helps you gain visibility into existing sharing links, monitor new shares, and remediate risky sharing configurations.

Prerequisites

Required Roles

  • Global Administrator - Full access to all settings
  • SharePoint Administrator - Can access SharePoint admin center and audit logs
  • Compliance Administrator - Access to Microsoft Purview for advanced search
  • Security Reader - Read-only access to audit logs

Required Licenses

  • Microsoft 365 E3/E5 or Business Premium
  • Microsoft Purview (for advanced eDiscovery and DLP)

Time Estimate

  • Initial Audit: 60-90 minutes
  • Report Configuration: 30 minutes
  • Alerting Setup: 20 minutes

Step-by-Step Instructions

Step 1: Enable Audit Logging

Verify unified audit logging is enabled:

  1. Navigate to Microsoft Purview compliance portal (https://compliance.microsoft.com)
  2. Go to Audit in the left navigation
  3. If prompted, click Start recording user and admin activity
  4. Audit logs are retained for 180 days (E5) or 90 days (E3)

Step 2: Search for Sharing Events

Via Purview Audit Log Search

  1. Navigate to PurviewAuditAudit New Search
  2. Configure search parameters:
    • Date range: Last 30 days (or as needed)
    • Activities: Search for specific sharing activities:
ActivityDescription
SharingSetSharing configuration changed
AnonymousLinkCreatedAnyone link created
AnonymousLinkUsedAnyone link accessed
CompanyLinkCreatedCompany-wide link created
SharingInvitationCreatedExternal user invited
SharingLinkCreatedAny sharing link created
SecureLinkCreatedPassword-protected link created
  1. Click Search
  2. Export results for analysis

Via PowerShell (Unified Audit Log)

# Connect to Exchange Online (required for Search-UnifiedAuditLog)
Connect-ExchangeOnline

# Search for sharing events
$startDate = (Get-Date).AddDays(-30)
$endDate = Get-Date

$sharingEvents = Search-UnifiedAuditLog -StartDate $startDate -EndDate $endDate `
    -Operations "SharingSet", "AnonymousLinkCreated", "SharingInvitationCreated", "SharingLinkCreated" `
    -ResultSize 5000

# Parse and format results
$sharingReport = $sharingEvents | ForEach-Object {
    $auditData = $_.AuditData | ConvertFrom-Json

    [PSCustomObject]@{
        Date = $_.CreationDate
        User = $_.UserIds
        Operation = $_.Operations
        SiteUrl = $auditData.SiteUrl
        ItemName = $auditData.SourceFileName
        ItemUrl = $auditData.ObjectId
        TargetUser = $auditData.TargetUserOrGroupName
        SharingType = $auditData.EventData
    }
}

# Display results
$sharingReport | Format-Table -AutoSize

# Export to CSV
$sharingReport | Export-Csv -Path "SharingAudit.csv" -NoTypeInformation

Step 3: Identify Anonymous Links

Anonymous (Anyone) links are the highest risk. Find all active anonymous links:

Using SharePoint Admin Center Reports

  1. Navigate to SharePoint admin center (https://admin.microsoft.com/sharepoint)
  2. Go to ReportsSharing
  3. Review the Sharing links report
  4. Filter by Link type: Anyone

Using PowerShell with PnP

# Connect to SharePoint Online
$siteUrl = "https://yourtenant.sharepoint.com/sites/SiteName"
Connect-PnPOnline -Url $siteUrl -Interactive

# Get all sharing links
$items = Get-PnPListItem -List "Documents" -PageSize 500

$anonymousLinks = @()

foreach ($item in $items) {
    $sharingInfo = Get-PnPFileSharingLink -Identity $item

    foreach ($link in $sharingInfo) {
        if ($link.Link.Type -eq "Anonymous") {
            $anonymousLinks += [PSCustomObject]@{
                FileName = $item.FieldValues.FileLeafRef
                FilePath = $item.FieldValues.FileRef
                LinkType = $link.Link.Type
                LinkScope = $link.Link.Scope
                HasPassword = $link.Link.HasPassword
                Expiration = $link.ExpirationDateTime
                CreatedBy = $link.Link.CreatedBy
            }
        }
    }
}

$anonymousLinks | Export-Csv -Path "AnonymousLinks.csv" -NoTypeInformation
Write-Host "Found $($anonymousLinks.Count) anonymous links"

Step 4: Audit Externally Shared Files

Find all files shared with external users:

# Using SharePoint Search with external sharing filter
Connect-PnPOnline -Url "https://yourtenant.sharepoint.com" -Interactive

# Search for externally shared content
$searchQuery = "IsDocument:True SharedWithUsersOWSUSER:*#ext#*"
$results = Submit-PnPSearchQuery -Query $searchQuery -MaxResults 500 -SelectProperties "Title", "Path", "SharedWithUsersOWSUSER", "LastModifiedTime"

$externalShares = $results.ResultRows | ForEach-Object {
    [PSCustomObject]@{
        Title = $_.Title
        Path = $_.Path
        SharedWith = $_.SharedWithUsersOWSUSER
        LastModified = $_.LastModifiedTime
    }
}

$externalShares | Export-Csv -Path "ExternallySharedFiles.csv" -NoTypeInformation

Step 5: Set Up Sharing Alerts

Create automated alerts for high-risk sharing:

Microsoft Purview Alert Policy

  1. Navigate to PurviewPoliciesAlert policies
  2. Click + New alert policy
  3. Configure:
    • Name: "Anonymous Link Created"
    • Description: "Alert when anyone link is created"
    • Category: Data loss prevention
    • Severity: Medium or High
    • Activity: AnonymousLinkCreated
    • Threshold: Every time this activity occurs
    • Email recipients: Security team
  4. Click Save

Additional Recommended Alerts

Alert NameActivitySeverity
Bulk External SharingMultiple SharingSet in 5 minutesHigh
Sensitive File SharedSharingSet on classified fileHigh
Anonymous Link to Executive FilesAnonymousLinkCreated on exec folderCritical
External Share to Competitor DomainSharingInvitationCreated to blocked domainCritical

Step 6: Integrate with DLP

Prevent sharing of sensitive content:

  1. Navigate to PurviewData loss preventionPolicies
  2. Create or edit a DLP policy
  3. Under Locations, include SharePoint and OneDrive
  4. Configure rules:
    • Condition: Content contains sensitive info (PII, financial data, etc.)
    • Action: Block external sharing
    • User notification: Explain why sharing is blocked
  5. Enable the policy

Step 7: Create Sharing Reports

Power BI Dashboard (Advanced)

  1. Export audit log data regularly to storage
  2. Connect Power BI to audit data
  3. Create visualizations:
    • Sharing trends over time
    • Top sharers
    • Most shared files
    • Anonymous vs authenticated shares
    • External domains receiving shares

Scheduled PowerShell Report

# Weekly sharing report - schedule via Task Scheduler or Azure Automation

Connect-ExchangeOnline

$startDate = (Get-Date).AddDays(-7)
$endDate = Get-Date

# Get sharing summary
$sharingEvents = Search-UnifiedAuditLog -StartDate $startDate -EndDate $endDate `
    -Operations "SharingSet", "AnonymousLinkCreated", "SharingInvitationCreated" `
    -ResultSize 5000

$summary = @{
    TotalShareEvents = $sharingEvents.Count
    AnonymousLinks = ($sharingEvents | Where-Object { $_.Operations -eq "AnonymousLinkCreated" }).Count
    ExternalInvites = ($sharingEvents | Where-Object { $_.Operations -eq "SharingInvitationCreated" }).Count
    UniqueUsers = ($sharingEvents | Select-Object -Unique UserIds).Count
    DateRange = "$($startDate.ToString('yyyy-MM-dd')) to $($endDate.ToString('yyyy-MM-dd'))"
}

# Generate HTML report
$htmlBody = @"
<h2>Weekly Sharing Activity Report</h2>
<p>Period: $($summary.DateRange)</p>
<table border='1'>
<tr><td>Total Sharing Events</td><td>$($summary.TotalShareEvents)</td></tr>
<tr><td>Anonymous Links Created</td><td>$($summary.AnonymousLinks)</td></tr>
<tr><td>External Invitations</td><td>$($summary.ExternalInvites)</td></tr>
<tr><td>Unique Users Sharing</td><td>$($summary.UniqueUsers)</td></tr>
</table>
"@

# Send email
Send-MailMessage -To "security@company.com" -Subject "Weekly Sharing Report" -Body $htmlBody -BodyAsHtml -SmtpServer "smtp.company.com"

Step 8: Remediate Risky Shares

Remove Specific Anonymous Links

Connect-PnPOnline -Url "https://yourtenant.sharepoint.com/sites/SiteName" -Interactive

# Remove anonymous link from a file
$file = Get-PnPFile -Url "/sites/SiteName/Shared Documents/SensitiveFile.docx"
$links = Get-PnPFileSharingLink -Identity $file

foreach ($link in $links) {
    if ($link.Link.Type -eq "Anonymous") {
        Remove-PnPFileSharingLink -Identity $file -LinkId $link.Id -Force
        Write-Host "Removed anonymous link: $($link.Link.WebUrl)"
    }
}

Bulk Anonymous Link Removal

# Remove all anonymous links from a site
$siteUrl = "https://yourtenant.sharepoint.com/sites/TargetSite"
Connect-PnPOnline -Url $siteUrl -Interactive

$lists = Get-PnPList | Where-Object { $_.BaseTemplate -eq 101 } # Document libraries

foreach ($list in $lists) {
    $items = Get-PnPListItem -List $list -PageSize 500

    foreach ($item in $items) {
        $links = Get-PnPFileSharingLink -Identity $item -ErrorAction SilentlyContinue

        foreach ($link in $links) {
            if ($link.Link.Type -eq "Anonymous") {
                Remove-PnPFileSharingLink -Identity $item -LinkId $link.Id -Force
                Write-Host "Removed: $($item.FieldValues.FileRef)"
            }
        }
    }
}

Step 9: Monitor Sharing Trends

Track sharing patterns over time:

// Azure Monitor / Sentinel query
OfficeActivity
| where TimeGenerated > ago(30d)
| where Operation in ("SharingSet", "AnonymousLinkCreated", "SharingInvitationCreated")
| summarize Count = count() by Operation, bin(TimeGenerated, 1d)
| render timechart

Step 10: Implement Governance Controls

Sharing Governance Recommendations

ControlImplementation
Disable anonymous linksSharePoint admin center → Sharing settings
Require link expirationSet maximum days for sharing links
Restrict external domainsAllow list for trusted domains
Enforce site classificationApply sensitivity labels
Educate usersSecurity awareness training

Verification Checklist

After implementing sharing visibility:

  • Audit logging is enabled and verified
  • Initial sharing audit completed
  • Anonymous links inventory created
  • External sharing inventory created
  • Alert policies configured for high-risk sharing
  • DLP policies prevent sensitive data sharing
  • Weekly/monthly reports are scheduled
  • Remediation process documented
  • Trend monitoring is operational
  • Governance controls are in place
  • User education on sharing best practices

Troubleshooting

Issue: Audit log search returns no results

Cause: Audit logging may not be enabled or data hasn't propagated.

Solution:

  1. Verify audit is enabled in Purview
  2. Wait up to 24 hours for new events to appear
  3. Check date range is correct
  4. Verify you have permission to search audit logs

Issue: Cannot find sharing links for a specific file

Cause: File may not have sharing links or permissions are missing.

Solution:

  1. Verify you have site collection admin rights
  2. Check the file directly in SharePoint for sharing status
  3. Use Graph API for more detailed sharing info:
    GET /sites/{site-id}/drive/items/{item-id}/permissions
    

Issue: Too many audit events to process

Cause: Large environment with high sharing volume.

Solution:

  1. Narrow date range
  2. Filter by specific operations
  3. Export to blob storage for Power BI analysis
  4. Use Microsoft Defender for Cloud Apps for automated analysis

Issue: Alert policy not triggering

Cause: Policy may be misconfigured or disabled.

Solution:

  1. Verify policy is enabled
  2. Check the activity filter matches actual events
  3. Verify email recipients are correct
  4. Check spam filters for alert emails
  5. Review policy in Purview for errors

Issue: Cannot determine who created old anonymous links

Cause: Historical data may be outside audit retention period.

Solution:

  1. Audit logs have limited retention (90-180 days)
  2. For older links, check file version history
  3. Review the link's metadata if available
  4. Consider the link owner as the file creator

Issue: Sharing reports show inconsistent numbers

Cause: Different tools may count sharing differently.

Solution:

  1. Use consistent time ranges
  2. Clarify what's being counted (events vs links vs files)
  3. Note that modifying sharing creates new events
  4. Deduplicate by file path when appropriate

Related Resources


Last updated: January 2025