Microsoft 365: Multi-Factor Authentication Verplicht Stellen Voor Alle Gebruikers

💼 Management Samenvatting

Multi-Factor Authentication (MFA) voor alle Microsoft 365-gebruikers is de meest effectieve beveiligingscontrole tegen account compromises, met een preventiepercentage van 99,9% volgens Microsoft's security onderzoek. MFA is een fundamentele Zero Trust-controle en verplicht onder vrijwel alle moderne compliance-frameworks.

Aanbeveling
IMPLEMENT
Risico zonder
Critical
Risk Score
10/10
Implementatie
16u (tech: 4u)
Van toepassing op:
M365
Azure AD

Authenticatie die uitsluitend op wachtwoorden berust, is extreem kwetsbaar voor moderne aanvalsmethoden. Phishing-aanvallen, waarbij aanvallers gebruikers misleiden om hun credentials in te voeren op nepwebsites, zijn zeer succesvol met een gemiddeld slagingspercentage van 20-30% volgens security studies. Password spraying-aanvallen waarbij aanvallers veelgebruikte wachtwoorden proberen tegen vele accounts tegelijk, zijn effectief omdat gebruikers voorspelbare wachtwoorden kiezen zoals Welkom01 of Zomer2024. Credential stuffing met leaked passwords uit data breaches van andere services (haveibeenpwned.com bevat miljarden gelekte credentials) succesvol is omdat mensen dezelfde wachtwoorden hergebruiken over meerdere services. Keyloggers en malware kunnen wachtwoorden stelen van gecompromitteerde machines zonder dat gebruikers het merken. Deze aanvallen resulteren in account takeover waarbij aanvallers volledige toegang krijgen tot email, SharePoint, Teams en andere M365-services, wat kan leiden tot business email compromise (BEC) fraude met gemiddelde schade van €100.000-500.000 per incident, data exfiltratie van gevoelige bedrijfsinformatie of klantgegevens, ransomware deployment via gecompromitteerde admin accounts, en reputatieschade. Multi-Factor Authentication elimineert 99,9% van deze risico's door een tweede factor toe te voegen die de aanvaller niet heeft: iets dat je hebt zoals een telefoon met Microsoft Authenticator app of een FIDO2 hardware security key, of iets dat je bent zoals een biometrische factor via Windows Hello for Business. Zelfs als een aanvaller het wachtwoord heeft gestolen via phishing, kan deze niet inloggen zonder de tweede factor, wat account takeover effectief voorkomt. Voor organisaties is MFA verplicht onder NIS2 Artikel 21 voor toegang tot kritieke systemen, BIO overheidsrichtlijn 09.04, ISO 27001 controle A.5.17 voor authentication information, en CIS Microsoft 365 Foundations Benchmark controle 1.1.5 Level 1.

PowerShell Modules Vereist
Primary API: Microsoft Graph API
Connection: Connect-MgGraph
Required Modules: Microsoft.Graph.Identity.SignIns

Implementatie

Deze maatregel implementeert verplichte Multi-Factor Authentication voor alle Microsoft 365-gebruikers via een Conditional Access policy die zonder uitzonderingen wordt afgedwongen. De policy wordt geconfigureerd met de volgende settings: Users scope omvat 'All users' met uitsluitend break-glass emergency access accounts die expliciet worden excluded om lockout-scenario's te voorkomen, Cloud apps scope is ingesteld op 'All cloud apps' zodat MFA wordt vereist voor alle Microsoft 365-services inclusief Exchange Online, SharePoint, Teams, Azure Portal, etc., en Grant controls vereist 'Require multi-factor authentication' zonder mogelijkheid tot bypass. De aanbevolen MFA-methoden in volgorde van security strength zijn: FIDO2 security keys (phishing-resistant hardware tokens, meest secure), Microsoft Authenticator app met push notifications of passwordless phone sign-in (phishing-resistant via number matching), Windows Hello for Business voor biometrische authenticatie op Windows devices, en certificaat-based authentication voor high-security scenarios. SMS en voice calls moeten worden vermeden omdat deze phishable zijn via SIM swapping of social engineering, en alleen als fallback methode beschikbaar worden gehouden. De implementatie volgt een phased rollout approach: eerst wordt de policy gecreëerd in Report-only mode waarbij gedurende 2 weken wordt gemonitord hoeveel sign-ins MFA zouden triggeren zonder daadwerkelijk te blokkeren, daarna wordt MFA-registratie geforceerd waarbij users bij hun volgende login worden verplicht om een MFA-methode te registreren, pilot groups worden eerst enabled voor validation, en tenslotte wordt de policy ingesteld op 'On' mode waarbij MFA universal wordt afgedwongen. Target is 100% MFA-registratie binnen 30 dagen met helpdesk support voor users. Sign-in logs moeten worden gemonitord om MFA-adoption te tracken en users zonder MFA te identificeren voor follow-up. De implementatie kost 4 uur technisch werk voor policy-configuratie plus 12 uur organizational effort voor user communication, training en helpdesk support. Dit is een non-negotiable security control en absolute must-have voor alle M365-omgevingen.

Vereisten

