M365 Security Baselines: What Your Tenant Is Missing
Your M365 tenant came with defaults optimized for convenience, not security. Legacy authentication is open, conditional access is nonexistent, audit logging is minimal, and sharing is unrestricted. Here is the practical checklist for locking it down before an attacker does it for you.
The default M365 tenant is not secure
When you provision a new Microsoft 365 tenant, it works out of the box. Users can sign in, send email, share files, and join Teams meetings. That functional baseline is exactly what makes it dangerous — everything is permissive by default, and Microsoft leaves the hardening to you.
Out of the box, here is what your tenant allows: legacy authentication protocols (IMAP, POP3, SMTP AUTH) that bypass MFA entirely. No conditional access policies, meaning any device from any location can authenticate. Minimal unified audit logging with short retention. Anonymous sharing links in SharePoint and OneDrive. Unrestricted guest access in Teams. No anti-phishing policies beyond basic EOP defaults.
This is not theoretical risk. Business email compromise (BEC) attacks are the single most costly cybercrime category, accounting for over $2.9 billion in reported losses in 2023 alone according to the FBI IC3 report. The attack pattern is almost always the same: an attacker phishes credentials, logs in via a legacy auth protocol that has no MFA challenge, sets up a mailbox forwarding rule to exfiltrate data, and operates undetected because audit logging was not configured to catch it.
Consent phishing is the other major vector. An attacker sends a legitimate-looking OAuth consent prompt. The user clicks "Accept," and now a malicious app has read access to their mailbox and files — no credentials stolen, no MFA bypassed, just a user clicking a button that Microsoft's defaults allowed.
"It works" is not the same as "it's secure." Let's fix the gaps.
Identity & Access: The big three policies
Conditional Access is the control plane for M365 identity security. Without it, you are relying on users to make good decisions. These three policies should be deployed in every tenant, regardless of size.
Policy 1: Require MFA for all users
Not just admins. Everyone. Microsoft's own data shows that MFA blocks 99.9% of automated attacks. The most common objection is "our users will complain." They will complain more when their mailbox is compromised and the CEO's wire transfer instructions turn out to be from an attacker in Lagos.
Use Security Defaults as a minimum if you do not have P1 licensing, but conditional access policies give you far more control. Exclude a break-glass account (and monitor it heavily).
Key detail: Security Defaults and Conditional Access are mutually exclusive. If you enable CA policies, disable Security Defaults first or they will conflict.
Policy 2: Block legacy authentication protocols
Legacy auth protocols — IMAP, POP3, SMTP AUTH, Exchange ActiveSync with basic auth, and Exchange Web Services with basic auth — do not support MFA. An attacker with a valid username and password can authenticate via IMAP even if the user has MFA enabled on their account. This is not a bug; it is how the protocols work.
Create a conditional access policy that targets all users, all cloud apps, and blocks the "Other clients" condition. This catches all legacy auth protocols. Test with report-only mode first — you may have a multifunction printer or an old app still using basic SMTP auth.
Policy 3: Require compliant or hybrid-joined devices
If you have Intune or hybrid Azure AD join deployed, add a policy that requires devices accessing Office 365 apps to be compliant or domain-joined. This prevents access from unmanaged personal devices, kiosk machines, and attacker-controlled endpoints. For BYOD scenarios, use app protection policies as an alternative grant.
Audit your current state with PowerShell
Before creating new policies, audit what exists. Many tenants have stale or conflicting conditional access policies from previous admins.
# Connect to Microsoft Graph
Connect-MgGraph -Scopes "Policy.Read.All"
# List all Conditional Access policies with their state
Get-MgIdentityConditionalAccessPolicy | Select-Object `
DisplayName, State, CreatedDateTime, ModifiedDateTime |
Format-Table -AutoSize
# Check for policies in report-only mode (common leftover)
Get-MgIdentityConditionalAccessPolicy |
Where-Object { $_.State -eq "enabledForReportingButNotEnforced" } |
Select-Object DisplayName Check MFA registration status across users
Before enforcing MFA, identify who has not registered yet. Rolling out MFA enforcement without a registration campaign leads to locked-out users and a flooded helpdesk.
# Get MFA registration details for all users
Connect-MgGraph -Scopes "UserAuthenticationMethod.Read.All","User.Read.All"
# Pull authentication method registration status
$Users = Get-MgUser -All -Property DisplayName, UserPrincipalName, Id
$Report = foreach ($User in $Users) {
$Methods = Get-MgUserAuthenticationMethod -UserId $User.Id
[PSCustomObject]@{
DisplayName = $User.DisplayName
UPN = $User.UserPrincipalName
MethodCount = $Methods.Count
HasMFA = ($Methods.Count -gt 1) # Password = 1, MFA = 2+
}
}
# Show users without MFA registered
$Report | Where-Object { -not $_.HasMFA } |
Sort-Object DisplayName |
Format-Table -AutoSize Email security essentials
Email is the primary attack surface for most organizations. M365 provides layered defenses, but most of them require manual configuration.
SPF, DKIM, and DMARC records
These three DNS records work together to prevent domain spoofing. SPF declares which servers can send email for your domain. DKIM cryptographically signs outbound messages. DMARC tells receiving servers what to do when SPF or DKIM fails. Without all three, anyone can send email that looks like it came from your domain.
# SPF record — add as TXT record on your domain
v=spf1 include:spf.protection.outlook.com -all
# DKIM — enable via Exchange Admin Center or PowerShell
# Two CNAME records are required per domain:
selector1._domainkey.contoso.com → selector1-contoso-com._domainkey.contoso.onmicrosoft.com
selector2._domainkey.contoso.com → selector2-contoso-com._domainkey.contoso.onmicrosoft.com
# DMARC record — start with monitoring, then enforce
# Phase 1 (monitor):
v=DMARC1; p=none; rua=mailto:dmarc-reports@contoso.com; pct=100
# Phase 2 (quarantine after reviewing reports):
v=DMARC1; p=quarantine; rua=mailto:dmarc-reports@contoso.com; pct=100
# Phase 3 (reject — full enforcement):
v=DMARC1; p=reject; rua=mailto:dmarc-reports@contoso.com; pct=100 Key detail: Do not jump
straight to p=reject.
Start with p=none
and monitor the aggregate reports for 2-4 weeks. You will almost certainly discover
legitimate services sending email from your domain that you forgot about (marketing
tools, CRM systems, ticketing platforms).
Anti-phishing policies in Defender for Office 365
If you have Microsoft Defender for Office 365 (Plan 1 or 2), configure these anti-phishing settings. The defaults are intentionally conservative — Microsoft errs on the side of not blocking legitimate mail, which means phishing gets through.
Safe Links and Safe Attachments
Safe Links rewrites URLs in email messages and checks them at click time — not just at delivery time. An attacker can send a clean URL and weaponize it after delivery. Safe Attachments detonates attachments in a sandbox before delivering them. Enable both for all users, and enable Safe Attachments for SharePoint, OneDrive, and Teams as well.
Mailbox forwarding rules: The #1 BEC persistence mechanism
After compromising an account, the first thing an attacker does is create a forwarding rule. This lets them silently receive copies of all incoming email even after you reset the password and enable MFA. Check for these regularly.
# Connect to Exchange Online
Connect-ExchangeOnline
# Find mailboxes with external forwarding (SMTP forwarding)
Get-Mailbox -ResultSize Unlimited |
Where-Object { $_.ForwardingSmtpAddress -ne $null } |
Select-Object DisplayName, UserPrincipalName, ForwardingSmtpAddress,
DeliverToMailboxAndForward |
Format-Table -AutoSize
# Find inbox rules that forward or redirect externally
$Mailboxes = Get-Mailbox -ResultSize Unlimited
foreach ($mbx in $Mailboxes) {
$Rules = Get-InboxRule -Mailbox $mbx.UserPrincipalName -ErrorAction SilentlyContinue |
Where-Object { $_.ForwardTo -or $_.ForwardAsAttachmentTo -or $_.RedirectTo }
if ($Rules) {
foreach ($rule in $Rules) {
[PSCustomObject]@{
Mailbox = $mbx.UserPrincipalName
RuleName = $rule.Name
ForwardTo = $rule.ForwardTo -join ";"
RedirectTo = $rule.RedirectTo -join ";"
Enabled = $rule.Enabled
}
}
}
} | Format-Table -AutoSize Pro tip: Set a transport rule to block automatic external forwarding tenant-wide. Users rarely have a legitimate reason to forward all their email externally, and this single rule shuts down one of the most common BEC persistence techniques.
Audit logging: What to turn on
Unified audit logging is enabled by default in M365, but "enabled" does not mean "useful." Many critical events are not captured at the default level, retention is only 90 days (180 for E5), and mailbox-level auditing has its own separate configuration.
Enable mailbox audit logging for all mailboxes
Since January 2019, Microsoft enables mailbox auditing by default for new mailboxes. But mailboxes created before that date, or mailboxes where auditing was manually disabled, may not have it. Verify and enforce across the tenant.
# Check which mailboxes do NOT have audit logging enabled
Get-Mailbox -ResultSize Unlimited |
Where-Object { $_.AuditEnabled -eq $false } |
Select-Object DisplayName, UserPrincipalName, AuditEnabled |
Format-Table -AutoSize
# Enable auditing on all mailboxes that have it disabled
Get-Mailbox -ResultSize Unlimited |
Where-Object { $_.AuditEnabled -eq $false } |
ForEach-Object {
Set-Mailbox -Identity $_.UserPrincipalName -AuditEnabled $true
Write-Host "Enabled audit logging for $($_.UserPrincipalName)"
}
# Verify the default audit actions are comprehensive
Get-Mailbox -Identity "admin@contoso.com" |
Select-Object AuditAdmin, AuditDelegate, AuditOwner Configure alert policies for critical events
M365 ships with some default alert policies, but they are limited. Create custom alerts for the events that matter most in a breach scenario.
Extend audit log retention
The default 90-day retention is not enough for compliance or incident response. Most security frameworks (NIST, CIS, SOC 2) require at least one year. If you have E5 or E5 Compliance add-on licensing, you can configure up to 10 years of retention.
# Connect to Security & Compliance PowerShell
Connect-IPPSSession
# Create a 1-year retention policy for all audit records
New-UnifiedAuditLogRetentionPolicy `
-Name "1-Year Audit Retention" `
-Description "Retain all audit logs for 365 days" `
-RetentionDuration TwelveMonths `
-Priority 100
# Verify the policy was created
Get-UnifiedAuditLogRetentionPolicy | Format-Table Name, RetentionDuration, Priority Budget alternative: If you
do not have E5 licensing, export audit logs to an Azure Log Analytics workspace
or a SIEM on a scheduled basis. A simple PowerShell scheduled task pulling
Search-UnifiedAuditLog
daily and writing to CSV is better than losing the data entirely.
SharePoint and OneDrive sharing defaults
The default sharing settings in SharePoint Online and OneDrive for Business are designed for maximum collaboration. That means "Anyone with the link" sharing is enabled, anonymous access is allowed, and there are no restrictions on external sharing. For most organizations, this is far too permissive.
Tighten sharing settings
At minimum, disable anonymous sharing links and restrict external sharing to authenticated users from specific domains. Here is how to check and configure the settings via PowerShell.
# Connect to SharePoint Online
Connect-SPOService -Url "https://contoso-admin.sharepoint.com"
# Check current tenant-level sharing settings
Get-SPOTenant | Select-Object `
SharingCapability,
DefaultSharingLinkType,
FileAnonymousLinkType,
FolderAnonymousLinkType,
RequireAcceptingAccountMatchInvitedAccount
# Restrict to authenticated external users only (no anonymous links)
Set-SPOTenant -SharingCapability ExternalUserSharingOnly
# Set default link type to "Specific people" instead of "Anyone"
Set-SPOTenant -DefaultSharingLinkType Direct
# Require external users to accept sharing invitation with same account
Set-SPOTenant -RequireAcceptingAccountMatchInvitedAccount $true
# Optional: Restrict sharing to specific domains
Set-SPOTenant -SharingDomainRestrictionMode AllowList `
-SharingAllowedDomainList "partnercorp.com vendorco.com" Enable DLP policies for sensitive files
Data Loss Prevention policies can detect and block sharing of files containing sensitive information like credit card numbers, Social Security numbers, or health records. Start with the built-in sensitive information types and add custom patterns for your industry.
Teams security: The overlooked surface
Teams is the most underestimated attack surface in M365. It combines chat, file sharing, meetings, and third-party app integrations into a single platform that most security teams treat as "just a chat app." The default settings are permissive, and most organizations never touch them.
Guest access policies
By default, anyone in your organization can invite external guests to Teams. Those guests then get access to the team's channels, files, and chat history. Tighten this down.
Meeting policies
Default meeting settings allow anonymous users to join meetings, bypass the lobby, and present content. For internal meetings this might be acceptable, but for an organization handling sensitive information, lock it down.
Third-party app restrictions
Teams supports third-party apps that can access messages, files, and user data. By default, users can install any app from the Teams store. This is the consent phishing vector applied to Teams instead of email.
Quick-win checklist: 10 things to do today
In priority order. You can get through all ten in about an hour. Each one meaningfully reduces your attack surface.
1. Enable Conditional Access: Block legacy authentication
Create a CA policy that blocks "Other clients" for all users. This single policy closes the biggest authentication gap in your tenant. Deploy in report-only first, verify no legitimate services break, then enforce.
2. Require MFA for all users via Conditional Access
If you already have Security Defaults, this is done. If not, create a CA policy requiring MFA for all cloud apps. Exclude one break-glass account and set up alerting on that account's sign-ins.
3. Block external mail forwarding tenant-wide
Create a mail flow rule in Exchange Admin Center that blocks automatic external forwarding. This prevents the most common BEC persistence technique. Takes two minutes and stops a real attack pattern.
4. Check for existing external forwarding rules
Run the forwarding audit script from the email section above. If you find forwarding rules you did not create, treat it as a potential compromise. Investigate immediately.
5. Publish SPF, DKIM, and DMARC records
If you do not have all three, add them now. SPF takes one DNS record. DKIM takes two CNAMEs and a toggle. DMARC takes one TXT record in monitoring mode. You can deploy all three in under 15 minutes.
6. Disable "Anyone" sharing links in SharePoint/OneDrive
Change the tenant sharing level to "Existing external users" or "New and existing external users" — anything but "Anyone." Set the default link type to "Specific people."
7. Enable mailbox audit logging for all mailboxes
Run the audit check script from above. Enable auditing on any mailboxes that have it disabled. This takes one command and gives you visibility into mailbox access that you cannot get any other way.
8. Restrict third-party app consent in Azure AD
In Entra ID, go to Enterprise applications and set "Users can consent to apps accessing company data on their behalf" to No. Require admin approval for app consent. This stops consent phishing attacks.
9. Enable Safe Links and Safe Attachments
If you have Defender for Office 365, create policies that cover all users. Enable URL detonation, real-time URL scanning on click, and Safe Attachments for SharePoint, OneDrive, and Teams.
10. Review admin role assignments
Check who has Global Admin. You should have no more than 2-4 Global Admins, plus a break-glass account. Everyone else should have the minimum role required. Use PIM (Privileged Identity Management) for just-in-time activation if you have P2 licensing.
Want the full hardening kit?
The M365 Tenant Hardening Kit takes everything in this post and turns it into actionable scripts, templates, and runbooks. Stop copying commands from blog posts — deploy a tested, repeatable hardening process across every tenant you manage.
- 80+ item security checklist covering identity, email, sharing, Teams, and compliance
- Conditional Access policy templates ready to import
- Audit monitoring script with automated alerting and reporting
- Tenant hardening report script — run it to get a scored baseline assessment
- 4 incident response playbooks for BEC, consent phishing, data exfiltration, and account compromise