Blokkeer Legacy Authenticatie Voor Microsoft 365

💼 Management Samenvatting

Legacy authenticatieprotocollen zoals Basic Authentication vormen een kritiek beveiligingsrisico omdat ze moderne beveiligingsmechanismen zoals Multi-Factor Authentication (MFA) en voorwaardelijke toegang volledig omzeilen. Het blokkeren van deze verouderde protocollen is essentieel voor een veilige Microsoft 365-omgeving.

Aanbeveling
Implementeer
Risico zonder
Critical
Risk Score
9/10
Implementatie
10u (tech: 6u)
Van toepassing op:
M365

Verouderde authenticatieprotocollen zoals IMAP, POP3, SMTP AUTH en Basic Authentication zijn ontwikkeld in een tijd waarin moderne beveiligingseisen nog niet bestonden. Deze protocollen ondersteunen geen MFA, voorwaardelijke toegang of moderne beveiligingscontroles. Aanvallers maken hier actief misbruik van omdat deze protocollen een eenvoudige toegangsroute bieden zonder aanvullende verificatie. Onderzoek toont aan dat meer dan 99% van alle password spray-aanvallen gebruikmaakt van legacy authenticatieprotocollen. Door deze protocollen te blijven toestaan, creëert u een zwakke schakel in uw beveiligingsketen die door kwaadwillenden kan worden uitgebuit om toegang te verkrijgen en persistentie te behouden binnen uw omgeving.

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

Implementatie

Deze maatregel implementeert een Conditional Access (CA) policy die alle legacy authenticatie blokkeert voor Microsoft 365-services. De policy richt zich op alle client-applicaties die oudere protocollen gebruiken, waaronder Exchange ActiveSync-clients en andere legacy clients. Door deze toegang te blokkeren via een CA-policy, wordt ervoor gezorgd dat alle authenticatiepogingen uitsluitend via moderne authenticatiemethoden verlopen die ondersteuning bieden voor MFA en andere beveiligingscontroles. Dit betekent dat applicaties en clients die nog steeds afhankelijk zijn van legacy protocollen, geen toegang meer krijgen totdat ze zijn gemigreerd naar moderne authenticatie.

Vereisten

Een succesvolle blokkade van legacy authenticatie begint met een volledig begrip van de huidige situatie. Verzamel minimaal dertig dagen aan Entra ID-inloggegevens, exporteer de rapporten over client-apps en maak onderscheid tussen protocollen als IMAP, POP, SMTP AUTH, Exchange ActiveSync en onverwachte basisauthenticatie via PowerShell. Verrijk deze analyses met Risky Sign-in rapportages, zodat duidelijk wordt welke accounts het vaakst door password spray of credential stuffing worden geraakt en welke service accounts nog afhankelijk zijn van gedeelde wachtwoorden of hardgecodeerde referenties. Documenteer per applicatie de paden waarlangs verkeer binnenkomt (bijvoorbeeld mobiele toestellen, multifunctionals, third-party archiveringsoplossingen) en leg vast welk zakelijk proces wordt geraakt wanneer toegang plotseling wordt geblokkeerd.

Zorg vervolgens voor de juiste licenties en technische randvoorwaarden. Voorwaardelijke toegang vereist minimaal Entra ID Premium P1, maar voor organisaties met geavanceerde scenario’s is P2 wenselijk vanwege functies als Identity Protection en aangepaste waarschuwingen. Richt een dedicated testtenant of isolatiegroep in om policies veilig te valideren zonder productiegebruikers direct te beïnvloeden. Controleer of alle beheerders beschikken over moderne authenticatiemiddelen zoals FIDO2-sleutels of Windows Hello for Business en verifieer de beschikbaarheid van noodtoegangsaccounts met statische wachtwoorden die zijn opgeslagen onder dubbele controle. Zonder deze basis kan de organisatie zichzelf buitensluiten zodra legacy protocollen worden afgedwongen.

Naast technische voorwaarden is een volwassen migratieplan essentieel. Inventariseer voor elke applicatie of hardwarecomponent welke alternatieve verbinding beschikbaar is. Voor printers en scanners betekent dit vaak overstappen naar moderne SMTP-verbindingen via Exchange Online met OAuth2, of het inzetten van een relay in een beveiligd netwerksegment. Line-of-business applicaties die oude Exchange Web Services gebruiken, moeten worden geüpdatet naar ondersteuning voor moderne OAuth 2.0 flows of naar Graph API endpoints. Leg per applicatie-eigenaar vast wie verantwoordelijk is voor de wijziging, welke testcases worden uitgevoerd, wat de fallback is en welke tijdlijn realistisch is. Indien een leverancier modernisatie uitstelt, leg dit contractueel vast inclusief duidelijke einddatum waarop legacy toegang definitief wordt beëindigd.