Een organisatie die Multi-Factor Authentication voor alle gebruikers wil afdwingen binnen de Nederlandse Baseline voor Veilige Cloud moet starten met een stevige fundamentlaag van licenties, processen en technische randvoorwaarden. Azure AD Premium P1 of hoger is onmisbaar om Conditional Access, Identity Protection en rapportages te kunnen gebruiken; daarnaast is het cruciaal om in kaart te brengen welke externe identiteiten, gastgebruikers en dienstaccounts actief zijn zodat zij niet onverwacht buiten de boot vallen. Elk account krijgt een duidelijk eigenaar in het Identity Governance-register zodat er geen onbeheerde logins overblijven die MFA kunnen omzeilen.

Een tweede pijler is de inrichting van noodtoegangsaccounts, vaak twee break-glass accounts met een uniek lang wachtwoord, hardware token en uitsluiting in het CA-beleid. Deze accounts moeten fysiek en procedureel worden beschermd, bijvoorbeeld via een verzegelde kluis met uitgifteprotocol dat door minimaal twee managers wordt ondertekend. Tegelijkertijd moeten service accounts worden beoordeeld: waar mogelijk worden ze omgezet naar beheerde identiteiten of workload identities die certificate-based authenticatie ondersteunen; alleen wanneer dit aantoonbaar niet kan, blijft een uitzondering tijdelijk bestaan, voorzien van een expliciete goedkeuring door de CISO.

De derde vereiste betreft adoptievoorbereiding. Er wordt een communicatiepakket opgesteld met instructies, FAQ, escalatiepad en meertalige templates zodat iedere medewerker binnen 30 dagen een methode registreert. Helpdeskmedewerkers krijgen een aparte trainingssessie inclusief simulatie van veelvoorkomende scenario’s zoals een verloren telefoon of SIM-swap. Voor medewerkers zonder smartphone worden alternatieven, zoals FIDO2-sleutels of Windows Hello for Business met externe beveiligingssleutels, vooraf besteld en uitgereikt. Werkplekken moeten de Microsoft Authenticator push notificaties ondersteunen; controleer daarom dat alle mobiele besturingssystemen up-to-date zijn en dat Device Compliance policies push-berichten niet blokkeren.

Tot slot hoort een governance- en monitoringraamwerk bij de vereisten. Er wordt afgesproken dat MFA-registratierapporten wekelijks aan het securityboard worden gepresenteerd, dat afwijkingen in maximaal twee werkdagen worden hersteld en dat elk nieuw systeem via het changeproces beoordeeld wordt op MFA-impact. Audit logging moet zijn ingeschakeld op Azure AD, Microsoft 365 Defender en Sentinel zodat bewijsstukken zeven jaar beschikbaar blijven. Zonder deze voorbereidingen ontstaat het risico op lock-outs, ongedocumenteerde uitzonderingen en onvoldoende bewijsvoering richting toezichthouders, waardoor de effectiviteit van MFA ondergraven wordt.

Een vaak vergeten vereiste is het integreren van MFA in het bredere risicobeheer. De organisatie moet bepalen hoe MFA-registratie verplicht wordt bij onboarding, hoe offboarding toekomstige toegang blokkeert en hoe periodiek wordt gecontroleerd dat alle geregistreerde apparaten nog steeds eigendom zijn van de gebruiker. Dit vereist samenwerking tussen HR, Identity & Access Management en fysieke beveiliging. Daarnaast moet de privacy officer bevestigen dat het gebruik van biometrische gegevens in lijn is met AVG-artikel 9 en dat eventueel gebruik van locatieservices in de Authenticator app transparant wordt uitgelegd aan medewerkers.

Verder moet er voldoende technische capaciteit beschikbaar zijn om authenticatieverzoeken af te handelen. Controleer of Azure AD rate limits, netwerk firewalls, web proxies en mobiele device management profielen pushmeldingen niet vertragen. Test of roaming gebruikers via privéapparaten nog steeds hun tweede factor kunnen ontvangen en leg vast hoe uitzonderingen worden afgehandeld wanneer medewerkers in streng beveiligde locaties geen telefoon mogen meenemen. Tot slot hoort bij de vereisten een contractueel kader richting leveranciers: in service level agreements wordt opgenomen dat toegang tot gedeelde tenants of supportportalen uitsluitend mogelijk is met MFA, zodat ketenpartners dezelfde beveiligingsstandaard hanteren.

Implementatie

De implementatie start met een nulmeting: exporteer uit Azure AD de huidige status van beveiligingsstandaard policies, bestaande Conditional Access regels en het percentage gebruikers met geregistreerde MFA-methoden. Deze nulmeting vormt het referentiedocument voor auditors en geeft inzicht in de benodigde communicatie- en supportcapaciteit. Vervolgens wordt in een niet-productie tenant de doelpolicy opgebouwd zodat alle instellingen kunnen worden getest zonder eindgebruikers te beïnvloeden. Denk aan de selectie van All users, het uitsluiten van de break-glass groep, het kiezen van All cloud apps en het instellen van een Grant control waarin Require multi-factor authentication gecombineerd wordt met Session controls zoals Sign-in frequency om de ervaring consistent te houden.

