Microsoft 365 : détecter et supprimer les transferts de courriels suspects

Inventoriez les règles cachées, transferts de boîtes et règles de transport, préservez les preuves et bloquez les transferts suspects avec des exceptions contrôlées.

01

Un transfert discret peut maintenir une fuite de données

Un utilisateur reçoit encore ses courriels, mais une copie part ailleurs. Le changement peut être légitime, mal configuré ou créé après une compromission. Le nom de la règle, la MFA et l’absence d’alerte ne suffisent pas à trancher. Il faut rapprocher la destination, le besoin d’affaires, la configuration et les événements disponibles.

Ce guide cible Exchange Online : inventaire en lecture seule, qualification, préservation des preuves et retrait contrôlé. Il complète le guide de première intervention sur un compte compromis; il ne remplace pas une investigation complète ni un audit de sécurité Microsoft 365. Tous les exemples utilisent des identités fictives.

02

Les trois emplacements à examiner

Une règle qui déplace les réponses dans un dossier ou les marque comme lues mérite aussi une analyse. Un transfert vers un contact de messagerie peut aboutir à une adresse externe : résoudre le destinataire est plus fiable que juger son nom. Si les deux propriétés de transfert de boîte sont renseignées, ForwardingAddress est prioritaire selon Set-Mailbox.

Ne confondez pas transfert automatique et envoi manuel. Les politiques de transfert sortant ne constituent pas une protection contre toutes les formes d’exfiltration, les applications OAuth ou une règle de transport malveillante.

MécanismeContrôlePoint d’attention
Règle de boîte de réceptionGet-InboxRule -IncludeHiddenForwardTo, RedirectTo et ForwardAsAttachmentTo; règles désactivées et actions de dissimulation
Transfert sur la boîteGet-MailboxForwardingAddress, ForwardingSmtpAddress et DeliverToMailboxAndForward
Règle de transportGet-TransportRule / EACRedirection ou copie à l’échelle du flux; conditions et exceptions
03

Préparer les droits et un dossier de preuves protégé

Utilisez ExchangeOnlineManagement avec une connexion interactive protégée par MFA. Ne mettez pas de mot de passe dans un script. Pour une collecte planifiée, concevez séparément l’authentification applicative et son RBAC à portée minimale; n’accordez pas Global Administrator pour faciliter l’inventaire.

Get-InboxRule ne fonctionne pas avec le seul groupe View-Only Organization Management ni avec Global Reader. Faites valider un rôle Exchange adapté aux commandes et aux boîtes du périmètre. La recherche d’audit demande les droits Purview correspondants. Distinguez les droits de lecture, de remédiation et de gestion des politiques.

Choisissez une fenêtre UTC et un identifiant de dossier. Protégez les exports par ACL, chiffrement et rétention limitée. Ils contiennent des adresses, noms de dossiers et renseignements sensibles. Export-Clixml documente les objets retournés : ce n’est ni une sauvegarde de boîte ni une restauration automatique des règles.

Connexion et emplacement de collecte
Import-Module ExchangeOnlineManagement
Connect-ExchangeOnline -UserPrincipalName admin@contoso.com
# Use an approved existing directory with restricted access.
$evidence = 'C:\IR\Case-001'
if (-not (Test-Path -LiteralPath $evidence -PathType Container)) {
    throw 'Create and secure the evidence directory before collection.'
}
$mailbox = 'alex@contoso.com'
04

Inventorier les transferts de boîtes, y compris les boîtes partagées

Le script suivant conserve les deux propriétés de destination plutôt que de chercher seulement ForwardingSmtpAddress. Le résultat est une liste de configurations à qualifier, pas une liste automatique d’incidents. DeliverToMailboxAndForward indique si une copie reste dans la boîte lorsque le transfert est configuré.

  • Inclure les boîtes partagées, comptes opérationnels et anciennes exceptions approuvées.
  • Résoudre ForwardingAddress avec Get-Recipient et vérifier ExternalEmailAddress si le destinataire est un contact.
  • Rechercher les chaînes de transfert; une destination interne peut transférer à son tour vers l’extérieur.
  • Documenter propriétaire, justification, destination et date d’expiration de chaque exception.