Tot slot horen governance en communicatie bij de vereisten. Stel een communicatiestrategie op voor eindgebruikers, servicedesks en leveranciers waarin wordt uitgelegd waarom legacy authenticatie verdwijnt, hoe phishingrisico’s hierdoor dalen en welke acties worden verwacht. Train servicedeskmedewerkers in het herkennen van foutmeldingen die optreden wanneer een gebruiker toch nog met een oud protocol probeert te verbinden, zodat zij onmiddellijk kunnen uitleggen hoe de moderne methode werkt. Richt dashboards in (Power BI of Microsoft Sentinel) waarmee bestuurders dagelijks kunnen volgen hoeveel legacy pogingen nog worden gedaan, hoeveel accounts succesvol zijn gemigreerd en welke uitzonderingen nog openstaan. Alleen wanneer deze organisatorische randvoorwaarden zijn geborgd, kan de technische blokkade zonder verstoringen worden uitgerold.

Implementeeratie

De implementatie start met het ontwerpen van een Conditional Access beleidsset die specifiek gericht is op client-apps die legacy protocollen gebruiken. Gebruik in de Entra ID portal de filteroptie “Client-apps (preview)” en selecteer uitsluitend de categorieën Exchange ActiveSync, andere clients en de oudere Office-clients. Deze selectie zorgt ervoor dat moderne authenticatie zoals browser en mobiele apps buiten beschouwing blijven, terwijl alle basisauthenticatieaanroepen worden afgevangen. Koppel het beleid aan de groep “All users” inclusief service accounts, maar sluit uitsluitend de twee tot drie gecontroleerde noodtoegangsaccounts uit. Richt de policy initieel in met de modus “Report-only” zodat sign-in logs exact laten zien welke verbinding zou worden geblokkeerd zonder dat gebruikers impact ondervinden. Exporteer deze gegevens dagelijks naar een Log Analytics workspace en laat SOC-analisten de trends interpreteren.

Parallel aan de monitoringsfase wordt een gefaseerde migratie uitgevoerd. Begin met kritieke applicaties in een pilotgroep en werk samen met de eigenaren om moderne authenticatie te activeren. Voor Exchange ActiveSync op mobiele toestellen betekent dit vaak overschakelen naar de ingebouwde Outlook-app of een MAM-beheerde variant. Voor scripts of PowerShell-automatisering worden moderne modules gebruikt zoals Microsoft Graph PowerShell met certificate-based authentication of managed identities. Documenteer voor elke migratie de resultaten en testcases. Zodra een workload succesvol is overgezet, verwijder je tijdelijke uitzonderingen in de policy en zorg je dat dit in het wijzigingsbeheer wordt vastgelegd.

Wanneer de rapporten aantonen dat alleen nog geautoriseerde uitzonderingen legacy verkeer genereren, kan de policy naar de status “On” worden gezet. Gebruik change management met een duidelijk go/no-go moment, inclusief war room ondersteuning door het SOC, identity team en servicedesk. Controleer direct na activatie de real-time Sign-in logs en Microsoft Defender for Cloud Apps alerts om foutstromen snel te detecteren. Voor elke blokkade die toch nog optreedt, wordt een standaardoperatie gehanteerd: tijdelijk toevoegen aan een uitzonderingsgroep alleen als de business impact kritisch is, een werkorder aanmaken voor modernisatie met harde einddatum en wekelijks rapporteren aan de stuurgroep. Zo blijft de druk op volledige uitfasering bestaan.

Implementeer aanvullend twee ondersteunende maatregelen. Ten eerste, configureer Identity Protection met policies die aanmeldingen met “Legacy Authentication clients” automatisch als hoog risico markeren, zodat SOC-analisten onmiddellijk een gebruikersrisicoreset kunnen afdwingen. Ten tweede, automatiseer alerts in Microsoft Sentinel of Splunk die elke legacy sign-in als P1 incident registreren zolang de overgang loopt. Deze alerts bevatten de gebruikersnaam, IP, protocol en applicatie zodat het team binnen minuten contact kan opnemen met de verantwoordelijke eigenaar. Combineer dit met weekly executive reporting waarin wordt getoond hoeveel legacy pogingen nog plaatsvinden, hoeveel daarvan succesvolle blokkades waren en hoeveel uitzonderingen actief zijn. De implementatie eindigt pas wanneer deze cijfers structureel op nul staan.