Na validatie wordt dezelfde policy in productie aangemaakt in report-only modus. Gedurende minimaal veertien dagen worden de sign-in logs en de Conditional Access insights dashboards geanalyseerd om te zien welke scenario’s geraakt worden, zoals oude scanners die SMTP AUTH gebruiken of third-party applicaties met legacy protocollen. Bevindingen worden vertaald naar mitigerende acties, bijvoorbeeld het inschakelen van SMTP AUTH client submission met app-wachtwoorden of het migreren naar modern authenticatie. Parallel start de registratiecampagne: via Azure AD Registration Campaigns, e-mail, intranet en Teams-berichten ontvangen medewerkers duidelijke stappenplannen, inclusief verwijzingen naar AVG-proof instructievideo’s en de Nederlandse Baseline voor Veilige Cloud richtlijnen.

Zodra minimaal 70% van de gebruikers een primaire en secundaire factor heeft geregistreerd, verschuift de policy naar On voor geselecteerde pilotgroepen zoals het securityteam, IT-beheer en een representatieve businessunit. Hun ervaringen worden binnen 48 uur geëvalueerd en verwerkt in een lessons-learned document. Daarna volgt de organisatiebrede uitrol. Gebruik Change Management om dagelijks voortgang te rapporteren, obstakels te documenteren en beslissingen te formaliseren. Voor iedere uitzondering wordt een tijdelijke Conditional Access filter gemaakt met een harde einddatum en compensating controls. Wanneer de 100% registratie is bereikt, wordt Report-only definitief uitgeschakeld, worden legacy authentications geblokkeerd en wordt het monitoring script `Invoke-Monitoring` ingepland in Azure Automation of een GitHub Actions workflow zodat de conformiteit continu wordt gecontroleerd.

De afronding bestaat uit drie acties: ten eerste het vastleggen van het beleid en de Azure AD export in het compliance-dossier, ten tweede het uitvoeren van een gecontroleerde hersteltest waarbij wordt gevalideerd dat break-glass accounts daadwerkelijk toegang houden, en ten derde het informeren van de organisatie dat MFA verplicht is en dat het helpdeskscript voor verloren apparaten bereikbaar is. Combineer dit met een maandelijkse review van sign-in risicorapporten zodat nieuwe gebruikers of leveranciers direct worden meegenomen. Door deze stapsgewijze aanpak blijft de businesscontinuïteit gewaarborgd terwijl de beveiligingsdoelstelling zonder concessies wordt gehaald.

Een volwassen implementatie kent daarnaast continue verbetering. Automatiseer registratiecampagnes via Graph API of Azure Automation zodat nieuwe medewerkers direct een reminder ontvangen indien zij na vijf dagen nog geen tweede factor hebben ingesteld. Integreer het monitoringresultaat met het Security Operations Center zodat hoge-risico sign-ins met een ontbrekende MFA prompt automatisch een incidentticket krijgen. Koppel tot slot de Conditional Access policy aan Identity Protection risk policies zodat risk-based MFA aanvullend kan worden afgedwongen bij verdachte aanmeldingen, zonder de primaire verplichting te verzwakken. Documenteer elke wijziging in een Configuration Management Database zodat auditors kunnen herleiden welke versie van het beleid wanneer actief was en welke testen daarbij hoorden; dit voorkomt discussie over retroactieve wijzigingen.

Compliance en Auditing

Het verplicht stellen van Multi-Factor Authentication is een van de weinige maatregelen die simultaan tegemoetkomt aan nagenoeg alle relevante normen voor Nederlandse publieke organisaties. Binnen het CIS Microsoft 365 Foundations Benchmark adresseert het rechtstreeks controle 1.1.5, waarbij auditors verwachten dat een Conditional Access beleid kan worden getoond inclusief export met Policy ID, status en scope. Voor de Baseline Informatiebeveiliging Overheid (BIO) raakt het maatregelcluster 09.04 waarin sterke authenticatie voor beheerders- en gebruikersaccounts wordt geëist; tijdens audits moet kunnen worden aangetoond dat beleid, registratierapporten en helpdeskprocedures consistent zijn en dat uitzonderingen expliciet via het risicoregister zijn geautoriseerd door de Chief Information Security Officer.

ISO 27001:2022 controle A.5.17 schrijft voor dat authenticatiemiddelen passend bij het risicoprofiel zijn. Dat betekent dat organisaties moeten aantonen waarom bepaalde methoden (bijvoorbeeld FIDO2 met hardware sleutels) wel of niet worden verplicht voor hoog-risico functies. Documenteer in het Statement of Applicability hoe MFA is geïmplementeerd, welke fallback-procedures bestaan en hoe periodieke reviews plaatsvinden. De NIS2-richtlijn, artikel 21 lid 2, benoemt expliciet dat aanbieders van essentiële en belangrijke diensten meervoudige authenticatie moeten toepassen waar passend; bij Inspectie Gezondheid en Jeugd of Agentschap Telecom controles wordt gevraagd naar technische bewijsstukken, bijvoorbeeld sign-in logs die laten zien dat MFA prompt is uitgevoerd vóórdat toegang tot gevoelige workloads is verkregen.