Inventaire en lecture seule
# Read-only tenant inventory, including shared mailboxes.
$mailboxes = @(Get-Mailbox -ResultSize Unlimited -ErrorAction Stop)
$mailboxes |
    Where-Object { $_.ForwardingAddress -or $_.ForwardingSmtpAddress } |
    Select-Object DisplayName,PrimarySmtpAddress,RecipientTypeDetails,
        ForwardingAddress,ForwardingSmtpAddress,DeliverToMailboxAndForward |
    Export-Csv (Join-Path $evidence 'mailbox-forwarding.csv') -NoTypeInformation -Encoding UTF8

# Resolve a directory recipient: it may be a mail contact with an external target.
$target = (Get-Mailbox -Identity $mailbox -ErrorAction Stop).ForwardingAddress
if ($target) {
    Get-Recipient -Identity $target -ErrorAction Stop |
        Format-List Name,RecipientTypeDetails,PrimarySmtpAddress,ExternalEmailAddress
}
05

Chercher les règles cachées sans modifier les boîtes

IncludeHidden ajoute les règles cachées aux résultats. Il ne prouve pas que toute persistance possible a été découverte. Gardez aussi les règles désactivées, l’ordre d’exécution et les règles sans transfert : elles peuvent masquer les alertes ou les échanges financiers.

Exécutez d’abord sur quelques boîtes. Pour un grand environnement, fractionnez le périmètre, gérez les limitations du service et rejouez les erreurs. Une erreur d’accès n’est jamais une boîte sans règle. Le CSV facilite le tri; les objets complets servent à relire les conditions et exceptions.

Collecte des règles et des erreurs
# Read-only collection. Scope to a pilot before a tenant-wide run.
$allRules = [System.Collections.Generic.List[object]]::new()
$errors = [System.Collections.Generic.List[object]]::new()
foreach ($box in $mailboxes) {
    $address = $box.PrimarySmtpAddress.ToString()
    try {
        $rules = @(Get-InboxRule -Mailbox $address -IncludeHidden -ResultSize Unlimited -ErrorAction Stop)
        foreach ($rule in $rules) {
            $allRules.Add([pscustomobject]@{ Mailbox = $address; Rule = $rule })
        }
    } catch {
        $errors.Add([pscustomobject]@{ Mailbox = $address; Error = $_.Exception.Message })
    }
}
# Keep full returned objects; CSV alone loses structured rule details.
$allRules | Export-Clixml (Join-Path $evidence 'inbox-rules.xml')
$allRules | Where-Object {
    $_.Rule.ForwardTo -or $_.Rule.RedirectTo -or $_.Rule.ForwardAsAttachmentTo
} | ForEach-Object {
    [pscustomobject]@{
        Mailbox = $_.Mailbox; Name = $_.Rule.Name
        RuleIdentity = $_.Rule.RuleIdentity; Enabled = $_.Rule.Enabled
        Priority = $_.Rule.Priority
        ForwardTo = ($_.Rule.ForwardTo -join '; ')
        RedirectTo = ($_.Rule.RedirectTo -join '; ')
        ForwardAsAttachmentTo = ($_.Rule.ForwardAsAttachmentTo -join '; ')
        DeleteMessage = $_.Rule.DeleteMessage
        MoveToFolder = [string]$_.Rule.MoveToFolder
        StopProcessingRules = $_.Rule.StopProcessingRules
    }
} | Export-Csv (Join-Path $evidence 'inbox-forwarding.csv') -NoTypeInformation -Encoding UTF8
$errors | Export-Csv (Join-Path $evidence 'collection-errors.csv') -NoTypeInformation -Encoding UTF8
06

Qualifier la destination et relier la règle à une activité réelle

Demandez au propriétaire, par un canal fiable, si le transfert est attendu. Ne vous fiez pas à une réponse reçue uniquement depuis le compte suspect. Vérifiez le domaine exact, les adresses proches d’un partenaire, l’ensemble des conditions et l’existence d’une approbation.

