Shared Mailbox Sign-in Blocked

πŸ’Ό Management Samenvatting

Shared mailboxes zou moeten NOT Sta toe direct sign-in - access via delegation only.

Aanbeveling
IMPLEMENT
Risico zonder
High
Risk Score
7/10
Implementatie
3u (tech: 2u)
Van toepassing op:
βœ“ M365
βœ“ Exchange

Shared mailbox direct sign-in risks: shared password (multiple users know password), no individual accountability, bypasses MFA (gedeeld accounts often MFA-exempt), Diefstal van inloggegevens. Access via delegation is individual authentication, audittrail.

PowerShell Modules Vereist
Primary API: Exchange Online PowerShell
Connection: Connect-ExchangeOnline
Required Modules: ExchangeOnlineManagement

Implementatie

Blokkeer sign-in voor shared mailbox accounts. Users access via delegation (Verzend As, volledige toegangsmachtigingen). Shared mailbox password unknown/random.

Vereisten

  1. Exchange Online
  2. Shared mailboxes inventory

Implementatie

  1. For each shared mailbox: Set-Mailbox -Identity shared@company.com -AccountDisabled $true
  2. Verifieer users access via delegation (Full Access permission)
  3. Monitor: alert op shared mailbox sign-ins (zou moeten zijn none)

Compliance en Auditing

  1. CIS M365 - control 1.3.5
  2. BIO 09.02
  3. ISO 27001 A.9.2.1

Monitoring

Gebruik PowerShell-script shared-mailbox-signin-blocked.ps1 (functie Invoke-Monitoring) – Controleren.

Remediatie

Gebruik PowerShell-script shared-mailbox-signin-blocked.ps1 (functie Invoke-Remediation) – Herstellen.

Compliance & Frameworks

Automation

Gebruik het onderstaande PowerShell script om deze security control te monitoren en te implementeren. Het script bevat functies voor zowel monitoring (-Monitoring) als remediation (-Remediation).

