I’ve been diving into the Center for Internet Security’s (CIS) benchmarks lately – which are a set of benchmarks to use against different technologies (including Microsoft 365 and freely available for non-commercial use). They are a good set of checks to go through in a tenant to review configuration with a security focus; including how to remediate.
There is of course a lot more to it than reading a document and configuring items the way it says to; you need to understand what you’re changing, and what impact that may have to the business and it’s end users. For example; blocking the ability to share anonymous links from SharePoint/OneDrive is generally ‘a good idea’ security wise, but if your users are actually doing that you probably don’t want to just shut that off. You need to assess what’s being used and how, and have a strategy to get to a more secure point.
Anyway, I’ve picked my favourite 5 settings from their comprehensive list that I feel people could miss; I may have missed these myself when I used to be a Microsoft 365 administrator.
For PowerShell commands, if you’re not sure how to get to the right module (e.g. Exchange Online from my first example) then check out msshells.net which will show you how to install and connect.
The headings are quoted from CIS, but the rest of the material is my own:
1 – 3.1.1 Ensure Microsoft 365 audit log search is Enabled
If you’re a Microsoft 365 focused admin, Azure and log search may not be a front of mind for you unless you go looking to solve a problem that arises.
This should be enabled in new tenants, but older ones may not have it. First check it’s status with the PowerShell command in Exchange Online:
Get-AdminAuditLogConfig | Select UnifiedAuditLogIngestionEnabled
This will show a True or Fasle value – if it’s True, it’s on. If it’s off/false, enable it with this command:
Set-AdminAuditLogConfig -UnifiedAuditLogIngestionEnabled $true
This should have no user impact and just enables the ingestion of the Audit Logs.
To view these logs you can use PowerShell commands, but this is generally one I’d rather use a GUI for – go to the Microsoft Purview portal and the Audit section, and trigger a search. Without getting into too much detail, there’s two tiers of Audit – Standard and Premium. Read further information here.
2. Ensure modern authentication for SharePoint applications is required
This is another that many old tenants may have disabled. SharePoint has ‘legacy authentication’ similar to other services that are planning or already deprecated legacy auth – Exchange Online being the common one most people know about.
To check if you have this disabled, connect via PowerShell to SharePoint Online and run the command:
Get-SPOTenant | ft LegacyAuthProtocolsEnabled
True means it’s enabled, False means disabled – and we want it to be False. The command to enable it is:
Set-SPOTenant -LegacyAuthProtocolsEnabled $false
Entra ID’s Conditional Access should be configured to block all Legacy Auth requests also, but this is an extra layer to make sure SharePoint won’t work that way anyway (plus holes are poked through Conditional Access all the time!). There seems to be very little official public documentation about this option from Microsoft – I could find this example where they show how to set it to $true to avoid some login issues which is a bit concerning.
This is one that may have some user impact or application impact if systems are connecting to SharePoint Online in legacy ways. Users should be used to modern auth and match their experiences in other Microsoft 365 services – applications however would need to be redesigned or updated to accommodate this. You can search the Entra ID authentication logs for any attempts to connect to SharePoint Online using legacy authentication over as long as possible before changing this setting.
3. Ensure sign-in to shared mailboxes is blocked (Automated)
Shared Mailboxes are both a delight for having a central area for emails to go to, and multiple staff having access to them, but also a dismay in user expectations of being able to send as the account, and potentially log in as it. A reception desk or similar may have multiple people jumping in and out of the location, but they want to access the same contents without the time-taking task of logging in and out of the computer each time. Regardless – security wise each user should have a unique login, and all their actions performed under that login.
Although it can be a fight and go way beyond a technical issue – shared mailboxes should be disabled from logging in. A disabled from login shared mailbox can still send and receive emails; you’re only disabling the ability to log in using that account itself, and the mailbox can still be accessed as a delegate.
As this is a per account setting, you’ll need to check all shared mailboxes. As per Microsoft Learn, you can block a single account from the Microsoft 365 Admin Center and go to Users > Active Users, select a Shared Mailbox, and click the ‘Block Sign-In’ option:
… but this doesn’t really scale to check all Shared Mailboxes and change the setting. Instead, as per Microsoft Learn, we have to use Exchange Online PowerShell to find the shared mailboxes, then we can use Microsoft Graph PowerShell SDK to disable them. After connecting to Exchange Online and Microsoft Graph with the below scope:
Connect-Graph -Scopes User.ReadWrite.All
You can then run the one command to use Exchange Online to find all Shared mailboxes and then use Microsoft Graph to set the account to disabled:
Get-EXOMailbox -RecipientTypeDetails "SharedMailbox" | ForEach {Update-MgUser -UserId $_.ExternalDirectoryObjectId -AccountEnabled:$false}
You could also do the same for Room and Equipment mailboxes if they don’t need to sign in:
Get-EXOMailbox -RecipientTypeDetails "RoomMailbox","EquipmentMailbox" | ForEach {Update-MgUser -UserId $_.ExternalDirectoryObjectId -AccountEnabled:$false}
Also note that Exchange Online has it’s own ‘AccountDisabled’ variable which you could set to true, but this blocks sign in to the mailbox, and not the entire account to any M365 service/Entra ID authentication.
User impact on this needs to be assessed by again checking the Entra ID logs against each Shared Mailbox, and working out how to set systems up to avoid the shared account login. There may be some user resistance to this, but one argument could be ‘what if someone sent a nasty email to your boss under the account and they thought it was you – you couldn’t prove it wasn’t easily if others are also using that same account’.
4. Ensure ‘Per-user MFA’ is disabled
This is the ‘old’ MFA before Conditional Access was around. This only suported the MFA methods of ‘Call to phone, Text message to phone, Notification through mobile app, and Verification code deom mobile app or hardware token’.
You can check if any users have this enabled by going to https://account.activedirectory.windowsazure.com/usermanagement/multifactorverification.aspx and ensuring all users show as ‘disabled’ for the ‘MULTI-FACTOR AUTHENTICATION STATUS’ column.
If you see any users enabled, then you should ensure Conditional Access is set up and ready to go, then change the users to disabled. You also shouldn’t be using this function at all when Conditional Access is enabled. A few warnings from Microsoft:
More details here: https://learn.microsoft.com/en-us/entra/identity/authentication/howto-mfa-userstates
5. Ensure a dynamic group for guest users is created
I quite like this one. Yes, you can reasonably easily determine if an account is a guest account or not, but having an automated group means it’s easy to point other Conditional Access policies, or other monitoring, on what these accounts are doing in your tenant. It’s very little effort to create, doesn’t need maintenance, and can help in other scenarios when you want to review what guest accounts are around.
How to do this is well documented by Microsoft but you do need an Entra ID Plan 1 or Plan 2 license to create dynamic groups.
Simply create a New Group in the Entra Admin Center https://entra.microsoft.com/#view/Microsoft_AAD_IAM/AddGroupBlade
and after selecting a Group Name and choosing Memebership type: Dynamics user, click ‘add dynamic query’:
Use the filters Property = userType, Operator = Equals, Value = Guest, and click ‘Save’, then ‘Create’.
Note that it can take a minute for the group to initially populate. You can now use this group to block from certain things as an extra layer of protection against accidental permissions, or have extra Conditional Access policies that always require certain MFA methods.
If you don’t have Entra ID Plan 2 to be able to have guest reviews, you could use the membership of this group as a simple way to review the guest accounts in your tenant.
That’s my top 5 picks – check out the CIS Benchmark for Microsoft 365 yourself along with their other benchmarks as there’s a lot to learn and check through. It’s also not a one-time thing, settings change, the benchmark itself grows (currently at v3.1 at the time of writing), plus there’s more security to check beyond this!