EXT-07: Detecting and Blocking Mail Forwarding
Overview
Automatic email forwarding to external addresses is a common data exfiltration technique. Attackers who compromise an account often set up forwarding rules to silently copy sensitive communications. This guide helps you detect existing forwarding rules, block unauthorized forwarding, and implement ongoing monitoring.
Prerequisites
Required Roles
- Global Administrator - Full access to all settings
- Exchange Administrator - Can manage Exchange Online settings
- Security Administrator - Can view security configurations
- Compliance Administrator - Access to audit logs and DLP
Required Licenses
- Microsoft 365 E3/E5 or Business Premium
- Exchange Online (included in above)
Time Estimate
- Audit Existing Rules: 30-45 minutes
- Policy Configuration: 20-30 minutes
- Monitoring Setup: 15-20 minutes
Step-by-Step Instructions
Step 1: Audit Existing Forwarding Rules
Types of Email Forwarding
| Type | Description | Risk Level |
|---|---|---|
| Inbox Rules | User-created rules in Outlook | High - often used in attacks |
| Transport Rules | Admin-created org-wide rules | Medium - should be documented |
| SMTP Forwarding | Mailbox property forwarding | High - server-side forwarding |
| Delegate Forwarding | Send-on-behalf permissions | Medium - requires additional access |
Step 2: Find SMTP Forwarding
SMTP forwarding is configured at the mailbox level:
Via Exchange Admin Center
- Navigate to Exchange admin center (https://admin.exchange.microsoft.com)
- Go to Recipients → Mailboxes
- For each mailbox, click to view properties
- Check Mail flow settings → Email forwarding
Via PowerShell (Recommended for Bulk)
# Connect to Exchange Online
Connect-ExchangeOnline
# Find all mailboxes with external forwarding
$mailboxes = Get-Mailbox -ResultSize Unlimited
$forwardingReport = @()
foreach ($mbx in $mailboxes) {
if ($mbx.ForwardingSmtpAddress -or $mbx.ForwardingAddress) {
$forwardingReport += [PSCustomObject]@{
DisplayName = $mbx.DisplayName
UserPrincipalName = $mbx.UserPrincipalName
ForwardingSmtpAddress = $mbx.ForwardingSmtpAddress
ForwardingAddress = $mbx.ForwardingAddress
DeliverToMailboxAndForward = $mbx.DeliverToMailboxAndForward
ForwardingType = "SMTP Forwarding"
}
}
}
Write-Host "Found $($forwardingReport.Count) mailboxes with SMTP forwarding"
$forwardingReport | Format-Table -AutoSize
$forwardingReport | Export-Csv -Path "SMTPForwarding.csv" -NoTypeInformation
Step 3: Find Inbox Rules with External Forwarding
Users can create inbox rules that forward or redirect email:
Connect-ExchangeOnline
# Get all mailboxes
$mailboxes = Get-Mailbox -ResultSize Unlimited
$inboxRulesReport = @()
foreach ($mbx in $mailboxes) {
$rules = Get-InboxRule -Mailbox $mbx.UserPrincipalName -ErrorAction SilentlyContinue
foreach ($rule in $rules) {
# Check for forwarding actions
if ($rule.ForwardTo -or $rule.ForwardAsAttachmentTo -or $rule.RedirectTo) {
# Check if forwarding to external
$targets = @()
$targets += $rule.ForwardTo
$targets += $rule.ForwardAsAttachmentTo
$targets += $rule.RedirectTo
foreach ($target in $targets) {
if ($target -and $target -notlike "*@$(($mbx.PrimarySmtpAddress -split '@')[1])") {
$inboxRulesReport += [PSCustomObject]@{
Mailbox = $mbx.UserPrincipalName
RuleName = $rule.Name
RuleEnabled = $rule.Enabled
ForwardTo = $rule.ForwardTo -join "; "
ForwardAsAttachment = $rule.ForwardAsAttachmentTo -join "; "
RedirectTo = $rule.RedirectTo -join "; "
RuleIdentity = $rule.Identity
}
}
}
}
}
}
Write-Host "Found $($inboxRulesReport.Count) inbox rules forwarding externally"
$inboxRulesReport | Format-Table Mailbox, RuleName, ForwardTo, RedirectTo -AutoSize
$inboxRulesReport | Export-Csv -Path "InboxRulesForwarding.csv" -NoTypeInformation
Step 4: Find Transport Rules with External Forwarding
Check admin-configured transport rules:
Connect-ExchangeOnline
# Get all transport rules
$transportRules = Get-TransportRule
$externalForwardingRules = $transportRules | Where-Object {
$_.BlindCopyTo -or $_.CopyTo -or $_.RedirectMessageTo
} | Select-Object Name, State, Priority, BlindCopyTo, CopyTo, RedirectMessageTo
$externalForwardingRules | Format-Table -AutoSize
if ($externalForwardingRules.Count -gt 0) {
Write-Host "Review these transport rules for external forwarding" -ForegroundColor Yellow
}
Step 5: Block External Forwarding
Option A: Block at Organization Level (Recommended)
- Navigate to Exchange admin center
- Go to Mail flow → Remote domains
- Click on Default (or create a new policy for specific domains)
- Under Reply types allowed, disable:
- Automatic replies
- Automatic forwarding
- Click Save
Via PowerShell
Connect-ExchangeOnline
# Block auto-forwarding for the default remote domain (affects all external domains)
Set-RemoteDomain -Identity Default -AutoForwardEnabled $false
# Verify the change
Get-RemoteDomain -Identity Default | Select-Object Name, AutoForwardEnabled
Option B: Create Transport Rule to Block Forwarding
For more granular control:
Connect-ExchangeOnline
# Create transport rule to block external forwarding
New-TransportRule -Name "Block External Auto-Forwarding" `
-MessageTypeMatches "AutoForward" `
-SentToScope "NotInOrganization" `
-RejectMessageReasonText "External email forwarding is not permitted. Contact IT for exceptions." `
-ExceptIfSentTo "approved-external@partner.com" `
-ExceptIfFrom "exception-user@company.com" `
-Priority 0 `
-Mode Enforce
Write-Host "Transport rule created to block external forwarding"
Option C: Block via Outbound Spam Policy (Microsoft 365)
- Navigate to Microsoft Defender portal (https://security.microsoft.com)
- Go to Policies & rules → Threat policies → Anti-spam
- Click Anti-spam outbound policy (Default)
- Under Forwarding rules, set:
- Automatic forwarding rules: Off - Forwarding is disabled
- Click Save
Step 6: Remove Unauthorized Forwarding
Remove SMTP Forwarding
Connect-ExchangeOnline
# Remove forwarding from a specific mailbox
$mailbox = "user@company.com"
Set-Mailbox -Identity $mailbox -ForwardingSmtpAddress $null -ForwardingAddress $null
Write-Host "Forwarding removed from $mailbox"
Remove Inbox Rules
Connect-ExchangeOnline
# Remove specific inbox rule
$mailbox = "user@company.com"
$ruleName = "Forward to personal"
Remove-InboxRule -Mailbox $mailbox -Identity $ruleName -Confirm:$false
Write-Host "Inbox rule removed"
Bulk Remove All External Forwarding Rules
Connect-ExchangeOnline
# Remove all inbox rules that forward externally
$mailboxes = Get-Mailbox -ResultSize Unlimited
foreach ($mbx in $mailboxes) {
$rules = Get-InboxRule -Mailbox $mbx.UserPrincipalName -ErrorAction SilentlyContinue
foreach ($rule in $rules) {
if ($rule.ForwardTo -or $rule.ForwardAsAttachmentTo -or $rule.RedirectTo) {
Remove-InboxRule -Mailbox $mbx.UserPrincipalName -Identity $rule.Name -Confirm:$false
Write-Host "Removed rule '$($rule.Name)' from $($mbx.UserPrincipalName)"
}
}
# Also remove SMTP forwarding
if ($mbx.ForwardingSmtpAddress -or $mbx.ForwardingAddress) {
Set-Mailbox -Identity $mbx.UserPrincipalName -ForwardingSmtpAddress $null -ForwardingAddress $null
Write-Host "Removed SMTP forwarding from $($mbx.UserPrincipalName)"
}
}
Step 7: Configure Exceptions for Legitimate Use
Some forwarding may be legitimate (e.g., shared mailboxes, integrations):
Allow Specific Users to Forward
# Create transport rule with exceptions
Set-TransportRule -Identity "Block External Auto-Forwarding" `
-ExceptIfFrom "legitimate-forwarder@company.com", "integration-mailbox@company.com"
Create Exception Group
# Create distribution group for forwarding exceptions
New-DistributionGroup -Name "Mail Forwarding Exceptions" -Type Security
# Add legitimate users
Add-DistributionGroupMember -Identity "Mail Forwarding Exceptions" -Member "user@company.com"
# Update transport rule to except this group
Set-TransportRule -Identity "Block External Auto-Forwarding" `
-ExceptIfFromMemberOf "Mail Forwarding Exceptions"
Step 8: Set Up Monitoring and Alerts
Alert on New Forwarding Rules
- Navigate to Microsoft Defender portal → Policies & rules
- Go to Alert policies
- Create new alert:
- Name: "Inbox Rule Created with External Forwarding"
- Category: Threat management
- Activity: New-InboxRule with forwarding action
- Severity: High
- Recipients: Security team
Use Audit Log for Detection
Connect-ExchangeOnline
# Search for recent forwarding rule creations
$startDate = (Get-Date).AddDays(-7)
$endDate = Get-Date
$auditLogs = Search-UnifiedAuditLog -StartDate $startDate -EndDate $endDate `
-Operations "New-InboxRule", "Set-InboxRule", "Set-Mailbox" `
-ResultSize 1000
$forwardingChanges = $auditLogs | ForEach-Object {
$auditData = $_.AuditData | ConvertFrom-Json
# Check if forwarding-related
if ($auditData.Parameters.Name -match "ForwardTo|ForwardAsAttachment|RedirectTo|ForwardingSmtpAddress") {
[PSCustomObject]@{
Date = $_.CreationDate
User = $_.UserIds
Operation = $_.Operations
Details = $auditData.Parameters | ConvertTo-Json -Compress
}
}
}
$forwardingChanges | Format-Table -AutoSize
Step 9: Implement Proactive Detection
Daily Forwarding Check Script
# Schedule via Azure Automation or Task Scheduler
Connect-ExchangeOnline
$previousReport = Import-Csv -Path "LastForwardingSnapshot.csv" -ErrorAction SilentlyContinue
$currentForwarding = @()
$mailboxes = Get-Mailbox -ResultSize Unlimited
foreach ($mbx in $mailboxes) {
if ($mbx.ForwardingSmtpAddress) {
$currentForwarding += [PSCustomObject]@{
Mailbox = $mbx.UserPrincipalName
ForwardTo = $mbx.ForwardingSmtpAddress.ToString()
Type = "SMTP"
}
}
$rules = Get-InboxRule -Mailbox $mbx.UserPrincipalName -ErrorAction SilentlyContinue
foreach ($rule in $rules) {
if ($rule.ForwardTo -or $rule.RedirectTo) {
$currentForwarding += [PSCustomObject]@{
Mailbox = $mbx.UserPrincipalName
ForwardTo = ($rule.ForwardTo + $rule.RedirectTo) -join "; "
Type = "InboxRule"
}
}
}
}
# Compare with previous
$newForwarding = $currentForwarding | Where-Object {
$current = $_
-not ($previousReport | Where-Object { $_.Mailbox -eq $current.Mailbox -and $_.ForwardTo -eq $current.ForwardTo })
}
if ($newForwarding.Count -gt 0) {
Write-Host "NEW FORWARDING DETECTED!" -ForegroundColor Red
$newForwarding | Format-Table
# Send alert
$body = $newForwarding | ConvertTo-Html -Fragment
Send-MailMessage -To "security@company.com" -Subject "Alert: New Email Forwarding Detected" -Body $body -BodyAsHtml
}
# Save current snapshot
$currentForwarding | Export-Csv -Path "LastForwardingSnapshot.csv" -NoTypeInformation
Step 10: Implement Defender for Cloud Apps Detection
Use MCAS/Defender for Cloud Apps for advanced detection:
- Navigate to Microsoft Defender portal → Cloud apps → Policies
- Create new policy:
- Policy type: Activity policy
- Activities matching all of the following:
- Activity type = New-InboxRule
- Activity parameter contains "ForwardTo" or "RedirectTo"
- Alerts: Create alert, send to security team
- Governance actions: Suspend user (optional, for high confidence)
Verification Checklist
After implementing mail forwarding controls:
- Initial audit completed for SMTP forwarding
- Initial audit completed for inbox rules
- Transport rules reviewed for forwarding
- External auto-forwarding blocked at remote domain level
- Transport rule or outbound spam policy blocking forwarding
- Unauthorized forwarding removed
- Exception process documented and implemented
- Alert policies configured for new forwarding rules
- Proactive detection script scheduled
- Defender for Cloud Apps policy created
- Security team notified of baseline findings
Troubleshooting
Issue: Legitimate forwarding stopped working
Cause: Blocking policies may be too broad.
Solution:
- Identify the specific forwarding requirement
- Add user to exception group
- Or add specific exception to transport rule
- Document the business justification
Issue: Cannot find forwarding rules in audit log
Cause: Audit log search may have wrong date range or filters.
Solution:
- Expand date range
- Search for "New-InboxRule" and "Set-Mailbox" operations
- Verify audit logging is enabled
- Check retention period hasn't expired
Issue: Forwarding rule is hidden from user
Cause: Attackers often create hidden rules.
Solution:
# Show all inbox rules including hidden ones
Get-InboxRule -Mailbox "user@company.com" -IncludeHidden
# Remove hidden rule by identity
Remove-InboxRule -Mailbox "user@company.com" -Identity "RuleGUID" -Confirm:$false
Issue: External forwarding still works after blocking
Cause: Multiple forwarding mechanisms exist.
Solution:
- Verify all three blocking methods:
- Remote domain auto-forward disabled
- Transport rule blocking auto-forward
- Outbound spam policy set to "Off"
- Check for transport rule exceptions
- Verify rules are processed in correct priority
Issue: Client-side rules bypass server policies
Cause: Outlook client rules may run locally.
Solution:
- Server-side rules (created via OWA or PowerShell) are always enforced
- For client rules, they execute before server policies
- Block at network/firewall level for complete protection
- Use DLP policies as additional layer
Issue: Forwarding works for some users but not others
Cause: Mailbox-level or user-level exceptions may exist.
Solution:
- Check if user is in exception group
- Review user's specific mailbox settings
- Check for user-specific transport rule exceptions
- Verify user license includes Exchange Online
Related Resources
- Control automatic external email forwarding
- Configure remote domains
- Mail flow rules in Exchange Online
- Alert policies in Defender for Office 365
Last updated: January 2025