Voor identiteitsniveaus verwijst het Nationaal Cyber Security Centrum naar NIST SP 800-63B. Het beleid moet dus minimaal voldoen aan Assurance Level AAL2, wat inhoudt dat kennisfactoren worden gecombineerd met een bezit- of inherente factor die door een gecertificeerde authenticator wordt geleverd. Wanneer phishing-resistente methoden worden ingezet (zoals FIDO2 of certificate-based authenticatie) kan zelfs AAL3 gedeeltelijk worden afgedekt. Leg vast dat SMS en spraak alleen zijn toegestaan als noodoptie en maximaal 24 uur geactiveerd blijven. Bewaar audit evidence gedurende zeven jaar: kopieën van het CA-beleid, exports van `Get-MgIdentityConditionalAccessPolicy`, screenshots van registratiecampagnes, output van het monitoring script en tickets die aantonen dat uitzonderingen tijdig zijn opgeheven. Deze set vormt de bewijslast richting de Autoriteit Persoonsgegevens bij toezicht op AVG-artikel 32, toont naleving van de Nederlandse Baseline voor Veilige Cloud aan en maakt incidentrespons sneller, omdat men direct kan aantonen welke accounts onder MFA vallen en welke niet.

Daarnaast vraagt interne auditing om meetbare Key Risk Indicators. Definieer bijvoorbeeld dat maximaal 1% van de gebruikers een actieve uitzondering mag hebben en dat deze binnen tien werkdagen moet worden opgeheven. Rapporteer maandelijks aan de Raad van Bestuur over het percentage phishing-resistente methoden om aan te tonen dat men richting AAL3 groeit. In het kader van ENSIA en DigiD-assessments kan dezelfde dataset worden gebruikt om aan te tonen dat beheerders van voorzieningen met een hoog beveiligingsniveau daadwerkelijk MFA toepassen. Tot slot moet worden vastgelegd hoe incidenten met tweede factoren worden gemeld en opgelost; denk aan een formeel proces waarin verlies van een security key leidt tot directe intrekking via Azure AD en registratie in het security incident register. Met deze aanvullende waarborgen ontstaat een sluitende audittrail die zowel interne inspecties als externe toezichthouders overtuigt.

Om volledig aantoonbaar te blijven, hoort bij elk compliance-kader een duidelijke mapping in de architectuurdocumentatie. Beschrijf welke paragrafen van de Nederlandse Baseline voor Veilige Cloud door MFA worden afgedekt, welke controles aanvullend nodig zijn (zoals device compliance) en hoe bewijsvoering wordt gedeeld met ketenpartners. Voeg een jaarlijkse onafhankelijke review toe waarin een derde partij controleert of de Conditional Access policies ongewijzigd functioneren en of registratierapporten overeenkomen met de werkelijkheid; zo wordt continu aangetoond dat MFA niet alleen op papier maar ook operationeel effectief is.

Monitoring

Gebruik PowerShell-script mfa-alle-gebruikers.ps1 (functie Invoke-Monitoring) – Controleren.

Remediatie