Exemple fictif : une règle nommée « . » redirige les messages contenant « facture » vers collecte@exemple-externe.invalid, puis les déplace. L’association de cette règle à une connexion inhabituelle augmente la priorité. À l’inverse, une destination de fournisseur connue n’est pas automatiquement autorisée à recevoir tout le contenu d’une boîte.

  • Comparer le moment du changement aux connexions Entra, délégations et changements administratifs.
  • Examiner dans Message Trace les messages concernés et leur état; une configuration seule ne démontre pas une livraison externe.
  • Consulter le rapport Auto forwarded messages pour compléter l’inventaire, sans le traiter comme un historique exhaustif.
  • Préserver les identifiants de messages, journaux, règles et horodatages avant la suppression lorsque le confinement le permet.
07

Reconstituer les changements dans Microsoft Purview Audit

Recherchez créations, modifications, activations et suppressions de règles, UpdateInboxRules et Set-Mailbox. UserIds représente l’auteur de l’opération : filtrer seulement sur le propriétaire peut exclure un administrateur ou un délégué. L’exemple collecte les opérations pertinentes du tenant; examinez ensuite ObjectId, UserId et Parameters dans AuditData pour isoler la boîte.

La recherche est paginée et limitée à 50 000 résultats avec ReturnLargeSet. Réduisez les fenêtres lorsque la limite est atteinte. L’absence d’événement peut refléter la rétention, les droits, un délai d’ingestion ou la complétude de la recherche; elle ne blanchit pas le changement. Pour la surveillance continue, Microsoft recommande la Management Activity API plutôt qu’un simple script de recherches répétées.

Collecte paginée des événements sur sept jours
# Read-only audit query. No UserIds filter: the actor may be a delegate/admin.
$end = (Get-Date).ToUniversalTime()
$start = $end.AddDays(-7)
$session = [guid]::NewGuid().ToString()
$operations = 'New-InboxRule','Set-InboxRule','Remove-InboxRule',
    'Enable-InboxRule','Disable-InboxRule','UpdateInboxRules','Set-Mailbox'
