The following is a lightly anonymised account of a real DFIR engagement. Client identifiers, staff names, and financial specifics have been altered. All technical artifacts, commands, and findings are presented as they occurred. We are publishing this case because BEC is the highest-grossing cybercrime category on earth and most organisations still do not understand how little technical sophistication it actually requires — or how much forensic evidence it leaves behind on the attacker’s side.
| Parameter | Detail |
|---|---|
| Case Type | Business Email Compromise (BEC) — Wire Fraud, Silent Inbox Monitoring |
| Industry | Legal Services (Mid-size Law Firm, Real Estate & Corporate Practice) |
| Duration | 4 days on-site, 11 days remote — concurrent with financial clawback attempt |
| Year | Year 6 of operations |
| Notoriety | The one where the attacker’s patience was genuinely more impressive than their technique |
The Engagement
How We Were Called In
The call came at 3:18 PM on a Thursday. The firm’s managing partner had just been informed by their client — a commercial real estate developer — that the $2.3 million wire transfer sent that morning to complete a property acquisition had arrived at the wrong bank. Specifically, it had arrived at a bank account that the developer had never provided, at a financial institution they had never heard of, in a jurisdiction they had not expected. The developer had called to confirm receipt. The funds were not there.
The wire had been sent six hours earlier. The originating bank had been notified and a recall initiated. We were engaged simultaneously. In BEC wire fraud, six hours is a very long time. The money was almost certainly already moving.
BEC is not a technical problem that occasionally involves money. It is a financial crime that occasionally involves technology. The forensics come second. The bank call comes first.
The Environment
The firm had 47 attorneys and approximately 90 total staff. Their email environment was Microsoft 365 Business Premium — an important detail, because Premium includes Defender for Office 365 Plan 1 and the full Unified Audit Log at 90-day retention. They had not configured any Defender for Office 365 policies beyond the defaults. Safe Links was enabled. Safe Attachments was not. Anti-phishing policy was at default sensitivity. The audit log was enabled but had never been reviewed.
The CFO’s account — the one that received and responded to the wire instruction — was the starting point for everything.
Finding 1: The Fraudulent Email — Header Analysis
Path: Exported from Outlook: File → Save As → .eml | Or: M365 Admin → Message Trace → Export headers
- Full headers include: Received chain (hop-by-hop), Return-Path, Authentication-Results (SPF/DKIM/DMARC)
- Authentication-Results header added by the RECEIVING mail server — not forgeable by sender
X-Originating-IP,X-Mailer, andX-Forwarded-Tocan reveal infrastructure even through webmail- Microsoft adds
X-MS-Exchange-CrossTenant-AuthAsandX-MS-Exchange-Organization-SCL(spam confidence)
The fraudulent wire instruction had been sent from an email address that appeared, at a glance, to be the developer’s CFO: the display name was correct, the signature block was correct, and the email address shown in the Outlook preview was correct. The fraud was in the actual sending domain — a lookalike registered four days before the attack.
# Email header dissection — SPF/DKIM/DMARC all pass for attacker-controlled lookalike domain From: James ████████ <j.████████@████████-properties.com> ← LEGITIMATE display # Actual sending domain (visible only in full headers / raw message): Return-Path: <j.████████@████████-propertiess.com> ← NOTE: double 's' in 'properties' X-Originating-IP: 185.234.██.██ ← Romanian VPS, not developer's known IP range # Authentication results (added by firm's M365 on receipt): Authentication-Results: spf=pass (sender IP 185.234.██.██) smtp.mailfrom=████████-propertiess.com; dkim=pass (signature was valid) header.d=████████-propertiess.com; dmarc=pass action=none header.from=████████-propertiess.com; # All three authentication checks PASS — because the attacker controls the lookalike domain # SPF: attacker added their VPS IP to the lookalike domain's SPF record # DKIM: attacker generated valid DKIM keys for the lookalike domain # DMARC: lookalike domain had p=none — monitors but takes no action # Microsoft Spam Confidence Level: X-MS-Exchange-Organization-SCL: -1 ← SCL -1 = bypass all spam filtering (trusted sender list) # Why SCL -1? The developer's REAL domain was on the firm's trusted sender list. # M365 applied the trust to the lookalike because domain-matching was not strict.
This is the mechanism that makes BEC effective at scale: the attacker registers a lookalike domain, configures legitimate SPF, DKIM, and DMARC records for that domain (a 20-minute task), and sends email that passes every authentication check. The authentication infrastructure is working exactly as designed — it is authenticating that the email genuinely came from the lookalike domain. It cannot tell you whether the lookalike domain is malicious.
# Lookalike domain OSINT — SPF/DKIM/DMARC all pre-configured, MX active to receive replies # WHOIS: whois ████████-propertiess.com # Registrar: Namecheap | Registered: 2024-██-██ (4 days before fraudulent email) # Registrant: Privacy-protected # DNS records (dig): dig TXT ████████-propertiess.com # v=spf1 ip4:185.234.██.0/24 ~all ← attacker's VPS subnet explicitly authorized dig TXT selector1._domainkey.████████-propertiess.com # v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA... ← valid DKIM public key dig TXT _dmarc.████████-propertiess.com # v=DMARC1; p=none; rua=mailto:reports@████████-propertiess.com # p=none: even if DMARC failed, no action would be taken # MX records (can this domain receive email?): dig MX ████████-propertiess.com # 10 mail.████████-propertiess.com ← YES. Attacker could receive replies. # VirusTotal domain report: # First seen: 2024-██-██ | Detections: 0/88 | Categories: uncategorized # Passive DNS: only 1 IP ever resolved — 185.234.██.██ (Romania, Frantech ASN)
Lookalike Domain Registered 4 Days Prior — Full SPF/DKIM/DMARC Authentication Bypasses Filtering
The fraudulent wire instruction was sent from a visually identical lookalike domain (double-letter typosquat) registered four days before the attack. The attacker pre-configured valid SPF, DKIM, and DMARC records — all three authentication checks passed. The domain had an active MX record, allowing the attacker to receive and reply to any responses. Microsoft’s SCL assigned -1 (trusted sender) because the firm’s allowed-sender list used domain prefix matching. The email bypassed all spam and anti-phishing controls.
Finding 2: The Silent Phase — 21 Days of Inbox Monitoring
Path: UAL Operation: MailItemsAccessed | Requires: E3+ licence with audit enabled
MailItemsAccessed: records every read operation against a mailbox — client type, IP, folder, message IDsOperationProperties.MailAccessType: ‘Bind’ = specific message read; ‘Sync’ = bulk folder sync (IMAP)ClientInfoStringidentifies the access method: OWA, Outlook, MAPI, IMAP, REST (Graph API)- CRITICAL: Sync events group many messages — look for unusual Sync bursts from non-Outlook clients
- Availability: only in E3/E5 — M365 Business Basic does NOT log MailItemsAccessed
The immediate question in any BEC investigation is: how did the attacker know about this specific wire transfer? The answer is almost always the same — they had been reading the target’s email for weeks. The UAL MailItemsAccessed operation is the artifact that proves it.
# MailItemsAccessed — REST/Graph API reads from Romanian VPS, 21 days prior to fraud # Pull MailItemsAccessed for CFO mailbox — 90 day lookback Connect-ExchangeOnline Search-UnifiedAuditLog \ -StartDate (Get-Date).AddDays(-90) \ -EndDate (Get-Date) \ -Operations MailItemsAccessed \ -UserIds cfo@firm.com \ -ResultSize 5000 | ForEach-Object { $d = $_.AuditData | ConvertFrom-Json [PSCustomObject]@{ Time = $_.CreationDate IP = $d.ClientIPAddress ClientInfo = $d.ClientInfoString AccessType = ($d.OperationProperties | Where-Object Name -eq 'MailAccessType').Value FolderPath = $d.Folders[0].Path } } | Export-Csv .\cfo_mailaccess.csv -NoTypeInformation # Group by IP and ClientInfo to identify anomalous access patterns: # IP ClientInfoString AccessCount DateRange # 192.168.█.███ Outlook/16.0 (Windows; MAPI) 4,847 [normal office access] # 198.51.100.██ Outlook/16.0 (Windows; MAPI) 312 [confirmed home IP] # 185.234.██.██ Client=REST;Action=GraphQL;Service=OWA 1,203 ← ANOMALOUS # The anomalous IP: Romanian VPS (same as fraudulent email sender IP) # ClientInfo: REST/GraphQL access — Graph API or OAuth app, NOT a standard Outlook client # First anomalous access: 21 days before the fraudulent wire instruction # Last anomalous access: 4 hours before the fraudulent email was sent
1,203 email access events from the attacker’s IP over 21 days. That averages to roughly 57 reads per day — not a flood, not an obvious anomaly in raw volume terms, but a steady cadence of someone checking in on a monitored inbox. The attacker was not downloading everything. They were reading selectively, and the UAL Bind events showed which threads they had prioritised.
# Bind event reconstruction — attacker-accessed message subjects, full 21-day thread surveillance $anomalous_ip = '185.234.██.██' $bind_events = Search-UnifiedAuditLog \ -Operations MailItemsAccessed \ -UserIds cfo@firm.com \ -StartDate (Get-Date).AddDays(-90) \ -EndDate (Get-Date) \ -ResultSize 5000 | Where-Object { ($_.AuditData | ConvertFrom-Json).ClientIPAddress -eq $anomalous_ip } # Extract InternetMessageIds from Bind events — cross-reference against mailbox $bind_events | ForEach-Object { ($_.AuditData | ConvertFrom-Json).Folders.FolderItems } | Select-Object -ExpandProperty InternetMessageId | Sort-Object -Unique | ForEach-Object { Get-MgUserMessage -UserId cfo@firm.com -Filter "internetMessageId eq '$_'" | Select-Object Subject, ReceivedDateTime, From } # RESULTS (subset — attacker-accessed messages, chronological): # ReceivedDateTime Subject From # T-21d Re: ████ Commercial Closing — docs attached developer.cfo@... # T-20d Re: Wire instructions for ████ acquisition developer.cfo@... # T-18d Updated wire confirmation — escrow contact firm.partner@... # T-15d Re: Closing date confirmed — ████-██-██ developer.cfo@... # T-7d Final wire amount confirmed: $2,341,500 developer.cfo@... # T-4d Re: Tuesday closing — anything else needed? developer.cfo@... # T-1d Wire ready to send — please confirm account details developer.cfo@...
The attacker read every email in the closing thread, in order, over three weeks. They waited until the wire amount was confirmed and the account details had been exchanged before they moved. This is patience, not technical sophistication.
21 Days of Silent Inbox Surveillance — 1,203 REST/Graph API Access Events from Attacker IP
UAL MailItemsAccessed records confirmed the attacker had authenticated to the CFO’s mailbox via REST API from a Romanian VPS beginning 21 days before the fraudulent email. Bind event analysis recovered the specific message IDs accessed — every email in the real estate closing thread, including the message confirming the exact wire amount ($2,341,500) and the legitimate bank account details. The attacker monitored the thread to completion, then struck in the final 24-hour window before the wire was due.
Finding 3: How the Account Was Compromised — OAuth App Consent
Path: Azure Portal → Azure Active Directory → Audit Logs → Activity: Consent to application
- Activity type: ‘Consent to application’ — records when a user grants OAuth permissions to a third-party app
- Key fields: InitiatedBy (user), Target (app name + AppId), additionalDetails (permissions granted)
- Also check: ‘Add OAuth2PermissionGrant’ in audit log — same event, different display depending on tenant config
- Entra ID Protection: OAuth phishing often precedes MailItemsAccessed anomalies by 24–72 hours
- Revoke immediately: Azure AD → Enterprise Applications → [App] → Delete, then revoke all refresh tokens
The question that takes longest to answer in BEC investigations is almost always: how did they get in? In this case, there was no password compromise in the traditional sense. The CFO’s password had never been stolen. Instead, the attacker had used a technique that bypasses passwords entirely: OAuth application phishing, sometimes called ‘consent phishing’ or ‘illicit consent grant.’
The mechanism is elegant in a profoundly irritating way. The attacker sends a link to a Microsoft OAuth authorization page. The page is a real Microsoft page — no spoofing, no lookalike domain. The CFO clicks ‘Accept,’ and in doing so, they grant a malicious application registered in Azure AD read access to their mailbox. No password changes hands. MFA is never triggered. Microsoft’s own OAuth infrastructure does the rest.
# Azure AD Audit Log — illicit OAuth app consent, Mail.Read + offline_access granted by CFO Connect-MgGraph -Scopes 'AuditLog.Read.All','Directory.Read.All' Get-MgAuditLogDirectoryAudit -Filter \ "activityDisplayName eq 'Consent to application' and " + "initiatedBy/user/userPrincipalName eq 'cfo@firm.com'" \ -Top 50 | ForEach-Object { [PSCustomObject]@{ Time = $_.ActivityDateTime App = ($_.TargetResources | Where-Object Type -eq 'ServicePrincipal').DisplayName AppId = ($_.TargetResources | Where-Object Type -eq 'ServicePrincipal').Id Permissions = ($_.AdditionalDetails | Where-Object Key -eq 'Permissions').Value IP = $_.InitiatedBy.User.IPAddress } } # OUTPUT: Time App AppId Permissions 2024-██-██T16:41:02Z 'Microsoft Secure Mail Reader' ██████-████-... Mail.Read, offline_access # 'Microsoft Secure Mail Reader' — not a Microsoft product. Attacker-registered app name. # Permissions granted: Mail.Read (read all mailbox content) + offline_access (refresh token) # offline_access = no expiry on access without user re-authentication # This consent event occurred 21 days before the fraud — matching MailItemsAccessed first anomaly
The malicious application was named ‘Microsoft Secure Mail Reader’ — a name chosen specifically to look plausible on the Microsoft OAuth consent screen, which lists the app name prominently and the permissions in smaller text below. The CFO had received a phishing email directing them to click a link to ‘verify their Microsoft 365 account security settings.’ The link went to a legitimate Microsoft authorization URL with the malicious app’s client_id embedded.
# OAuth phishing URL reconstruction — legitimate Microsoft authorization endpoint, malicious app client_id https://login.microsoftonline.com/common/oauth2/v2.0/authorize ?client_id=██████-████-████-████-████████████ ← malicious app's Azure AD registration &response_type=code &redirect_uri=https://██████-██████.azurewebsites.net/callback ← attacker's Azure Web App &scope=Mail.Read%20offline_access &state=██████ # This is a REAL Microsoft URL — nothing to block at network layer # The only indicator is the client_id, which requires Azure AD app registration lookup # Check for other users who consented to the same malicious app: Get-MgServicePrincipal -ServicePrincipalId ██████-████-████-████-████████████ | Get-MgServicePrincipalOauth2PermissionGrant | Select-Object PrincipalId, Scope # OUTPUT: 1 additional user — a junior associate who had also consented # (their mailbox was not targeted — lower-value intelligence)
Illicit OAuth Consent Grant — Mail.Read + offline_access, No Password Compromise, MFA Irrelevant
The account compromise was achieved via OAuth application phishing (‘illicit consent grant’). The CFO was directed to a legitimate Microsoft OAuth authorization page and granted a malicious Azure AD-registered application named ‘Microsoft Secure Mail Reader’ permission to read their entire mailbox (Mail.Read) with non-expiring access (offline_access). MFA was never triggered because no password was used. The attacker’s app used the issued refresh token to read the mailbox via Graph API for 21 days without re-authentication. A second user (junior associate) had also consented to the same app.
Finding 4: The Interception — Thread Hijack Reconstruction
Path: Exchange Admin Center → Mail Flow → Message Trace | PowerShell: Get-MessageTrace
- Message Trace covers 10 days in the EAC UI; 90 days via
Start-HistoricalSearch - Key fields: MessageId, SenderAddress, RecipientAddress, Subject, Status, ToIP (destination MTA)
- Status ‘Delivered’ = accepted by next-hop MTA; ‘GettingStatus’ = extended trace in progress
- Cross-reference MessageId with UAL MailItemsAccessed to confirm attacker read the real replies
- Use
Get-MessageTraceDetail -MessageIdto get full delivery hop chain per message
The attacker’s tradecraft in the interception itself was simple but effective. Rather than compromising the developer’s email account — a harder target — they impersonated it. After 21 days of surveillance, they knew the thread, the parties, the tone, the closing timeline, and the exact moment the CFO would be expecting wire confirmation details.
The fraudulent email arrived the morning of the closing. It was a reply to a real thread — the attacker had copied the In-Reply-To header from a legitimately observed email, making their message appear in the same conversation chain in Outlook. The content: a brief, professionally worded note from ‘James’ explaining that the escrow company had changed banks and providing updated wire instructions. The signature block was copied verbatim from a real email James had sent three days earlier.
# Message trace — fraudulent email delivery path, anti-spam bypass, and time-to-wire-sent Get-MessageTrace -SenderAddress j.████████@████████-propertiess.com \ -RecipientAddress cfo@firm.com \ -StartDate (Get-Date).AddDays(-7) \ -EndDate (Get-Date) | Select-Object Received, SenderAddress, RecipientAddress, Subject, Status, MessageId # OUTPUT: Received SenderAddress Status Subject 2024-██-██ 09:14:33 j.████████@████████-propertiess.com Delivered Re: ████ Commercial Closing... # Delivery hops: # 1. Submitted from: 185.234.██.██ (Romanian VPS) → smtp.████████-propertiess.com (attacker MTA) # 2. Relayed to: firm-com.mail.protection.outlook.com (M365 inbound MX) # 3. Anti-spam verdict: SCL -1 (bypass — domain on trusted list) # 4. Delivered to: cfo@firm.com inbox — 09:14:33 # Time from delivery to CFO opening the email: # MailItemsAccessed Bind event for this MessageId: 09:16:51 — 2 min 18 sec # Time from CFO opening to wire being sent: # Bank wire log (provided by firm's finance team): 10:47:00 — 1 hour 30 minutes
The attacker also took a precaution that many BEC operators skip: they monitored the CFO’s mailbox in near-real-time during the critical window. Between 09:14 (delivery) and 10:47 (wire sent), the attacker’s REST API access log showed 14 Bind events against the CFO’s inbox — checking for replies, checking whether the CFO had forwarded the email for verification, checking whether anything had gone wrong. When the wire confirmation email arrived from the CFO’s bank at 10:52 — five minutes after the wire was sent — the attacker read it within 90 seconds.
Thread Hijack via In-Reply-To Header Spoofing — Wire Sent 93 Minutes After Fraudulent Email Opened
The fraudulent email used the legitimate conversation’s In-Reply-To header, causing it to appear within the correct thread in the CFO’s Outlook client. Delivery-to-open was 2 minutes 18 seconds. Open-to-wire was 93 minutes. The attacker monitored the mailbox in real-time during the attack window (14 REST API reads in 93 minutes) to detect any indication of suspicion. The bank confirmation email was accessed by the attacker 90 seconds after arrival — before the CFO’s firm had even begun to suspect the fraud.
Finding 5: Attacker Infrastructure — The Mule Account Chain
Path: Wire transfer records (bank-provided) | FinCEN SAR database | Passive DNS | OSINT
- Wire trace: correspondent bank chain from originating institution to first-hop receiving account
- BEC mule accounts: typically domestic US/EU accounts registered 2–8 weeks before use, personal or LLC
- FinCEN BSA E-Filing: SAR filings on accounts — searchable via law enforcement channels (not public)
- Time is critical: most BEC funds move within 24–48 hours via layering to international accounts
- FBI IC3 complaint + FinCEN Financial Crimes Enforcement Network contact = fastest clawback path
In parallel with the forensic investigation, the firm’s bank had initiated a wire recall and the firm’s litigation counsel had filed an emergency FBI IC3 complaint. We supported both by documenting the attack chain and providing IOCs to law enforcement. The financial trace is not traditional DFIR work — but in BEC cases, it is inseparable from the investigation, because the attacker’s infrastructure overlaps between the technical and financial layers.
# Wire trace and funds movement timeline — $2.1M converted to crypto within 9 hours Originating Bank: Royal ████ Bank — Toronto, Canada Originating Account: ████████████████ (firm's trust account) Amount: CAD $2,341,500.00 Value Date: 2024-██-██ Wire Method: SWIFT MT103 Receiving Bank: ████████████ Bank — Miami, Florida, USA Receiving Account: ████████████████ Account Name: ████████ Global Solutions LLC ← registered Florida LLC, 6 weeks old BIC/SWIFT: ████████XXX # OSINT on receiving entity: # Florida SOS lookup: ████████ Global Solutions LLC # Filed: 2024-██-██ (6 weeks before wire) ← matches typical BEC mule account timing # Registered Agent: private registered agent service (no identifiable principal) # Authorized Member: name matches known money mule recruitment forum persona # Funds movement (from FBI financial intelligence, 48hr post-complaint): # T+4 hours: $2,341,500 received at Miami account # T+6 hours: $2,100,000 wired to intermediary — ████████ Bank, Hong Kong # T+9 hours: $1,900,000 onward-wired to virtual asset service provider (VASP) # T+11 hours: Funds converted to USDT (Tether) — wallet address: 0x████████ # T+18 hours: $241,500 remaining in Miami account — FROZEN on bank hold request # Recovery: $241,500 recovered (10.3% of total wire amount)
Of the $2,341,500 wired, $241,500 was recovered via bank hold — a 10.3% recovery rate. The remaining $2.1 million moved through a domestic mule account, across a correspondent bank in Hong Kong, and into a virtual asset service provider within nine hours of the wire clearing. Once converted to USDT on a non-KYC exchange, traceability collapsed to blockchain analysis — possible but slow, and by that point the assets had already been further dispersed across multiple wallets.
Ten percent recovery is, by the grim arithmetic of BEC wire fraud, not a bad outcome. The median recovery rate for BEC wire fraud reported to FBI IC3 is approximately 4%. The reason we did better than median was that the bank call happened within six hours and the IC3 complaint was filed with complete technical documentation the same afternoon. Documentation quality and speed are the only variables that remain in the victim’s control at that point.
Funds Moved to Crypto in 9 Hours — $241,500 Recovered (10.3%), $2.1M to USDT
The receiving mule account (a 6-week-old Florida LLC) moved funds in three hops within 11 hours: domestic bank → Hong Kong correspondent → VASP → USDT. A bank hold request on the Miami account recovered $241,500. The VASP wallet received the remaining funds but had no KYC requirement; blockchain tracing identified subsequent dispersion to 7 downstream wallets. Law enforcement referral was made. Prosecution prospects at time of writing: the Florida mule was identified and charged; operators remain unattributed beyond the Romanian VPS infrastructure cluster.
Finding 6: Persistence — The Transport Rule Nobody Knew About
Path: Exchange Admin Center → Mail Flow → Rules | UAL: New-TransportRule, New-InboxRule
- Transport rules (admin-level) can silently redirect/delete mail before it reaches the inbox — invisible to users
- Inbox rules (user-level) visible in Outlook — attacker-created rules may forward or delete replies
- UAL
New-TransportRule: confirms if attacker escalated to admin-level mail flow manipulation - Check: any rule created in the anomalous IP window that matches keywords related to the fraud topic
- BEC operators frequently create deletion rules for terms like ‘fraud’, ‘verify’, ‘unusual’ to suppress warnings
On day two of the investigation, reviewing the CFO’s inbox rules, we found something that had not been in the initial scope: a rule created from the attacker’s IP address three days before the fraudulent wire instruction was sent. It was not a forwarding rule. It was a deletion rule.
# Inbox deletion rule — silently deletes fraud alerts and verification emails containing key terms Get-InboxRule -Mailbox cfo@firm.com -IncludeHidden | \ Select-Object Name, Enabled, DeleteMessage, MoveToFolder, SubjectContainsWords, SubjectOrBodyContainsWords, From, @{N='Created';E={$_.WhenChanged}} | Sort-Object Created # RESULT — anomalous rule (attacker-created, already disabled post-incident): Name: 'junk-filter-update' Enabled: False ← disabled as part of IR containment DeleteMessage: True ← permanently deletes matching email, bypasses Deleted Items SubjectOrBodyContainsWords: {unusual, verify wire, confirm account, bank change, fraud alert, suspicious, security alert, stop payment, recall} # This rule would have silently deleted any email containing fraud-related keywords # before the CFO ever saw it — including bank fraud alerts, IT security notifications, # and any reply from the developer's real CFO saying 'we didn't send new wire instructions' # UAL confirmation of rule creation: # Operation: New-InboxRule | Time: T-3 days, 02:17 UTC | ClientIP: 185.234.██.██ # The rule was created at 2:17 AM — when the CFO was not at their desk.
The deletion rule is the detail that makes BEC investigations particularly unsettling on reflection. The attacker had anticipated the fraud-detection response and pre-deleted it. Any email containing words like ‘verify wire,’ ‘stop payment,’ ‘bank change,’ or ‘fraud alert’ would have been permanently deleted before the CFO saw it. The attacker was not just stealing — they were actively managing the victim’s awareness.
In this case, the fraud was detected not because the deletion rule failed, but because the developer’s real CFO had called on the phone to confirm receipt. Voice calls remain outside the attacker’s control surface. This detail ended up in the firm’s post-incident security training.
Deletion Inbox Rule Pre-Created 3 Days Before Fraud — Silently Suppressed Fraud Alerts
The attacker created an inbox deletion rule named ‘junk-filter-update’ at 02:17 UTC (2:17 AM local time) three days before the fraudulent email was sent. The rule permanently deleted any email containing fraud, verification, or payment-related keywords — including bank fraud alerts, security notifications, and any verification requests from the developer’s actual team. The rule was confirmed via UAL (New-InboxRule from attacker IP). Discovery was only possible because the developer’s CFO made a voice call rather than sending an email to verify receipt.
Reconstructed Attack Timeline
| Timestamp | Artifact Source | Event |
|---|---|---|
T-25 days |
Azure AD Audit Log | OAuth phishing email delivered to CFO. Linked to legitimate Microsoft OAuth authorization page for malicious app ‘Microsoft Secure Mail Reader.’ |
T-25d, 16:41 UTC |
Azure AD Audit Log | CFO grants Mail.Read + offline_access to malicious OAuth app. Refresh token issued. No password compromise. MFA not triggered. |
T-21 days |
UAL MailItemsAccessed | First REST API read of CFO inbox from Romanian VPS (185.234.██.██). Attacker begins monitoring the real estate closing thread. |
T-21 to T-4 days |
UAL MailItemsAccessed | 1,203 read events. Attacker tracks full closing thread: wire amount ($2,341,500), account details, closing date, participant names and tone. |
T-4 days, 02:17 UTC |
UAL (New-InboxRule) | Deletion inbox rule ‘junk-filter-update’ created at 2:17 AM. Silently deletes emails containing fraud, verify, bank change, stop payment keywords. |
T-4 days |
DNS WHOIS | Lookalike domain ████████-propertiess[.]com registered. SPF, DKIM, DMARC, and MX records configured. Domain ready to send and receive email. |
T-0, 09:14:33 |
Message Trace | Fraudulent wire instruction sent from lookalike domain, using real thread’s In-Reply-To header. Delivered to CFO inbox — SCL -1 (trusted sender bypass). |
T-0, 09:16:51 |
UAL MailItemsAccessed | Attacker confirms delivery — Bind read event on fraudulent message ID from Romanian VPS. Real-time monitoring begins. |
T-0, 09:14 to 10:47 |
UAL MailItemsAccessed | 14 attacker read events during 93-minute fraud window. Attacker monitoring for verification attempts or suspicious replies. |
T-0, 10:47 |
Bank wire records | CFO initiates SWIFT MT103 wire for $2,341,500 to Florida mule account (████████ Global Solutions LLC). |
T-0, 10:52 |
UAL MailItemsAccessed | Bank wire confirmation email arrives in CFO inbox. Attacker reads it within 90 seconds — before the firm suspects fraud. |
T-0, 14:45 |
Developer phone call | Developer’s real CFO calls to confirm wire receipt. Fraud discovered. Bank notified. IR engaged. 6 hours post-wire. |
T-0, 15:18 |
IR engagement | Mjolnir Security retained. UAL collection begins. OAuth app identified and revoked. Deletion rule disabled. |
T-0 + 4 hrs |
Bank records | Funds arrive in Florida mule account. $2,100,000 immediately wired onward to Hong Kong. |
T-0 + 9 hrs |
Bank records / blockchain | $2,100,000 converted to USDT via VASP. Blockchain wallet identified. Funds dispersed to 7 downstream addresses. |
T-0 + 18 hrs |
Bank hold | $241,500 remaining in Florida account frozen. 10.3% recovery. FBI IC3 complaint filed with full technical documentation. |
What This Engagement Teaches Us
For Incident Responders
- In BEC, the bank call is the most time-sensitive action — before forensics, before containment, before anything else. Every minute between wire completion and bank notification reduces the recovery probability. Document this in your IR runbook explicitly.
- UAL MailItemsAccessed with REST/Graph ClientInfoString is the canonical indicator of OAuth-based silent mailbox monitoring. Filter for access from non-Outlook client strings (REST, GraphQL, IMAP) and non-expected IP addresses in the days to weeks before the fraud date.
- Always check inbox rules AND transport rules. Attacker-created deletion rules targeting fraud-related keywords are a standard BEC persistence mechanism. These rules run silently, are not visible in the normal Outlook inbox rules pane, and will be enabled during the critical window.
- Reconstruct which specific messages the attacker read using Bind events in MailItemsAccessed — this lets you prove exactly what intelligence the attacker had, which is essential for the financial fraud investigation and any litigation.
For Security Engineers & Legal/Financial Sector IT
- Block illicit OAuth consent grants at the tenant level: Azure AD → Enterprise Applications → Consent and Permissions → User consent settings → ‘Do not allow user consent.’ Force all OAuth app approvals through an admin consent workflow. This single configuration change would have prevented this incident entirely.
- DMARC enforcement (
p=rejectorp=quarantine) on your OWN domain does not protect against lookalike domain fraud. Your vendors, clients, and counterparties also need DMARC enforcement. Consider a supplier email security standard for high-value transacting parties. - Wire transfer verification must include a voice callback to a pre-registered number — not a number provided in the email requesting the change. This is the sole control that actually interrupted the fraud in this case. Make it mandatory for any wire instruction change, regardless of how legitimate the email appears.
- Audit connected OAuth applications in your M365 tenant quarterly: Azure AD → Enterprise Applications → All Applications → filter by ‘User Assigned.’ Any application with
Mail.ReadorMail.ReadWritethat your security team did not approve is an immediate investigation. Tools like Hawk (open source) automate this audit.
Mjolnir Security — BEC Investigation & Incident Response
Mjolnir Security provides 24/7 incident response, M365 forensics, and BEC investigation services to law firms, financial institutions, and real estate companies. Our DFIR team has investigated over 150 BEC engagements and supported wire fraud recovery totalling over $40 million.
mjolnirsecurity.com — 24/7 Incident Response Hotline: +1 833 403 5875
Written by Mjolnir Security DFIR team
Published September 2024 · DFIR Engagement Series · TLP:WHITE
Case #463 · Skuggaheimar · Mjolnir Security · All client details anonymized · TLP:WHITE