Gebruik PowerShell-script mfa-alle-gebruikers.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 MFA voor Alle Gebruikers (All Users) .DESCRIPTION Ensures all users have MFA enforced via Conditional Access policy. This is a fundamental security control for Microsoft 365. .NOTES Filename: mfa-alle-gebruikers.ps1 Author: Nederlandse Baseline voor Veilige Cloud CIS: Related to Identity Protection BIO: Control 11.05.02 .EXAMPLE .\mfa-alle-gebruikers.ps1 -Monitoring Check if MFA is enforced for all users .EXAMPLE .\mfa-alle-gebruikers.ps1 -Remediation Create Conditional Access policy requiring MFA for all users #> #Requires -Version 5.1 #Requires -Modules Microsoft.Graph [CmdletBinding()] param( [Parameter(Mandatory = $false)] [switch]$Monitoring, [Parameter(Mandatory = $false)] [switch]$Remediation, [switch]$Revert, [switch]$WhatIf ) $ErrorActionPreference = 'Stop' # ============================================================================ # HEADER # ============================================================================ Write-Host "`n========================================" -ForegroundColor Cyan Write-Host "MFA voor Alle Gebruikers (All Users)" -ForegroundColor Cyan Write-Host "Nederlandse Baseline voor Veilige Cloud" -ForegroundColor Cyan Write-Host "========================================`n" -ForegroundColor Cyan # ============================================================================ # FUNCTIONS # ============================================================================ function Invoke-Monitoring { <# .SYNOPSIS Checks if MFA is enforced for all users via Conditional Access #> 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 MFA voor Alle Gebruikers (All Users) .DESCRIPTION Ensures all users have MFA enforced via Conditional Access policy. This is a fundamental security control for Microsoft 365. .NOTES Filename: mfa-alle-gebruikers.ps1 Author: Nederlandse Baseline voor Veilige Cloud CIS: Related to Identity Protection BIO: Control 11.05.02 .EXAMPLE .\mfa-alle-gebruikers.ps1 -Monitoring Check if MFA is enforced for all users .EXAMPLE .\mfa-alle-gebruikers.ps1 -Remediation Create Conditional Access policy requiring MFA for all users #> #Requires -Version 5.1 #Requires -Modules Microsoft.Graph [CmdletBinding()] param( [Parameter(Mandatory=$false)] [switch]$Monitoring, [Parameter(Mandatory=$false)] [switch]$Remediation, [switch]$Revert, [switch]$WhatIf ) $ErrorActionPreference = 'Stop' # ============================================================================ # HEADER # ============================================================================ Write-Host "`n========================================" -ForegroundColor Cyan Write-Host "MFA voor Alle Gebruikers (All Users)" -ForegroundColor Cyan Write-Host "Nederlandse Baseline voor Veilige Cloud" -ForegroundColor Cyan Write-Host "========================================`n" -ForegroundColor Cyan # ============================================================================ # FUNCTIONS # ============================================================================ function Invoke-Monitoring { <# .SYNOPSIS Checks if MFA is enforced for all users via Conditional Access #> try { Write-Host "Connecting to Microsoft Graph..." -ForegroundColor Gray Connect-MgGraph -Scopes "Policy.Read.All" -ErrorAction Stop -NoWelcome Write-Host "Retrieving Conditional Access policies..." -ForegroundColor Gray $policies = Invoke-MgGraphRequest -Method GET -Uri "https://graph.microsoft.com/v1.0/identity/conditionalAccess/policies" $result = @{ isCompliant = $false mfaPolicies = 0 policyNames = @() } foreach ($policy in $policies.value) { # Check if policy is enabled if ($policy.state -ne 'enabled') { continue } # Check if policy applies to all users $includesAllUsers = $policy.conditions.users.includeUsers -contains 'All' # Check if policy requires MFA $requiresMFA = $policy.grantControls.builtInControls -contains 'mfa' if ($includesAllUsers -and $requiresMFA) { $result.mfaPolicies++ $result.policyNames += $policy.displayName $result.isCompliant = $true Write-Host " [OK] MFA POLICY FOR ALL USERS: $($policy.displayName)" -ForegroundColor Green } } Write-Host "`n MFA policies for all users: $($result.mfaPolicies)" -ForegroundColor $( if ($result.mfaPolicies -gt 0) { 'Green' } else { 'Red' } ) if ($result.isCompliant) { Write-Host "`n[OK] COMPLIANT - MFA is enforced for all users" -ForegroundColor Green exit 0 } else { Write-Host "`n[FAIL] NON-COMPLIANT - MFA not enforced for all users" -ForegroundColor Red Write-Host "Recommendation: Create Conditional Access policy requiring MFA" -ForegroundColor Yellow exit 1 } } catch { Write-Host "`n[FAIL] ERROR: $_" -ForegroundColor Red Write-Host "Error Details: $($_.Exception.Message)" -ForegroundColor Red exit 2 } } function Invoke-Remediation { <# .SYNOPSIS Creates Conditional Access policy to enforce MFA for all users #> try { Write-Host "⚠️ Creating Conditional Access policy requires admin consent" -ForegroundColor Yellow Write-Host "`nConnecting to Microsoft Graph..." -ForegroundColor Gray Connect-MgGraph -Scopes "Policy.ReadWrite.ConditionalAccess" -ErrorAction Stop -NoWelcome Write-Host "Creating MFA policy for all users..." -ForegroundColor Gray $policyBody = @{ displayName = "Require MFA for All Users - Nederlandse Baseline" state = "enabledForReportingButNotEnforced" conditions = @{ users = @{ includeUsers = @("All") excludeUsers = @() excludeGroups = @() } applications = @{ includeApplications = @("All") } clientAppTypes = @("all") } grantControls = @{ operator = "OR" builtInControls = @("mfa") } } $newPolicy = Invoke-MgGraphRequest -Method POST ` -Uri "https://graph.microsoft.com/v1.0/identity/conditionalAccess/policies" ` -Body ($policyBody | ConvertTo-Json -Depth 10) Write-Host "`n[OK] Policy created: $($newPolicy.displayName)" -ForegroundColor Green Write-Host "⚠️ Policy is in REPORT-ONLY mode for safety" -ForegroundColor Yellow Write-Host "Steps to enable:" -ForegroundColor Cyan Write-Host " 1. Review impact in Azure Portal > Conditional Access" -ForegroundColor Gray Write-Host " 2. Check sign-in logs for potential issues" -ForegroundColor Gray Write-Host " 3. Exclude emergency access accounts if needed" -ForegroundColor Gray Write-Host " 4. Change state to 'enabled' when ready" -ForegroundColor Gray exit 0 } catch { Write-Host "`n[FAIL] ERROR: $_" -ForegroundColor Red Write-Host "Error Details: $($_.Exception.Message)" -ForegroundColor Red exit 2 } } # ============================================================================ # MAIN EXECUTION # ============================================================================ try { if ($Monitoring) { Invoke-Monitoring } elseif ($Remediation) { Invoke-Remediation } else { Write-Host "Usage:" -ForegroundColor Yellow Write-Host " -Monitoring Check current compliance status" -ForegroundColor Gray Write-Host " -Remediation Create MFA policy (report-only mode)" -ForegroundColor Gray } } catch { throw } finally { Write-Host "`n========================================`n" -ForegroundColor Cyan } " throw } } try { Write-Host "Connecting to Microsoft Graph..." -ForegroundColor Gray Connect-MgGraph -Scopes "Policy.Read.All" -ErrorAction Stop -NoWelcome Write-Host "Retrieving Conditional Access policies..." -ForegroundColor Gray $policies = Invoke-MgGraphRequest -Method GET -Uri "https://graph.microsoft.com/v1.0/identity/conditionalAccess/policies" $result = @{ isCompliant = $false mfaPolicies = 0 policyNames = @() } foreach ($policy in $policies.value) { # Check if policy is enabled if ($policy.state -ne 'enabled') { continue } # Check if policy applies to all users $includesAllUsers = $policy.conditions.users.includeUsers -contains 'All' # Check if policy requires MFA $requiresMFA = $policy.grantControls.builtInControls -contains 'mfa' if ($includesAllUsers -and $requiresMFA) { $result.mfaPolicies++ $result.policyNames += $policy.displayName $result.isCompliant = $true Write-Host " [OK] MFA POLICY FOR ALL USERS: $($policy.displayName)" -ForegroundColor Green } } Write-Host "`n MFA policies for all users: $($result.mfaPolicies)" -ForegroundColor $( if ($result.mfaPolicies -gt 0) { 'Green' } else { 'Red' } ) if ($result.isCompliant) { Write-Host "`n[OK] COMPLIANT - MFA is enforced for all users" -ForegroundColor Green exit 0 } else { Write-Host "`n[FAIL] NON-COMPLIANT - MFA not enforced for all users" -ForegroundColor Red Write-Host "Recommendation: Create Conditional Access policy requiring MFA" -ForegroundColor Yellow exit 1 } } catch { Write-Host "`n[FAIL] ERROR: $_" -ForegroundColor Red Write-Host "Error Details: $($_.Exception.Message)" -ForegroundColor Red exit 2 } } function Invoke-Remediation { <# .SYNOPSIS Creates Conditional Access policy to enforce MFA for all users #> 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 MFA voor Alle Gebruikers (All Users) .DESCRIPTION Ensures all users have MFA enforced via Conditional Access policy. This is a fundamental security control for Microsoft 365. .NOTES Filename: mfa-alle-gebruikers.ps1 Author: Nederlandse Baseline voor Veilige Cloud CIS: Related to Identity Protection BIO: Control 11.05.02 .EXAMPLE .\mfa-alle-gebruikers.ps1 -Monitoring Check if MFA is enforced for all users .EXAMPLE .\mfa-alle-gebruikers.ps1 -Remediation Create Conditional Access policy requiring MFA for all users #> #Requires -Version 5.1 #Requires -Modules Microsoft.Graph [CmdletBinding()] param( [Parameter(Mandatory=$false)] [switch]$Monitoring, [Parameter(Mandatory=$false)] [switch]$Remediation, [switch]$Revert, [switch]$WhatIf ) $ErrorActionPreference = 'Stop' # ============================================================================ # HEADER # ============================================================================ Write-Host "`n========================================" -ForegroundColor Cyan Write-Host "MFA voor Alle Gebruikers (All Users)" -ForegroundColor Cyan Write-Host "Nederlandse Baseline voor Veilige Cloud" -ForegroundColor Cyan Write-Host "========================================`n" -ForegroundColor Cyan # ============================================================================ # FUNCTIONS # ============================================================================ function Invoke-Monitoring { <# .SYNOPSIS Checks if MFA is enforced for all users via Conditional Access #> try { Write-Host "Connecting to Microsoft Graph..." -ForegroundColor Gray Connect-MgGraph -Scopes "Policy.Read.All" -ErrorAction Stop -NoWelcome Write-Host "Retrieving Conditional Access policies..." -ForegroundColor Gray $policies = Invoke-MgGraphRequest -Method GET -Uri "https://graph.microsoft.com/v1.0/identity/conditionalAccess/policies" $result = @{ isCompliant = $false mfaPolicies = 0 policyNames = @() } foreach ($policy in $policies.value) { # Check if policy is enabled if ($policy.state -ne 'enabled') { continue } # Check if policy applies to all users $includesAllUsers = $policy.conditions.users.includeUsers -contains 'All' # Check if policy requires MFA $requiresMFA = $policy.grantControls.builtInControls -contains 'mfa' if ($includesAllUsers -and $requiresMFA) { $result.mfaPolicies++ $result.policyNames += $policy.displayName $result.isCompliant = $true Write-Host " [OK] MFA POLICY FOR ALL USERS: $($policy.displayName)" -ForegroundColor Green } } Write-Host "`n MFA policies for all users: $($result.mfaPolicies)" -ForegroundColor $( if ($result.mfaPolicies -gt 0) { 'Green' } else { 'Red' } ) if ($result.isCompliant) { Write-Host "`n[OK] COMPLIANT - MFA is enforced for all users" -ForegroundColor Green exit 0 } else { Write-Host "`n[FAIL] NON-COMPLIANT - MFA not enforced for all users" -ForegroundColor Red Write-Host "Recommendation: Create Conditional Access policy requiring MFA" -ForegroundColor Yellow exit 1 } } catch { Write-Host "`n[FAIL] ERROR: $_" -ForegroundColor Red Write-Host "Error Details: $($_.Exception.Message)" -ForegroundColor Red exit 2 } } function Invoke-Remediation { <# .SYNOPSIS Creates Conditional Access policy to enforce MFA for all users #> try { Write-Host "⚠️ Creating Conditional Access policy requires admin consent" -ForegroundColor Yellow Write-Host "`nConnecting to Microsoft Graph..." -ForegroundColor Gray Connect-MgGraph -Scopes "Policy.ReadWrite.ConditionalAccess" -ErrorAction Stop -NoWelcome Write-Host "Creating MFA policy for all users..." -ForegroundColor Gray $policyBody = @{ displayName = "Require MFA for All Users - Nederlandse Baseline" state = "enabledForReportingButNotEnforced" conditions = @{ users = @{ includeUsers = @("All") excludeUsers = @() excludeGroups = @() } applications = @{ includeApplications = @("All") } clientAppTypes = @("all") } grantControls = @{ operator = "OR" builtInControls = @("mfa") } } $newPolicy = Invoke-MgGraphRequest -Method POST ` -Uri "https://graph.microsoft.com/v1.0/identity/conditionalAccess/policies" ` -Body ($policyBody | ConvertTo-Json -Depth 10) Write-Host "`n[OK] Policy created: $($newPolicy.displayName)" -ForegroundColor Green Write-Host "⚠️ Policy is in REPORT-ONLY mode for safety" -ForegroundColor Yellow Write-Host "Steps to enable:" -ForegroundColor Cyan Write-Host " 1. Review impact in Azure Portal > Conditional Access" -ForegroundColor Gray Write-Host " 2. Check sign-in logs for potential issues" -ForegroundColor Gray Write-Host " 3. Exclude emergency access accounts if needed" -ForegroundColor Gray Write-Host " 4. Change state to 'enabled' when ready" -ForegroundColor Gray exit 0 } catch { Write-Host "`n[FAIL] ERROR: $_" -ForegroundColor Red Write-Host "Error Details: $($_.Exception.Message)" -ForegroundColor Red exit 2 } } # ============================================================================ # MAIN EXECUTION # ============================================================================ try { if ($Monitoring) { Invoke-Monitoring } elseif ($Remediation) { Invoke-Remediation } else { Write-Host "Usage:" -ForegroundColor Yellow Write-Host " -Monitoring Check current compliance status" -ForegroundColor Gray Write-Host " -Remediation Create MFA policy (report-only mode)" -ForegroundColor Gray } } catch { throw } finally { Write-Host "`n========================================`n" -ForegroundColor Cyan } " throw } } try { Write-Host "⚠️ Creating Conditional Access policy requires admin consent" -ForegroundColor Yellow Write-Host "`nConnecting to Microsoft Graph..." -ForegroundColor Gray Connect-MgGraph -Scopes "Policy.ReadWrite.ConditionalAccess" -ErrorAction Stop -NoWelcome Write-Host "Creating MFA policy for all users..." -ForegroundColor Gray $policyBody = @{ displayName = "Require MFA for All Users - Nederlandse Baseline" state = "enabledForReportingButNotEnforced" conditions = @{ users = @{ includeUsers = @("All") excludeUsers = @() excludeGroups = @() } applications = @{ includeApplications = @("All") } clientAppTypes = @("all") } grantControls = @{ operator = "OR" builtInControls = @("mfa") } } $newPolicy = Invoke-MgGraphRequest -Method POST ` -Uri "https://graph.microsoft.com/v1.0/identity/conditionalAccess/policies" ` -Body ($policyBody | ConvertTo-Json -Depth 10) Write-Host "`n[OK] Policy created: $($newPolicy.displayName)" -ForegroundColor Green Write-Host "⚠️ Policy is in REPORT-ONLY mode for safety" -ForegroundColor Yellow Write-Host "Steps to enable:" -ForegroundColor Cyan Write-Host " 1. Review impact in Azure Portal > Conditional Access" -ForegroundColor Gray Write-Host " 2. Check sign-in logs for potential issues" -ForegroundColor Gray Write-Host " 3. Exclude emergency access accounts if needed" -ForegroundColor Gray Write-Host " 4. Change state to 'enabled' when ready" -ForegroundColor Gray exit 0 } catch { Write-Host "`n[FAIL] ERROR: $_" -ForegroundColor Red Write-Host "Error Details: $($_.Exception.Message)" -ForegroundColor Red exit 2 } } # ============================================================================ # MAIN EXECUTION # ============================================================================ 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 MFA voor Alle Gebruikers (All Users) .DESCRIPTION Ensures all users have MFA enforced via Conditional Access policy. This is a fundamental security control for Microsoft 365. .NOTES Filename: mfa-alle-gebruikers.ps1 Author: Nederlandse Baseline voor Veilige Cloud CIS: Related to Identity Protection BIO: Control 11.05.02 .EXAMPLE .\mfa-alle-gebruikers.ps1 -Monitoring Check if MFA is enforced for all users .EXAMPLE .\mfa-alle-gebruikers.ps1 -Remediation Create Conditional Access policy requiring MFA for all users #> #Requires -Version 5.1 #Requires -Modules Microsoft.Graph [CmdletBinding()] param( [Parameter(Mandatory=$false)] [switch]$Monitoring, [Parameter(Mandatory=$false)] [switch]$Remediation, [switch]$Revert, [switch]$WhatIf ) $ErrorActionPreference = 'Stop' # ============================================================================ # HEADER # ============================================================================ Write-Host "`n========================================" -ForegroundColor Cyan Write-Host "MFA voor Alle Gebruikers (All Users)" -ForegroundColor Cyan Write-Host "Nederlandse Baseline voor Veilige Cloud" -ForegroundColor Cyan Write-Host "========================================`n" -ForegroundColor Cyan # ============================================================================ # FUNCTIONS # ============================================================================ function Invoke-Monitoring { <# .SYNOPSIS Checks if MFA is enforced for all users via Conditional Access #> try { Write-Host "Connecting to Microsoft Graph..." -ForegroundColor Gray Connect-MgGraph -Scopes "Policy.Read.All" -ErrorAction Stop -NoWelcome Write-Host "Retrieving Conditional Access policies..." -ForegroundColor Gray $policies = Invoke-MgGraphRequest -Method GET -Uri "https://graph.microsoft.com/v1.0/identity/conditionalAccess/policies" $result = @{ isCompliant = $false mfaPolicies = 0 policyNames = @() } foreach ($policy in $policies.value) { # Check if policy is enabled if ($policy.state -ne 'enabled') { continue } # Check if policy applies to all users $includesAllUsers = $policy.conditions.users.includeUsers -contains 'All' # Check if policy requires MFA $requiresMFA = $policy.grantControls.builtInControls -contains 'mfa' if ($includesAllUsers -and $requiresMFA) { $result.mfaPolicies++ $result.policyNames += $policy.displayName $result.isCompliant = $true Write-Host " [OK] MFA POLICY FOR ALL USERS: $($policy.displayName)" -ForegroundColor Green } } Write-Host "`n MFA policies for all users: $($result.mfaPolicies)" -ForegroundColor $( if ($result.mfaPolicies -gt 0) { 'Green' } else { 'Red' } ) if ($result.isCompliant) { Write-Host "`n[OK] COMPLIANT - MFA is enforced for all users" -ForegroundColor Green exit 0 } else { Write-Host "`n[FAIL] NON-COMPLIANT - MFA not enforced for all users" -ForegroundColor Red Write-Host "Recommendation: Create Conditional Access policy requiring MFA" -ForegroundColor Yellow exit 1 } } catch { Write-Host "`n[FAIL] ERROR: $_" -ForegroundColor Red Write-Host "Error Details: $($_.Exception.Message)" -ForegroundColor Red exit 2 } } function Invoke-Remediation { <# .SYNOPSIS Creates Conditional Access policy to enforce MFA for all users #> try { Write-Host "⚠️ Creating Conditional Access policy requires admin consent" -ForegroundColor Yellow Write-Host "`nConnecting to Microsoft Graph..." -ForegroundColor Gray Connect-MgGraph -Scopes "Policy.ReadWrite.ConditionalAccess" -ErrorAction Stop -NoWelcome Write-Host "Creating MFA policy for all users..." -ForegroundColor Gray $policyBody = @{ displayName = "Require MFA for All Users - Nederlandse Baseline" state = "enabledForReportingButNotEnforced" conditions = @{ users = @{ includeUsers = @("All") excludeUsers = @() excludeGroups = @() } applications = @{ includeApplications = @("All") } clientAppTypes = @("all") } grantControls = @{ operator = "OR" builtInControls = @("mfa") } } $newPolicy = Invoke-MgGraphRequest -Method POST ` -Uri "https://graph.microsoft.com/v1.0/identity/conditionalAccess/policies" ` -Body ($policyBody | ConvertTo-Json -Depth 10) Write-Host "`n[OK] Policy created: $($newPolicy.displayName)" -ForegroundColor Green Write-Host "⚠️ Policy is in REPORT-ONLY mode for safety" -ForegroundColor Yellow Write-Host "Steps to enable:" -ForegroundColor Cyan Write-Host " 1. Review impact in Azure Portal > Conditional Access" -ForegroundColor Gray Write-Host " 2. Check sign-in logs for potential issues" -ForegroundColor Gray Write-Host " 3. Exclude emergency access accounts if needed" -ForegroundColor Gray Write-Host " 4. Change state to 'enabled' when ready" -ForegroundColor Gray exit 0 } catch { Write-Host "`n[FAIL] ERROR: $_" -ForegroundColor Red Write-Host "Error Details: $($_.Exception.Message)" -ForegroundColor Red exit 2 } } # ============================================================================ # MAIN EXECUTION # ============================================================================ try { if ($Monitoring) { Invoke-Monitoring } elseif ($Remediation) { Invoke-Remediation } else { Write-Host "Usage:" -ForegroundColor Yellow Write-Host " -Monitoring Check current compliance status" -ForegroundColor Gray Write-Host " -Remediation Create MFA policy (report-only mode)" -ForegroundColor Gray } } catch { throw } finally { Write-Host "`n========================================`n" -ForegroundColor Cyan } " throw } } try { if ($Monitoring) { Invoke-Monitoring } elseif ($Remediation) { Invoke-Remediation } else { Write-Host "Usage:" -ForegroundColor Yellow Write-Host " -Monitoring Check current compliance status" -ForegroundColor Gray Write-Host " -Remediation Create MFA policy (report-only mode)" -ForegroundColor Gray } } catch { throw } finally { Write-Host "`n========================================`n" -ForegroundColor Cyan }

Risico zonder implementatie

Risico zonder implementatie
Critical: Critical - Zonder MFA: 99.9% hogere kans op account compromise via phishing/password spraying. Account takeover is datalek, BEC fraud, ransomware deployment. MFA is #1 beveiligingscontrole.

Management Samenvatting

Verplicht MFA voor alle M365 users via CA beleid. Microsoft Authenticator app preferred. 99.9% preventie van account takeover. Voldoet aan CIS 1.1.5 L1, BIO 9.04, NIS2. Rollout: 4u technical + 12u organizational (training).