$records = [System.Collections.Generic.List[object]]::new()
do {
    $page = @(Search-UnifiedAuditLog -StartDate $start -EndDate $end -Operations $operations `
        -SessionId $session -SessionCommand ReturnLargeSet -ResultSize 5000 -ErrorAction Stop)
    foreach ($record in $page) { $records.Add($record) }
} while ($page.Count -gt 0 -and $records.Count -lt 50000)
$records | Export-Clixml (Join-Path $evidence 'audit-records.xml')
$records | Select-Object CreationDate,UserIds,Operations,AuditData |
    Export-Csv (Join-Path $evidence 'audit-records.csv') -NoTypeInformation -Encoding UTF8
if ($records.Count -ge 50000) {
    Write-Warning 'Result cap reached: repeat with smaller UTC time windows.'
}
08

Désactiver ou supprimer uniquement ce qui a été confirmé

En cas de fuite active, le confinement ne doit pas attendre une collecte parfaite. Préservez rapidement ce qui est disponible, puis coordonnez le blocage du compte et l’arrêt du transfert avec l’équipe de réponse. Une simple suppression de règle ne retire pas l’accès de l’attaquant.

Attention : Microsoft avertit que créer, modifier, activer, désactiver ou supprimer une règle avec Exchange PowerShell peut supprimer les règles côté client créées dans Outlook. Documentez-les avec l’utilisateur lorsque possible, conservez les avertissements et choisissez la méthode adaptée. N’utilisez pas une suppression globale ou -Force pour ignorer ce risque.

L’exemple commence par WhatIf. Désactiver conserve la règle côté serveur pour examen, mais ne garantit pas un retour arrière complet des règles Outlook. Le retrait du transfert de boîte ne touche pas les règles de réception ni les règles de transport. Traitez ces mécanismes séparément.

Remédiation ciblée : simulations avant changement
# CHANGE: inspect and export first. Replace the placeholder with the exact RuleIdentity.
$ruleId = 'REPLACE_WITH_CONFIRMED_RULE_ID'
if ($ruleId -eq 'REPLACE_WITH_CONFIRMED_RULE_ID' -or [string]::IsNullOrWhiteSpace($ruleId)) {
    throw 'Select the confirmed malicious rule before proceeding.'
}
Get-InboxRule -Mailbox $mailbox -Identity $ruleId -IncludeHidden -ErrorAction Stop | Format-List *
Disable-InboxRule -Mailbox $mailbox -Identity $ruleId -WhatIf
# After approval, run without -WhatIf; retain normal confirmation prompts.
# Disable-InboxRule -Mailbox $mailbox -Identity $ruleId
# Remove-InboxRule -Mailbox $mailbox -Identity $ruleId

# CHANGE: removes both mailbox-forwarding targets, not inbox or transport rules.
Set-Mailbox -Identity $mailbox -ForwardingAddress $null -ForwardingSmtpAddress $null -DeliverToMailboxAndForward $false -WhatIf
# Run without -WhatIf only after validating the intended scope.
Get-Mailbox -Identity $mailbox |
    Format-List ForwardingAddress,ForwardingSmtpAddress,DeliverToMailboxAndForward
09

Bloquer les transferts externes et encadrer les exceptions

Dans Microsoft Defender, examinez les politiques antispam sortantes. Configurez explicitement Off pour interdire le transfert automatique externe; n’interprétez pas Automatic comme une garantie identique dans tous les tenants. Ce contrôle ne bloque pas les transferts internes. Les règles de transport demandent une revue distincte.

Inventoriez les politiques personnalisées avant de changer la politique par défaut. La première politique sortante applicable selon sa priorité est utilisée; la politique par défaut vient en dernier. Une exception On doit viser les seuls expéditeurs autorisés, avec propriétaire et échéance. Les domaines distants peuvent restreindre les destinations, mais leur interaction doit être testée : un blocage applicable peut empêcher le transfert malgré une autorisation ailleurs.

  • Commencer par une boîte pilote et un message sans données réelles.
  • Tester un transfert externe interdit, une exception approuvée, un transfert interne et un courriel manuel externe.
  • Vérifier réception normale, conservation de copie si prévue, Message Trace et éventuel NDR 5.7.520.
  • Enregistrer la configuration initiale; ne rétablir une exception que si la destination et le besoin ont été reconfirmés.
Lire les contrôles et leur portée
# Read-only configuration: scope, exceptions and priority matter.
Get-HostedOutboundSpamFilterPolicy | Format-List Name,AutoForwardingMode
Get-HostedOutboundSpamFilterRule | Sort-Object Priority |
    Format-List Name,State,Priority,HostedOutboundSpamFilterPolicy,
        From,FromMemberOf,SenderDomainIs,ExceptIfFrom,ExceptIfFromMemberOf,ExceptIfSenderDomainIs
Get-RemoteDomain | Format-Table Name,DomainName,AutoForwardEnabled
Get-TransportRule | Sort-Object Priority |
    Format-List Name,Identity,State,Mode,Priority,Description
10

Surveiller la réapparition et fermer le dossier correctement

Examinez notamment l’alerte Suspicious email forwarding activity et les alertes de création de transfert disponibles dans votre environnement. La première cible une activité jugée suspecte, pas chaque transfert; elle ne constitue pas un inventaire exhaustif. Vérifiez les licences, rôles, notifications et destinataires de garde. Microsoft indique qu’une politique d’alerte nouvelle ou modifiée peut prendre jusqu’à 24 heures avant de déclencher.

Si la règle réapparaît, cherchez l’accès qui la recrée : session, délégué, application ou compte administrateur. Réévaluez les méthodes d’authentification et consentements OAuth. Le dossier devrait contenir destination, période, messages potentiellement exposés, degré de certitude, changements et preuves de tests. Une configuration retirée ne récupère pas les copies déjà livrées.

  • Inventaire terminé, erreurs de collecte résolues ou explicitement documentées.
  • Règles et transferts suspects neutralisés; règles métier préservées autant que possible.
  • Accès à l’origine de l’incident contenu; tests de messagerie validés.
  • Exceptions approuvées, surveillance attribuée et suivi planifié.
11

Quand faire appel à un accompagnement professionnel?

Plusieurs boîtes touchées, des règles recréées, une application inconnue ou une fuite financière justifient une investigation plus large. Mon accompagnement Microsoft 365 permet de qualifier l’exposition, revoir les droits et politiques et mettre en place une surveillance adaptée. Ce diagnostic ciblé reste une étape, pas un remplacement de l’audit complet ni de la réponse aux incidents.