Compliance en Auditing

Het blokkeren van legacy authenticatie is rechtstreeks gekoppeld aan meerdere compliance-eisen. De CIS Microsoft 365 Foundations Benchmark eist onder controle 1.1.8 dat basisauthenticatie wordt uitgeschakeld om credential spraying te voorkomen. De Baseline Informatiebeveiliging Overheid (BIO) hoofdstuk 09.04 schrijft voor dat alleen sterke authenticatieprotocollen mogen worden gebruikt en dat toegangsmechanismen periodiek worden herzien. Door legacy protocollen af te sluiten, toont de organisatie aan dat deze voorschriften concreet worden nageleefd. Leg dit vast in het beveiligingsplan en verwijs naar de architectuurkeuzes, zodat auditors exact kunnen zien hoe het besluit is geborgd in beleid, processen en technische configuraties.

ISO 27001:2022 controle A.9.4.2 (toegangscontrole voor netwerkediensten) en A.5.17 (identiteitbeheer) vereisen dat toegang tot informatiesystemen is gebaseerd op geautoriseerde, veilige methoden. Een audittrail waarin duidelijk staat dat legacy authenticatie door Conditional Access wordt geblokkeerd, bewijst dat slechts moderne, met MFA beschermde sessies mogelijk zijn. Documenteer daarom het beleid, de configuratie-screenshots, de change tickets en de testresultaten in het ISMS. Voor NIS2 Artikel 21 lid 2 sub e betreft dit onderdeel van de verplichting om meervoudige authenticatie en beveiligingsbeleid toe te passen op netwerk- en informatiesystemen die essentieel zijn voor de continuïteit van diensten in de publieke sector.

Auditors vragen doorgaans om tastbare bewijsstukken. Verzamel daarom een export van de Conditional Access policy in JSON-formaat, een PowerShell-rapport met de eigenschap “LegacyAuthBlockedState”, en een Microsoft Graph query die bevestigt dat Exchange Online basisauthenticatie is uitgeschakeld voor POP, IMAP, MAPI en RPC. Voeg daar Sentinel-dashboards aan toe die aantonen dat eventuele legacy pogingen onmiddellijk een incident genereren. Voor dienstverleners die namens de overheid Microsoft 365 beheren, hoort hier ook een verklaring bij dat leveranciers geen uitzonderingen krijgen zonder schriftelijke goedkeuring van de opdrachtgever en dat deze uitzonderingen uiterlijk binnen een afgesproken termijn verdwijnen.

Continu naleving vereist monitoring en periodieke herbeoordeling. Plan elk kwartaal een controle waarbij de export van Sign-in logs wordt geanalyseerd op het veld “ClientAppUsed” om te bevestigen dat geen legacypogingen slagen. Registreer de resultaten in het auditlogboek en koppel eventuele afwijkingen aan corrigerende maatregelen. Tijdens pentests of Red Team-oefeningen moet het team expliciet verifiëren dat pogingen via oude protocollen daadwerkelijk worden geweigerd en dat geen serviceaccount buiten de policy valt. Deze bewijzen worden minimaal zeven jaar bewaard in lijn met de archiveringsrichtlijnen, zodat toezichthouders, NCSC-auditors of interne controllers altijd kunnen beoordelen dat de maatregel consistent is uitgevoerd.

Monitoring

Gebruik PowerShell-script legacy-authentication-block.ps1 (functie Invoke-Monitoring) – Controleren.

Remediatie

