Σε σχεδόν κάθε περιστατικό BEC, το πρώτο που κάνει ο επιτιθέμενος μόλις μπει σε ένα mailbox είναι να φτιάξει έναν inbox rule. Τα τιμολόγια πάνε στον φάκελο RSS Feeds, οι απαντήσεις του προμηθευτή σβήνονται, κι ένα αντίγραφο κάθε μηνύματος φεύγει σε μια διεύθυνση Gmail. Ο χρήστης δεν βλέπει τίποτα, και ο κανόνας συνεχίζει να δουλεύει ακόμα κι αφού αλλάξει ο κωδικός.
Το εργαλείο αυτό ελέγχει όλα τα mailboxes του οργανισμού σου με μία κίνηση. Τρέχεις ένα script, ανεβάζεις το αρχείο, και βλέπεις ποιος κανόνας είναι ύποπτος, γιατί, και τι κάνεις τώρα. Δεν χρειάζεται εγγραφή, ούτε πρόσβαση στο tenant σου. Αν θέλεις πρώτα να δεις πώς δουλεύει, πάτησε «Δοκίμασε με παράδειγμα».
Exchange Online · Inbox rules · Mailbox forwarding
🔒 Το αρχείο δεν φεύγει από τον υπολογιστή σου
Η ανάλυση γίνεται μόνο μέσα στον browser σου. Οι διευθύνσεις, τα ονόματα των κανόνων και οι λέξεις-κλειδιά δεν στέλνονται σε κανέναν server, ούτε στο thecybersec.gr, και δεν αποθηκεύονται. Λεπτομέρειες στην Πολιτική απορρήτου.
1. Βγάλε το αρχείο από το Microsoft 365 σου
- Στον υπολογιστή σου με Windows, άνοιξε το PowerShell: πάτησε το πλήκτρο Windows, γράψε PowerShell και άνοιξε το Windows PowerShell. Όχι το «Windows PowerShell ISE»: εκεί η σύνδεση αποτυγχάνει με το σφάλμα «A window handle must be configured». Δεν χρειάζεται «Run as administrator».
- Μόνο την πρώτη φορά, τρέξε τις δύο εντολές παρακάτω, μία μία. Η πρώτη επιτρέπει στο PowerShell να φορτώνει τα scripts που φτιάχνει το module κατά τη σύνδεση· χωρίς αυτήν, το Connect-ExchangeOnline βγάζει το σφάλμα «Module could not be correctly formed». Η δεύτερη εγκαθιστά το module της Microsoft για το Exchange Online. Όπου σε ρωτήσει, γράψε Y και Enter. Μετά κλείσε το PowerShell και άνοιξέ το ξανά.
Set-ExecutionPolicy RemoteSigned -Scope CurrentUser Install-Module ExchangeOnlineManagement -Scope CurrentUser
- Κατέβασε το script και τρέξ' το. Θα ανοίξει το παράθυρο σύνδεσης της Microsoft: μπες με λογαριασμό που έχει ρόλο Exchange Administrator ή Global Administrator. Ο ρόλος Global Reader δεν αρκεί.Στο PowerShell, τρέξε τις τρεις εντολές μία μία. Η πρώτη σε πηγαίνει στον φάκελο Λήψεις. Η δεύτερη ξεμπλοκάρει το αρχείο, γιατί τα Windows μπλοκάρουν τα scripts που κατεβαίνουν από το internet. Η τρίτη το τρέχει.
cd $env:USERPROFILE\Downloads Unblock-File .\inboxrules-audit.ps1 .\inboxrules-audit.ps1
- Περίμενε να τελειώσει. Για μερικές εκατοντάδες mailboxes θέλει λίγα λεπτά. Το script μόνο διαβάζει, δεν αλλάζει τίποτα. Στο τέλος σου δείχνει μια σύνοψη, πόσα mailboxes, κανόνες και προωθήσεις βρήκε, και πού αποθήκευσε το inboxrules.json: στον ίδιο φάκελο, δηλαδή στις Λήψεις.
📄 Θες να δεις τον κώδικα ή να τον κάνεις copy-paste;
Είναι το ίδιο script με το αρχείο. Αν δεν θέλεις να κατεβάσεις αρχείο, πάτησε «Αντιγραφή script», επικόλλησέ το στο PowerShell και πάτησε Enter. Τότε δεν χρειάζονται οι τρεις εντολές του βήματος 3. Για ένα μόνο mailbox, άλλαξε το -ResultSize Unlimited σε -Identity user@mycompany.gr.
# ============================================================
# Exchange Online - Mailbox Forwarding & Inbox Rules Audit
# Read-only audit
# ============================================================
Connect-ExchangeOnline
$OutputFile = ".\inboxrules.json"
# Retry ρυθμίσεις για Get-InboxRule (throttling / timeouts)
$MaxAttempts = 3 # Συνολικές προσπάθειες ανά mailbox
$BaseDelay = 5 # Δευτερόλεπτα· αυξάνεται ανά προσπάθεια (5, 10, ...)
$out = foreach (
$m in Get-EXOMailbox `
-ResultSize Unlimited `
-Properties ForwardingSmtpAddress,ForwardingAddress,DeliverToMailboxAndForward
) {
# --------------------------------------------------------
# 1. Mailbox-level forwarding
# --------------------------------------------------------
[pscustomobject]@{
Type = 'Mailbox'
Mailbox = $m.UserPrincipalName
ForwardingSmtpAddress = "$($m.ForwardingSmtpAddress)"
ForwardingAddress = "$($m.ForwardingAddress)"
DeliverToMailboxAndForward = $m.DeliverToMailboxAndForward
}
# --------------------------------------------------------
# 2. Inbox Rules (με retry)
# Περιλαμβάνονται και hidden rules
# --------------------------------------------------------
# Σε παροδική αποτυχία (throttling, timeout) γίνεται νέα
# προσπάθεια μετά από αυξανόμενη αναμονή, έως $MaxAttempts.
# --------------------------------------------------------
$ruleErr = $null
$rules = $null
$attempts = 0
for ($attempt = 1; $attempt -le $MaxAttempts; $attempt++) {
$attempts = $attempt
# Reset σε κάθε προσπάθεια ώστε error προηγούμενης
# προσπάθειας ή προηγούμενου mailbox να μην επηρεάσει.
$ruleErr = $null
$rules = $null
$rules = Get-InboxRule `
-Mailbox $m.UserPrincipalName `
-IncludeHidden `
-WarningAction SilentlyContinue `
-ErrorAction SilentlyContinue `
-ErrorVariable ruleErr
if (-not $ruleErr) { break }
if ($attempt -lt $MaxAttempts) {
Write-Host "Retry $attempt/$($MaxAttempts - 1) για $($m.UserPrincipalName)..." `
-ForegroundColor DarkYellow
Start-Sleep -Seconds ($BaseDelay * $attempt)
}
}
# --------------------------------------------------------
# 3. Καταγραφή failure
# --------------------------------------------------------
# Αν μετά από όλες τις προσπάθειες δεν διαβάστηκαν τα
# Inbox Rules, καταγράφεται ως Error ώστε το mailbox να
# μη θεωρηθεί λανθασμένα "καθαρό".
# Αν το Exception.Message είναι κενό, κρατείται ολόκληρο
# το ErrorRecord ως κείμενο.
# --------------------------------------------------------
if ($ruleErr) {
$msg = "$($ruleErr[0].Exception.Message)"
if ([string]::IsNullOrWhiteSpace($msg)) {
$msg = "$($ruleErr[0])"
}
if ([string]::IsNullOrWhiteSpace($msg)) {
$msg = "Unknown error ($($ruleErr[0].FullyQualifiedErrorId))"
}
[pscustomobject]@{
Type = 'Error'
Mailbox = $m.UserPrincipalName
Attempts = $attempts
Message = $msg
}
}
# --------------------------------------------------------
# 4. Καταγραφή όλων των Inbox Rules
# --------------------------------------------------------
$rules | ForEach-Object {
[pscustomobject]@{
Type = 'Rule'
Mailbox = $m.UserPrincipalName
# Rule information
# Τα κενά (null) φιλτράρονται με Where-Object { $_ }, αλλιώς
# το @() γίνεται @("") και κάθε κανόνας μετριέται ως προώθηση.
Name = $_.Name
Enabled = $_.Enabled
Priority = $_.Priority
Description = "$($_.Description)"
# Conditions
From = @(
$_.From | Where-Object { $_ } |
ForEach-Object { "$_" }
)
FromAddressContainsWords = @(
$_.FromAddressContainsWords | Where-Object { $_ }
)
SubjectContainsWords = @(
$_.SubjectContainsWords | Where-Object { $_ }
)
BodyContainsWords = @(
$_.BodyContainsWords | Where-Object { $_ }
)
SubjectOrBodyContainsWords = @(
$_.SubjectOrBodyContainsWords | Where-Object { $_ }
)
# Actions
MoveToFolder = "$($_.MoveToFolder)"
CopyToFolder = "$($_.CopyToFolder)"
DeleteMessage = $_.DeleteMessage
SoftDeleteMessage = $_.SoftDeleteMessage
MarkAsRead = $_.MarkAsRead
StopProcessingRules = $_.StopProcessingRules
ForwardTo = @(
$_.ForwardTo |
Where-Object { $_ } |
ForEach-Object { "$_" }
)
ForwardAsAttachmentTo = @(
$_.ForwardAsAttachmentTo |
Where-Object { $_ } |
ForEach-Object { "$_" }
)
RedirectTo = @(
$_.RedirectTo |
Where-Object { $_ } |
ForEach-Object { "$_" }
)
}
}
}
# ============================================================
# 5. Export αποτελεσμάτων σε JSON
# ============================================================
$out |
ConvertTo-Json -Depth 5 |
Out-File $OutputFile -Encoding utf8
# ============================================================
# 6. Statistics
# ============================================================
$path = (Resolve-Path $OutputFile).Path
$mailboxes = @(
$out | Where-Object Type -eq 'Mailbox'
).Count
$rules = @(
$out | Where-Object Type -eq 'Rule'
).Count
$failedItems = @(
$out | Where-Object Type -eq 'Error'
)
$failed = $failedItems.Count
$forwardingMailboxes = @(
$out |
Where-Object {
$_.Type -eq 'Mailbox' -and
(
$_.ForwardingSmtpAddress -or
$_.ForwardingAddress
)
}
).Count
$forwardingRules = @(
$out |
Where-Object {
$_.Type -eq 'Rule' -and
(
@($_.ForwardTo).Count -gt 0 -or
@($_.ForwardAsAttachmentTo).Count -gt 0 -or
@($_.RedirectTo).Count -gt 0
)
}
).Count
# ============================================================
# 7. Disconnect από Exchange Online
# ============================================================
Disconnect-ExchangeOnline -Confirm:$false
# ============================================================
# 8. Summary
# ============================================================
Write-Host ""
Write-Host "==========================================" -ForegroundColor Cyan
Write-Host " Exchange Online Audit Completed" -ForegroundColor Cyan
Write-Host "==========================================" -ForegroundColor Cyan
Write-Host ""
Write-Host "Mailboxes checked: $mailboxes"
Write-Host "Inbox Rules found: $rules"
Write-Host "Mailbox forwarding found: $forwardingMailboxes"
Write-Host "Forwarding rules found: $forwardingRules"
if ($failed -gt 0) {
Write-Host ""
Write-Host "WARNING: Δεν διαβάστηκαν τα Inbox Rules για $failed mailbox(es) μετά από $MaxAttempts προσπάθειες." `
-ForegroundColor Yellow
# Εμφάνιση των αποτυχημένων mailboxes απευθείας στην οθόνη
$failedItems | ForEach-Object {
Write-Host " - $($_.Mailbox): $($_.Message)" -ForegroundColor Yellow
}
Write-Host "Τα συγκεκριμένα mailboxes έχουν καταγραφεί ως Type='Error' στο JSON." `
-ForegroundColor Yellow
}
else {
Write-Host ""
Write-Host "Inbox Rules successfully read for all checked mailboxes." `
-ForegroundColor Green
}
Write-Host ""
Write-Host "Το αρχείο αποθηκεύτηκε στο:" -ForegroundColor Green
Write-Host $path -ForegroundColor Green
Write-Host ""2. Σύρε εδώ το inboxrules.json από τον φάκελο που σου έγραψε το PowerShell, ή επικόλλησε το περιεχόμενό του.
Ένας κανόνας που σημειώνεται εδώ δεν είναι απόδειξη παραβίασης: πολλοί χρήστες έχουν νόμιμους κανόνες που διαγράφουν ή μετακινούν μηνύματα. Τον κρίνεις εσύ, με τον χρήστη και με τα logs του KQL. Το εργαλείο δεν βλέπει κανόνες που υπάρχουν μόνο στο Outlook της συσκευής (client-only rules), mail flow rules του admin ή εφαρμογές με δικαίωμα στο mailbox.
Πώς δουλεύει
Το script του βήματος 1 τρέχει στο Exchange Online PowerShell και μόνο διαβάζει. Για κάθε mailbox γράφει στο inboxrules.json δύο πράγματα: τους inbox rules του χρήστη, μαζί με τους κρυφούς που δεν φαίνονται στο Outlook, και την προώθηση που έχει οριστεί στο ίδιο το mailbox (SMTP forwarding). Η δεύτερη ορίζεται από admin, δεν φαίνεται στους κανόνες του χρήστη, και συχνά ξεχνιέται στους ελέγχους.
Στο εργαλείο, κάθε κανόνας ελέγχεται για τα σημάδια που περιγράφει η ίδια η Microsoft:
- Προώθηση σε εξωτερική διεύθυνση με ForwardTo, ForwardAsAttachmentTo ή RedirectTo. Αν προωθεί κάθε μήνυμα χωρίς φίλτρο, είναι «Κρίσιμο».
- Διαγραφή κάθε εισερχόμενου χωρίς φίλτρο, ή διαγραφή μηνυμάτων με λέξεις για πληρωμές και προειδοποιήσεις ασφάλειας.
- Μετακίνηση σε φάκελο που κανείς δεν ανοίγει, όπως RSS Feeds, Conversation History ή Archive, ιδίως μαζί με σήμανση ως αναγνωσμένο.
- Λέξεις-κλειδιά όπως invoice, πληρωμή, IBAN, phish, suspicious, ύποπτη σύνδεση, στα Αγγλικά και στα Ελληνικά.
- Ονόματα χωρίς γράμματα, όπως «.», «..» ή «,,,», για να μη φαίνεται ο κανόνας στη λίστα.
Δύο ή περισσότερα σημάδια μαζί ανεβάζουν τη σοβαρότητα σε «Κρίσιμο». Ένας απενεργοποιημένος κανόνας πέφτει ένα επίπεδο, γιατί δεν δουλεύει τώρα, αλλά μένει στη λίστα: ο επιτιθέμενος τον ενεργοποιεί ξανά με ένα κλικ.
Για να ξεχωρίσει τι είναι εξωτερικό, το εργαλείο παίρνει τα domains από τα ίδια τα mailboxes. Αν έχεις θυγατρικές ή άλλα domains, πρόσθεσέ τα στο βήμα 3, αλλιώς η προώθηση προς αυτά θα σημειωθεί ως εξωτερική.
Τι κάνεις αν βρεις κάτι
Η σειρά έχει σημασία. Πρώτα απενεργοποιείς τον κανόνα και την προώθηση, με τις εντολές που σου δίνει το εργαλείο σε κάθε mailbox. Το Disable-InboxRule κρατά τον κανόνα ως τεκμήριο για τη διερεύνηση, ενώ το Remove-InboxRule τον σβήνει. Μετά ακυρώνεις τις ενεργές συνεδρίες του χρήστη και αλλάζεις τον κωδικό. Η αλλαγή κωδικού μόνη της δεν φτάνει, γιατί ο επιτιθέμενος συνεχίζει με τα tokens που ήδη έχει.
Ύστερα ελέγχεις τις μεθόδους MFA, τις εφαρμογές και τους ρόλους του λογαριασμού, και τρέχεις το KQL του εργαλείου στο Advanced hunting. Εκεί βλέπεις πότε φτιάχτηκε κάθε κανόνας, από ποια IP και από ποια χώρα. Από την ίδια IP βρίσκεις συχνά κι άλλους λογαριασμούς που παραβιάστηκαν την ίδια μέρα.
Τέλος, κλείνεις την πόρτα για το μέλλον. Στο outbound spam policy του Microsoft Defender, όρισε τα Automatic forwarding rules σε Off. Η προεπιλογή «Automatic - System-controlled» δεν σημαίνει Off σε κάθε tenant: σε όσα χρησιμοποιούσαν ήδη την προώθηση πριν το 2021, μπορεί να ισοδυναμεί με On. Όσοι χρήστες χρειάζονται πραγματικά εξωτερική προώθηση μπαίνουν σε ξεχωριστή πολιτική.
🛠️ Ο επιτιθέμενος έστειλε email από το mailbox; Ανάλυσε τα headers ενός ύποπτου μηνύματος και δες τι αποφάσισε το Microsoft 365 γι' αυτό.
Τι δεν μπορεί να σου πει
- Αν ο κανόνας είναι επίθεση ή νόμιμος. Πολλοί χρήστες έχουν κανόνες που διαγράφουν ή μετακινούν μηνύματα. Το εργαλείο σημειώνει τα σημάδια, την απόφαση την παίρνεις εσύ, με τον χρήστη και με τα logs.
- Κανόνες που υπάρχουν μόνο στο Outlook της συσκευής. Οι client-only rules δεν αποθηκεύονται στον server και δεν φαίνονται στο
Get-InboxRule. - Άλλους τρόπους πρόσβασης στο mailbox. Mail flow rules του admin, δικαιώματα delegate (Full Access, Send As) και εφαρμογές με δικαίωμα Mail.Read δεν ελέγχονται εδώ.
Γιατί έχει σημασία για τη συμμόρφωση
Η ΚΥΑ 1689/2025 ζητά τακτικό έλεγχο των καταγραφών για ύποπτη δραστηριότητα (απαίτηση 24.ε), διαδικασίες διαχείρισης περιστατικών (24.α) και έλεγχο των μηνυμάτων ηλεκτρονικού ταχυδρομείου (20.γ). Η Οδηγία NIS2 ζητά χειρισμό περιστατικών (21.2.β) και, για σημαντικό περιστατικό, έγκαιρη προειδοποίηση εντός 24 ωρών (23.4.α). Στο ISO/IEC 27001 αφορά την αξιολόγηση των συμβάντων (A.5.25), την απόκριση στα περιστατικά (A.5.26) και την παρακολούθηση (A.8.16).
Στον GDPR, ένα mailbox που προωθούσε email σε τρίτο είναι σχεδόν πάντα παραβίαση προσωπικών δεδομένων. Αφορά την ασφάλεια των συστημάτων (32.1.β) και τη γνωστοποίηση στην Αρχή Προστασίας Δεδομένων εντός 72 ωρών (33.1). Η αναφορά .pdf του εργαλείου, μαζί με τα αποτελέσματα του KQL, είναι το πρώτο τεκμήριο για τον φάκελο του περιστατικού.
🛠️ Επιβεβαιώθηκε παραβίαση; Ετοίμασε την αναφορά περιστατικού προς την Εθνική Αρχή Κυβερνοασφάλειας, με επιλογή για την έγκαιρη προειδοποίηση των 24 ωρών ή την αναφορά των 72 ωρών.
🛠️ Θες τα queries ανά απαίτηση; Δες τη βιβλιοθήκη KQL για το Defender XDR, αντιστοιχισμένη σε ΚΥΑ 1689/2025, NIS2 και ISO 27001.
Απόρρητο
Το thecybersec.gr δεν έχει server που να δέχεται το αρχείο σου. Η ανάλυση γίνεται εξ ολοκλήρου μέσα στον browser σου, και το περιεχόμενο δεν αποθηκεύεται, ούτε στο localStorage. Αν έχεις αποδεχτεί τα cookies ανάλυσης, το πλαίσιο κειμένου και τα αποτελέσματα αποκρύπτονται από την καταγραφή του Microsoft Clarity. Περισσότερα στην πολιτική απορρήτου.
Η ερμηνεία είναι ενδεικτική και δεν αντικαθιστά τη διερεύνηση στο δικό σου περιβάλλον. Το thecybersec.gr είναι προσωπικό blog και δεν εκπροσωπεί τη Microsoft ή την Εθνική Αρχή Κυβερνοασφάλειας.
