Back to Checks
Shared mailbox has sign-in blocked
exchange_shared_mailbox_sign_in_disabled
Service: exchangeSeverity: medium
OfficialBuilt-inVerified
Categories:identity-access
Resource Type:NotDefined
Microsoft 365 Shared mailboxes are used for collaboration and should not permit direct sign-in. This check verifies that the AccountEnabled property is set to false in Entra ID for all shared mailboxes, preventing direct authentication.
Risk
When sign-in is enabled on shared mailboxes, users with the password can bypass delegation controls and access the mailbox directly. This undermines accountability since actions cannot be attributed to individual users, and it increases the attack surface for credential-based attacks.
Run this check with Prowler
Run in Prowler CloudRun
prowler m365 --checks exchange_shared_mailbox_sign_in_disabledRecommendation
Block sign-in for all shared mailboxes to ensure users can only access them through delegation. This enforces accountability and reduces security risks from shared credentials.
Remediation
CLI
Get-EXOMailbox -RecipientTypeDetails SharedMailbox | ForEach-Object { Update-MgUser -UserId $_.ExternalDirectoryObjectId -AccountEnabled:$false }Other
1Navigate to Entra admin center (https://entra.microsoft.com/)
2Expand Identity > Users and select All users
3Search for and select the shared mailbox user account
4In the properties pane, go to Account status
5Uncheck 'Account enabled' and click Save
6Repeat for all shared mailbox accounts
Check Code
from typing import List
from prowler.lib.check.models import Check, CheckReportM365
from prowler.providers.m365.services.entra.entra_client import entra_client
from prowler.providers.m365.services.exchange.exchange_client import exchange_client
class exchange_shared_mailbox_sign_in_disabled(Check):
"""
Verify that sign-in is blocked for all shared mailboxes.
Shared mailboxes are designed for collaboration and should not permit direct
sign-in. Users should access shared mailboxes through delegation only, which
ensures accountability and proper access controls.
- PASS: Shared mailbox has sign-in blocked (AccountEnabled = False in Entra ID).
- FAIL: Shared mailbox has sign-in enabled (AccountEnabled = True in Entra ID).
- MANUAL: The Entra users could not be retrieved (tenant-level), or the
shared mailbox could not be resolved in Entra ID, so its sign-in status
cannot be verified.
"""
def execute(self) -> List[CheckReportM365]:
"""
Execute the check to verify shared mailbox sign-in status.
Cross-references shared mailboxes from Exchange Online with user accounts
in Entra ID to determine if sign-in is blocked.
Returns:
List[CheckReportM365]: A list of reports with the sign-in status for
each shared mailbox.
"""
findings = []
# A tenant-wide failure retrieving Entra users would otherwise surface
# as one misleading MANUAL per mailbox: report it once instead.
if exchange_client.shared_mailboxes and entra_client.users_error:
report = CheckReportM365(
metadata=self.metadata(),
resource={},
resource_name="Shared Mailboxes",
resource_id="sharedMailboxes",
)
report.status = "MANUAL"
report.status_extended = (
"Cannot verify sign-in status for shared mailboxes: "
f"{entra_client.users_error}."
)
findings.append(report)
return findings
for shared_mailbox in exchange_client.shared_mailboxes:
report = CheckReportM365(
metadata=self.metadata(),
resource=shared_mailbox,
resource_name=shared_mailbox.name or shared_mailbox.user_principal_name,
resource_id=shared_mailbox.external_directory_object_id
or shared_mailbox.identity,
)
# Look up the user in Entra ID by their external directory object ID
entra_user = entra_client.users.get(
shared_mailbox.external_directory_object_id
)
if not entra_user:
report.status = "MANUAL"
report.status_extended = f"Cannot verify sign-in status for shared mailbox {shared_mailbox.user_principal_name}: the user could not be resolved in Entra ID."
elif entra_user.account_enabled:
report.status = "FAIL"
report.status_extended = f"Shared mailbox {shared_mailbox.user_principal_name} has sign-in enabled."
else:
report.status = "PASS"
report.status_extended = f"Shared mailbox {shared_mailbox.user_principal_name} has sign-in blocked."
findings.append(report)
return findings