Gebruik PowerShell-script legacy-authentication-block.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 Block Legacy Authentication .DESCRIPTION Blocks legacy authentication protocols in Microsoft 365 using Conditional Access. Legacy authentication doesn't support MFA and is a major security risk. .NOTES Filename: legacy-authentication-block.ps1 Author: Nederlandse Baseline voor Veilige Cloud CIS: Related to Identity Protection .EXAMPLE .\legacy-authentication-block.ps1 -Monitoring Check if legacy authentication is blocked #> #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 "Block Legacy Authentication" -ForegroundColor Cyan Write-Host "Nederlandse Baseline voor Veilige Cloud" -ForegroundColor Cyan Write-Host "========================================`n" -ForegroundColor Cyan # ============================================================================ # FUNCTIONS # ============================================================================ function Invoke-Monitoring { <# .SYNOPSIS Checks if legacy authentication is blocked 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 Block Legacy Authentication .DESCRIPTION Blocks legacy authentication protocols in Microsoft 365 using Conditional Access. Legacy authentication doesn't support MFA and is a major security risk. .NOTES Filename: legacy-authentication-block.ps1 Author: Nederlandse Baseline voor Veilige Cloud CIS: Related to Identity Protection .EXAMPLE .\legacy-authentication-block.ps1 -Monitoring Check if legacy authentication is blocked #> #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 "Block Legacy Authentication" -ForegroundColor Cyan Write-Host "Nederlandse Baseline voor Veilige Cloud" -ForegroundColor Cyan Write-Host "========================================`n" -ForegroundColor Cyan # ============================================================================ # FUNCTIONS # ============================================================================ function Invoke-Monitoring { <# .SYNOPSIS Checks if legacy authentication is blocked via Conditional Access #> try { Write-Host "Connecting to Microsoft Graph..." -ForegroundColor Gray Connect-MgGraph -Scopes "Policy.Read.All" -ErrorAction Stop -NoWelcome Write-Host "Checking Conditional Access policies..." -ForegroundColor Gray $policies = Invoke-MgGraphRequest -Method GET -Uri "https://graph.microsoft.com/v1.0/identity/conditionalAccess/policies" $result = @{ isCompliant = $false blockingPolicies = 0 policyNames = @() } foreach ($policy in $policies.value) { # Check if policy is enabled if ($policy.state -ne 'enabled') { continue } # Check if it applies to all users or a broad scope $appliesToAll = $policy.conditions.users.includeUsers -contains 'All' # Check if it blocks legacy authentication $blocksLegacyAuth = $policy.conditions.clientAppTypes -contains 'exchangeActiveSync' -or $policy.conditions.clientAppTypes -contains 'other' # Check if grant control is to block $hasBlockControl = $policy.grantControls.builtInControls -contains 'block' if ($appliesToAll -and $blocksLegacyAuth -and $hasBlockControl) { $result.blockingPolicies++ $result.policyNames += $policy.displayName $result.isCompliant = $true Write-Host " [OK] BLOCKING POLICY: $($policy.displayName)" -ForegroundColor Green } } Write-Host "`n Policies blocking legacy auth: $($result.blockingPolicies)" -ForegroundColor $(if ($result.blockingPolicies -gt 0) { 'Green' } else { 'Red' }) if ($result.isCompliant) { Write-Host "`n[OK] COMPLIANT - Legacy authentication is blocked" -ForegroundColor Green exit 0 } else { Write-Host "`n[FAIL] NON-COMPLIANT - Legacy authentication not blocked" -ForegroundColor Red Write-Host "Create a Conditional Access policy to block legacy authentication!" -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 block legacy authentication #> 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 policy to block legacy authentication..." -ForegroundColor Gray $policyBody = @{ displayName = "Block Legacy Authentication - Nederlandse Baseline" state = "enabledForReportingButNotEnforced" conditions = @{ users = @{ includeUsers = @("All") excludeUsers = @() excludeGroups = @() } applications = @{ includeApplications = @("All") } clientAppTypes = @( "exchangeActiveSync", "other" ) } grantControls = @{ operator = "OR" builtInControls = @("block") } } $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" -ForegroundColor Yellow Write-Host "Review impact before enabling!" -ForegroundColor Yellow Write-Host "`nTo enable: Change state to 'enabled' in Azure Portal" -ForegroundColor Cyan 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 "Use: -Monitoring or -Remediation" -ForegroundColor Yellow } } 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 "Checking Conditional Access policies..." -ForegroundColor Gray $policies = Invoke-MgGraphRequest -Method GET -Uri "https://graph.microsoft.com/v1.0/identity/conditionalAccess/policies" $result = @{ isCompliant = $false blockingPolicies = 0 policyNames = @() } foreach ($policy in $policies.value) { # Check if policy is enabled if ($policy.state -ne 'enabled') { continue } # Check if it applies to all users or a broad scope $appliesToAll = $policy.conditions.users.includeUsers -contains 'All' # Check if it blocks legacy authentication $blocksLegacyAuth = $policy.conditions.clientAppTypes -contains 'exchangeActiveSync' -or $policy.conditions.clientAppTypes -contains 'other' # Check if grant control is to block $hasBlockControl = $policy.grantControls.builtInControls -contains 'block' if ($appliesToAll -and $blocksLegacyAuth -and $hasBlockControl) { $result.blockingPolicies++ $result.policyNames += $policy.displayName $result.isCompliant = $true Write-Host " [OK] BLOCKING POLICY: $($policy.displayName)" -ForegroundColor Green } } Write-Host "`n Policies blocking legacy auth: $($result.blockingPolicies)" -ForegroundColor $(if ($result.blockingPolicies -gt 0) { 'Green' } else { 'Red' }) if ($result.isCompliant) { Write-Host "`n[OK] COMPLIANT - Legacy authentication is blocked" -ForegroundColor Green exit 0 } else { Write-Host "`n[FAIL] NON-COMPLIANT - Legacy authentication not blocked" -ForegroundColor Red Write-Host "Create a Conditional Access policy to block legacy authentication!" -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 block legacy authentication #> 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 Block Legacy Authentication .DESCRIPTION Blocks legacy authentication protocols in Microsoft 365 using Conditional Access. Legacy authentication doesn't support MFA and is a major security risk. .NOTES Filename: legacy-authentication-block.ps1 Author: Nederlandse Baseline voor Veilige Cloud CIS: Related to Identity Protection .EXAMPLE .\legacy-authentication-block.ps1 -Monitoring Check if legacy authentication is blocked #> #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 "Block Legacy Authentication" -ForegroundColor Cyan Write-Host "Nederlandse Baseline voor Veilige Cloud" -ForegroundColor Cyan Write-Host "========================================`n" -ForegroundColor Cyan # ============================================================================ # FUNCTIONS # ============================================================================ function Invoke-Monitoring { <# .SYNOPSIS Checks if legacy authentication is blocked via Conditional Access #> try { Write-Host "Connecting to Microsoft Graph..." -ForegroundColor Gray Connect-MgGraph -Scopes "Policy.Read.All" -ErrorAction Stop -NoWelcome Write-Host "Checking Conditional Access policies..." -ForegroundColor Gray $policies = Invoke-MgGraphRequest -Method GET -Uri "https://graph.microsoft.com/v1.0/identity/conditionalAccess/policies" $result = @{ isCompliant = $false blockingPolicies = 0 policyNames = @() } foreach ($policy in $policies.value) { # Check if policy is enabled if ($policy.state -ne 'enabled') { continue } # Check if it applies to all users or a broad scope $appliesToAll = $policy.conditions.users.includeUsers -contains 'All' # Check if it blocks legacy authentication $blocksLegacyAuth = $policy.conditions.clientAppTypes -contains 'exchangeActiveSync' -or $policy.conditions.clientAppTypes -contains 'other' # Check if grant control is to block $hasBlockControl = $policy.grantControls.builtInControls -contains 'block' if ($appliesToAll -and $blocksLegacyAuth -and $hasBlockControl) { $result.blockingPolicies++ $result.policyNames += $policy.displayName $result.isCompliant = $true Write-Host " [OK] BLOCKING POLICY: $($policy.displayName)" -ForegroundColor Green } } Write-Host "`n Policies blocking legacy auth: $($result.blockingPolicies)" -ForegroundColor $(if ($result.blockingPolicies -gt 0) { 'Green' } else { 'Red' }) if ($result.isCompliant) { Write-Host "`n[OK] COMPLIANT - Legacy authentication is blocked" -ForegroundColor Green exit 0 } else { Write-Host "`n[FAIL] NON-COMPLIANT - Legacy authentication not blocked" -ForegroundColor Red Write-Host "Create a Conditional Access policy to block legacy authentication!" -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 block legacy authentication #> 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 policy to block legacy authentication..." -ForegroundColor Gray $policyBody = @{ displayName = "Block Legacy Authentication - Nederlandse Baseline" state = "enabledForReportingButNotEnforced" conditions = @{ users = @{ includeUsers = @("All") excludeUsers = @() excludeGroups = @() } applications = @{ includeApplications = @("All") } clientAppTypes = @( "exchangeActiveSync", "other" ) } grantControls = @{ operator = "OR" builtInControls = @("block") } } $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" -ForegroundColor Yellow Write-Host "Review impact before enabling!" -ForegroundColor Yellow Write-Host "`nTo enable: Change state to 'enabled' in Azure Portal" -ForegroundColor Cyan 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 "Use: -Monitoring or -Remediation" -ForegroundColor Yellow } } 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 policy to block legacy authentication..." -ForegroundColor Gray $policyBody = @{ displayName = "Block Legacy Authentication - Nederlandse Baseline" state = "enabledForReportingButNotEnforced" conditions = @{ users = @{ includeUsers = @("All") excludeUsers = @() excludeGroups = @() } applications = @{ includeApplications = @("All") } clientAppTypes = @( "exchangeActiveSync", "other" ) } grantControls = @{ operator = "OR" builtInControls = @("block") } } $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" -ForegroundColor Yellow Write-Host "Review impact before enabling!" -ForegroundColor Yellow Write-Host "`nTo enable: Change state to 'enabled' in Azure Portal" -ForegroundColor Cyan 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 Block Legacy Authentication .DESCRIPTION Blocks legacy authentication protocols in Microsoft 365 using Conditional Access. Legacy authentication doesn't support MFA and is a major security risk. .NOTES Filename: legacy-authentication-block.ps1 Author: Nederlandse Baseline voor Veilige Cloud CIS: Related to Identity Protection .EXAMPLE .\legacy-authentication-block.ps1 -Monitoring Check if legacy authentication is blocked #> #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 "Block Legacy Authentication" -ForegroundColor Cyan Write-Host "Nederlandse Baseline voor Veilige Cloud" -ForegroundColor Cyan Write-Host "========================================`n" -ForegroundColor Cyan # ============================================================================ # FUNCTIONS # ============================================================================ function Invoke-Monitoring { <# .SYNOPSIS Checks if legacy authentication is blocked via Conditional Access #> try { Write-Host "Connecting to Microsoft Graph..." -ForegroundColor Gray Connect-MgGraph -Scopes "Policy.Read.All" -ErrorAction Stop -NoWelcome Write-Host "Checking Conditional Access policies..." -ForegroundColor Gray $policies = Invoke-MgGraphRequest -Method GET -Uri "https://graph.microsoft.com/v1.0/identity/conditionalAccess/policies" $result = @{ isCompliant = $false blockingPolicies = 0 policyNames = @() } foreach ($policy in $policies.value) { # Check if policy is enabled if ($policy.state -ne 'enabled') { continue } # Check if it applies to all users or a broad scope $appliesToAll = $policy.conditions.users.includeUsers -contains 'All' # Check if it blocks legacy authentication $blocksLegacyAuth = $policy.conditions.clientAppTypes -contains 'exchangeActiveSync' -or $policy.conditions.clientAppTypes -contains 'other' # Check if grant control is to block $hasBlockControl = $policy.grantControls.builtInControls -contains 'block' if ($appliesToAll -and $blocksLegacyAuth -and $hasBlockControl) { $result.blockingPolicies++ $result.policyNames += $policy.displayName $result.isCompliant = $true Write-Host " [OK] BLOCKING POLICY: $($policy.displayName)" -ForegroundColor Green } } Write-Host "`n Policies blocking legacy auth: $($result.blockingPolicies)" -ForegroundColor $(if ($result.blockingPolicies -gt 0) { 'Green' } else { 'Red' }) if ($result.isCompliant) { Write-Host "`n[OK] COMPLIANT - Legacy authentication is blocked" -ForegroundColor Green exit 0 } else { Write-Host "`n[FAIL] NON-COMPLIANT - Legacy authentication not blocked" -ForegroundColor Red Write-Host "Create a Conditional Access policy to block legacy authentication!" -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 block legacy authentication #> 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 policy to block legacy authentication..." -ForegroundColor Gray $policyBody = @{ displayName = "Block Legacy Authentication - Nederlandse Baseline" state = "enabledForReportingButNotEnforced" conditions = @{ users = @{ includeUsers = @("All") excludeUsers = @() excludeGroups = @() } applications = @{ includeApplications = @("All") } clientAppTypes = @( "exchangeActiveSync", "other" ) } grantControls = @{ operator = "OR" builtInControls = @("block") } } $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" -ForegroundColor Yellow Write-Host "Review impact before enabling!" -ForegroundColor Yellow Write-Host "`nTo enable: Change state to 'enabled' in Azure Portal" -ForegroundColor Cyan 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 "Use: -Monitoring or -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 or -Remediation" -ForegroundColor Yellow } } catch { throw } finally { Write-Host "`n========================================`n" -ForegroundColor Cyan }

Risico zonder implementatie

Risico zonder implementatie
Critical: Critical - Legacy auth bypasses MFA. Attackers gebruiken voor persistence. 99%+ of password spray attacks gebruiken legacy protocols.

Management Samenvatting

Blokkeer legacy authentication via CA policy. Migrate apps to Modern Auth first. Voldoet aan CIS 1.1.8 L1, BIO 9.04. Setup: 6u.