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
CIS M365: Control 1.1.8 (L1) - Blokkeer legacy auth
BIO: 09.04 - Modern authentication only
ISO 27001:2022: A.9.4.2 - veilige authentication
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 controlWrite-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 enabledif ($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 = $trueWrite-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 enabledif ($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 = $trueWrite-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 controlWrite-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 enabledif ($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 = $trueWrite-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 controlWrite-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 enabledif ($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 = $trueWrite-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.