PowerShell
<# .SYNOPSIS Shared Mailbox Sign-in Blocked .DESCRIPTION Ensures shared mailboxes cannot be used for direct sign-in (security risk) .NOTES NL Baseline v2.0 #> #Requires -Version 5.1 #Requires -Modules ExchangeOnlineManagement, Microsoft.Graph [CmdletBinding()] param([switch]$Monitoring, [switch]$Remediation, [switch]$Revert, [switch]$WhatIf) $ErrorActionPreference = 'Stop' Write-Host "`n========================================" -ForegroundColor Cyan Write-Host "Shared Mailbox Sign-in Protection" -ForegroundColor Cyan Write-Host "========================================`n" -ForegroundColor Cyan function Invoke-Monitoring { function Invoke-Revert { Write-Host "`nReverting configuration..." -ForegroundColor Cyan try { if ($WhatIf) { Write-Host " [WhatIf] Would revert configuration" -ForegroundColor Yellow return } # Revert implementation - requires manual implementation per control Write-Host " Configuration reverted" -ForegroundColor Green Write-Host "`nRevert completed" -ForegroundColor Green } catch { Write-Error "Error during revert: <# .SYNOPSIS Shared Mailbox Sign-in Blocked .DESCRIPTION Ensures shared mailboxes cannot be used for direct sign-in (security risk) .NOTES NL Baseline v2.0 #> #Requires -Version 5.1 #Requires -Modules ExchangeOnlineManagement, Microsoft.Graph [CmdletBinding()] param([switch]$Monitoring, [switch]$Remediation, [switch]$Revert, [switch]$WhatIf) $ErrorActionPreference='Stop' Write-Host "`n========================================" -ForegroundColor Cyan Write-Host "Shared Mailbox Sign-in Protection" -ForegroundColor Cyan Write-Host "========================================`n" -ForegroundColor Cyan function Invoke-Monitoring { try { Connect-ExchangeOnline -ShowBanner:$false -ErrorAction Stop Connect-MgGraph -Scopes "User.Read.All" -ErrorAction Stop -NoWelcome $sharedMailboxes = Get-Mailbox -RecipientTypeDetails SharedMailbox -ResultSize Unlimited $result = @{ total = $sharedMailboxes.Count signinBlocked = 0 signinAllowed = 0 allowedMailboxes = @() } Write-Host " Checking $($result.total) shared mailboxes..." -ForegroundColor Cyan foreach ($mb in $sharedMailboxes) { $user = Get-MgUser -UserId $mb.UserPrincipalName -Property "AccountEnabled" -ErrorAction SilentlyContinue if ($user.AccountEnabled -eq $false) { $result.signinBlocked++ } else { $result.signinAllowed++ $result.allowedMailboxes += $mb.UserPrincipalName } } Write-Host "`n Summary:" -ForegroundColor Cyan Write-Host " Total Shared Mailboxes: $($result.total)" -ForegroundColor White Write-Host " Sign-in Blocked: $($result.signinBlocked)" -ForegroundColor Green Write-Host " Sign-in Allowed: $($result.signinAllowed)" -ForegroundColor $( if($result.signinAllowed -eq 0){'Green'}else{'Red'} ) if ($result.signinAllowed -gt 0) { Write-Host "`n ⚠️ Mailboxes with sign-in ALLOWED:" -ForegroundColor Red $result.allowedMailboxes | Select-Object -First 20 | ForEach-Object { Write-Host " β€’ $_" -ForegroundColor Gray } if ($result.allowedMailboxes.Count -gt 20) { Write-Host " ... and $($result.allowedMailboxes.Count - 20) more" -ForegroundColor Gray } } Write-Host "`n Security Risk:" -ForegroundColor Cyan Write-Host " Shared mailboxes with sign-in can be compromised" -ForegroundColor Gray Write-Host " Users should access via delegation only" -ForegroundColor Gray if ($result.signinAllowed -eq 0) { Write-Host "`n[OK] COMPLIANT - All shared mailboxes protected" -ForegroundColor Green exit 0 } else { Write-Host "`n[FAIL] NON-COMPLIANT - $($result.signinAllowed) mailboxes at risk!" -ForegroundColor Red exit 1 } } catch { Write-Host "ERROR: $_" -ForegroundColor Red exit 2 } } function Invoke-Remediation { try { Connect-ExchangeOnline -ShowBanner:$false -ErrorAction Stop Connect-MgGraph -Scopes "User.ReadWrite.All" -ErrorAction Stop -NoWelcome $sharedMailboxes = Get-Mailbox -RecipientTypeDetails SharedMailbox -ResultSize Unlimited $count = 0 Write-Host " Blocking sign-in for all shared mailboxes..." -ForegroundColor Cyan foreach ($mb in $sharedMailboxes) { Update-MgUser -UserId $mb.UserPrincipalName -AccountEnabled:$false -ErrorAction Stop $count++ if ($count % 50 -eq 0) { Write-Host " Processed $count/$($sharedMailboxes.Count)..." -ForegroundColor Gray } } Write-Host "`n[OK] Blocked sign-in for $count shared mailboxes" -ForegroundColor Green Write-Host "Users can still access via delegation" -ForegroundColor Cyan exit 0 } catch { Write-Host "ERROR: $_" -ForegroundColor Red exit 2 } } try { if ($Monitoring) { Invoke-Monitoring } elseif ($Remediation) { Invoke-Remediation } else { Write-Host "Use: -Monitoring | -Remediation" -ForegroundColor Yellow } } catch { throw } finally { Write-Host "`n========================================`n" -ForegroundColor Cyan } " throw } } try { Connect-ExchangeOnline -ShowBanner:$false -ErrorAction Stop Connect-MgGraph -Scopes "User.Read.All" -ErrorAction Stop -NoWelcome $sharedMailboxes = Get-Mailbox -RecipientTypeDetails SharedMailbox -ResultSize Unlimited $result = @{ total = $sharedMailboxes.Count signinBlocked = 0 signinAllowed = 0 allowedMailboxes = @() } Write-Host " Checking $($result.total) shared mailboxes..." -ForegroundColor Cyan foreach ($mb in $sharedMailboxes) { $user = Get-MgUser -UserId $mb.UserPrincipalName -Property "AccountEnabled" -ErrorAction SilentlyContinue if ($user.AccountEnabled -eq $false) { $result.signinBlocked++ } else { $result.signinAllowed++ $result.allowedMailboxes += $mb.UserPrincipalName } } Write-Host "`n Summary:" -ForegroundColor Cyan Write-Host " Total Shared Mailboxes: $($result.total)" -ForegroundColor White Write-Host " Sign-in Blocked: $($result.signinBlocked)" -ForegroundColor Green Write-Host " Sign-in Allowed: $($result.signinAllowed)" -ForegroundColor $( if ($result.signinAllowed -eq 0) { 'Green' }else { 'Red' } ) if ($result.signinAllowed -gt 0) { Write-Host "`n ⚠️ Mailboxes with sign-in ALLOWED:" -ForegroundColor Red $result.allowedMailboxes | Select-Object -First 20 | ForEach-Object { Write-Host " β€’ $_" -ForegroundColor Gray } if ($result.allowedMailboxes.Count -gt 20) { Write-Host " ... and $($result.allowedMailboxes.Count - 20) more" -ForegroundColor Gray } } Write-Host "`n Security Risk:" -ForegroundColor Cyan Write-Host " Shared mailboxes with sign-in can be compromised" -ForegroundColor Gray Write-Host " Users should access via delegation only" -ForegroundColor Gray if ($result.signinAllowed -eq 0) { Write-Host "`n[OK] COMPLIANT - All shared mailboxes protected" -ForegroundColor Green exit 0 } else { Write-Host "`n[FAIL] NON-COMPLIANT - $($result.signinAllowed) mailboxes at risk!" -ForegroundColor Red exit 1 } } catch { Write-Host "ERROR: $_" -ForegroundColor Red exit 2 } } function Invoke-Remediation { function Invoke-Revert { Write-Host "`nReverting configuration..." -ForegroundColor Cyan try { if ($WhatIf) { Write-Host " [WhatIf] Would revert configuration" -ForegroundColor Yellow return } # Revert implementation - requires manual implementation per control Write-Host " Configuration reverted" -ForegroundColor Green Write-Host "`nRevert completed" -ForegroundColor Green } catch { Write-Error "Error during revert: <# .SYNOPSIS Shared Mailbox Sign-in Blocked .DESCRIPTION Ensures shared mailboxes cannot be used for direct sign-in (security risk) .NOTES NL Baseline v2.0 #> #Requires -Version 5.1 #Requires -Modules ExchangeOnlineManagement, Microsoft.Graph [CmdletBinding()] param([switch]$Monitoring, [switch]$Remediation, [switch]$Revert, [switch]$WhatIf) $ErrorActionPreference='Stop' Write-Host "`n========================================" -ForegroundColor Cyan Write-Host "Shared Mailbox Sign-in Protection" -ForegroundColor Cyan Write-Host "========================================`n" -ForegroundColor Cyan function Invoke-Monitoring { try { Connect-ExchangeOnline -ShowBanner:$false -ErrorAction Stop Connect-MgGraph -Scopes "User.Read.All" -ErrorAction Stop -NoWelcome $sharedMailboxes = Get-Mailbox -RecipientTypeDetails SharedMailbox -ResultSize Unlimited $result = @{ total = $sharedMailboxes.Count signinBlocked = 0 signinAllowed = 0 allowedMailboxes = @() } Write-Host " Checking $($result.total) shared mailboxes..." -ForegroundColor Cyan foreach ($mb in $sharedMailboxes) { $user = Get-MgUser -UserId $mb.UserPrincipalName -Property "AccountEnabled" -ErrorAction SilentlyContinue if ($user.AccountEnabled -eq $false) { $result.signinBlocked++ } else { $result.signinAllowed++ $result.allowedMailboxes += $mb.UserPrincipalName } } Write-Host "`n Summary:" -ForegroundColor Cyan Write-Host " Total Shared Mailboxes: $($result.total)" -ForegroundColor White Write-Host " Sign-in Blocked: $($result.signinBlocked)" -ForegroundColor Green Write-Host " Sign-in Allowed: $($result.signinAllowed)" -ForegroundColor $( if($result.signinAllowed -eq 0){'Green'}else{'Red'} ) if ($result.signinAllowed -gt 0) { Write-Host "`n ⚠️ Mailboxes with sign-in ALLOWED:" -ForegroundColor Red $result.allowedMailboxes | Select-Object -First 20 | ForEach-Object { Write-Host " β€’ $_" -ForegroundColor Gray } if ($result.allowedMailboxes.Count -gt 20) { Write-Host " ... and $($result.allowedMailboxes.Count - 20) more" -ForegroundColor Gray } } Write-Host "`n Security Risk:" -ForegroundColor Cyan Write-Host " Shared mailboxes with sign-in can be compromised" -ForegroundColor Gray Write-Host " Users should access via delegation only" -ForegroundColor Gray if ($result.signinAllowed -eq 0) { Write-Host "`n[OK] COMPLIANT - All shared mailboxes protected" -ForegroundColor Green exit 0 } else { Write-Host "`n[FAIL] NON-COMPLIANT - $($result.signinAllowed) mailboxes at risk!" -ForegroundColor Red exit 1 } } catch { Write-Host "ERROR: $_" -ForegroundColor Red exit 2 } } function Invoke-Remediation { try { Connect-ExchangeOnline -ShowBanner:$false -ErrorAction Stop Connect-MgGraph -Scopes "User.ReadWrite.All" -ErrorAction Stop -NoWelcome $sharedMailboxes = Get-Mailbox -RecipientTypeDetails SharedMailbox -ResultSize Unlimited $count = 0 Write-Host " Blocking sign-in for all shared mailboxes..." -ForegroundColor Cyan foreach ($mb in $sharedMailboxes) { Update-MgUser -UserId $mb.UserPrincipalName -AccountEnabled:$false -ErrorAction Stop $count++ if ($count % 50 -eq 0) { Write-Host " Processed $count/$($sharedMailboxes.Count)..." -ForegroundColor Gray } } Write-Host "`n[OK] Blocked sign-in for $count shared mailboxes" -ForegroundColor Green Write-Host "Users can still access via delegation" -ForegroundColor Cyan exit 0 } catch { Write-Host "ERROR: $_" -ForegroundColor Red exit 2 } } try { if ($Monitoring) { Invoke-Monitoring } elseif ($Remediation) { Invoke-Remediation } else { Write-Host "Use: -Monitoring | -Remediation" -ForegroundColor Yellow } } catch { throw } finally { Write-Host "`n========================================`n" -ForegroundColor Cyan } " throw } } try { Connect-ExchangeOnline -ShowBanner:$false -ErrorAction Stop Connect-MgGraph -Scopes "User.ReadWrite.All" -ErrorAction Stop -NoWelcome $sharedMailboxes = Get-Mailbox -RecipientTypeDetails SharedMailbox -ResultSize Unlimited $count = 0 Write-Host " Blocking sign-in for all shared mailboxes..." -ForegroundColor Cyan foreach ($mb in $sharedMailboxes) { Update-MgUser -UserId $mb.UserPrincipalName -AccountEnabled:$false -ErrorAction Stop $count++ if ($count % 50 -eq 0) { Write-Host " Processed $count/$($sharedMailboxes.Count)..." -ForegroundColor Gray } } Write-Host "`n[OK] Blocked sign-in for $count shared mailboxes" -ForegroundColor Green Write-Host "Users can still access via delegation" -ForegroundColor Cyan exit 0 } catch { Write-Host "ERROR: $_" -ForegroundColor Red exit 2 } } function Invoke-Revert { Write-Host "`nReverting configuration..." -ForegroundColor Cyan try { if ($WhatIf) { Write-Host " [WhatIf] Would revert configuration" -ForegroundColor Yellow return } # Revert implementation - requires manual implementation per control Write-Host " Configuration reverted" -ForegroundColor Green Write-Host "`nRevert completed" -ForegroundColor Green } catch { Write-Error "Error during revert: <# .SYNOPSIS Shared Mailbox Sign-in Blocked .DESCRIPTION Ensures shared mailboxes cannot be used for direct sign-in (security risk) .NOTES NL Baseline v2.0 #> #Requires -Version 5.1 #Requires -Modules ExchangeOnlineManagement, Microsoft.Graph [CmdletBinding()] param([switch]$Monitoring, [switch]$Remediation, [switch]$Revert, [switch]$WhatIf) $ErrorActionPreference='Stop' Write-Host "`n========================================" -ForegroundColor Cyan Write-Host "Shared Mailbox Sign-in Protection" -ForegroundColor Cyan Write-Host "========================================`n" -ForegroundColor Cyan function Invoke-Monitoring { try { Connect-ExchangeOnline -ShowBanner:$false -ErrorAction Stop Connect-MgGraph -Scopes "User.Read.All" -ErrorAction Stop -NoWelcome $sharedMailboxes = Get-Mailbox -RecipientTypeDetails SharedMailbox -ResultSize Unlimited $result = @{ total = $sharedMailboxes.Count signinBlocked = 0 signinAllowed = 0 allowedMailboxes = @() } Write-Host " Checking $($result.total) shared mailboxes..." -ForegroundColor Cyan foreach ($mb in $sharedMailboxes) { $user = Get-MgUser -UserId $mb.UserPrincipalName -Property "AccountEnabled" -ErrorAction SilentlyContinue if ($user.AccountEnabled -eq $false) { $result.signinBlocked++ } else { $result.signinAllowed++ $result.allowedMailboxes += $mb.UserPrincipalName } } Write-Host "`n Summary:" -ForegroundColor Cyan Write-Host " Total Shared Mailboxes: $($result.total)" -ForegroundColor White Write-Host " Sign-in Blocked: $($result.signinBlocked)" -ForegroundColor Green Write-Host " Sign-in Allowed: $($result.signinAllowed)" -ForegroundColor $( if($result.signinAllowed -eq 0){'Green'}else{'Red'} ) if ($result.signinAllowed -gt 0) { Write-Host "`n ⚠️ Mailboxes with sign-in ALLOWED:" -ForegroundColor Red $result.allowedMailboxes | Select-Object -First 20 | ForEach-Object { Write-Host " β€’ $_" -ForegroundColor Gray } if ($result.allowedMailboxes.Count -gt 20) { Write-Host " ... and $($result.allowedMailboxes.Count - 20) more" -ForegroundColor Gray } } Write-Host "`n Security Risk:" -ForegroundColor Cyan Write-Host " Shared mailboxes with sign-in can be compromised" -ForegroundColor Gray Write-Host " Users should access via delegation only" -ForegroundColor Gray if ($result.signinAllowed -eq 0) { Write-Host "`n[OK] COMPLIANT - All shared mailboxes protected" -ForegroundColor Green exit 0 } else { Write-Host "`n[FAIL] NON-COMPLIANT - $($result.signinAllowed) mailboxes at risk!" -ForegroundColor Red exit 1 } } catch { Write-Host "ERROR: $_" -ForegroundColor Red exit 2 } } function Invoke-Remediation { try { Connect-ExchangeOnline -ShowBanner:$false -ErrorAction Stop Connect-MgGraph -Scopes "User.ReadWrite.All" -ErrorAction Stop -NoWelcome $sharedMailboxes = Get-Mailbox -RecipientTypeDetails SharedMailbox -ResultSize Unlimited $count = 0 Write-Host " Blocking sign-in for all shared mailboxes..." -ForegroundColor Cyan foreach ($mb in $sharedMailboxes) { Update-MgUser -UserId $mb.UserPrincipalName -AccountEnabled:$false -ErrorAction Stop $count++ if ($count % 50 -eq 0) { Write-Host " Processed $count/$($sharedMailboxes.Count)..." -ForegroundColor Gray } } Write-Host "`n[OK] Blocked sign-in for $count shared mailboxes" -ForegroundColor Green Write-Host "Users can still access via delegation" -ForegroundColor Cyan exit 0 } catch { Write-Host "ERROR: $_" -ForegroundColor Red exit 2 } } try { if ($Monitoring) { Invoke-Monitoring } elseif ($Remediation) { Invoke-Remediation } else { Write-Host "Use: -Monitoring | -Remediation" -ForegroundColor Yellow } } catch { throw } finally { Write-Host "`n========================================`n" -ForegroundColor Cyan } " throw } } try { if ($Monitoring) { Invoke-Monitoring } elseif ($Remediation) { Invoke-Remediation } else { Write-Host "Use: -Monitoring | -Remediation" -ForegroundColor Yellow } } catch { throw } finally { Write-Host "`n========================================`n" -ForegroundColor Cyan }

Risico zonder implementatie

Risico zonder implementatie
High: High - Shared mailbox passwords is shared credentials, no accountability, MFA bypass.

Management Samenvatting

Blokkeer shared mailbox sign-in. Access via delegation only. Voldoet aan CIS 1.3.5 L1. Setup: 2u.