> For the complete documentation index, see [llms.txt](https://docs.stoik.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.stoik.io/cyber-best-practices/nl/handleidingen-voor-het-verhelpen-van-kwetsbaarheden/ad-scan-vulnerability-remediation-guide.md).

# Handleiding voor herstel van Active Directory Scan

Elke kwetsbaarheidssectie bevat:

* **Wat het betekent:** een uitleg van het risico in gewone taal
* **Wat de scan controleert:** de specifieke voorwaarden die het alarm activeren
* **Waarom het alarm kan aanhouden:** veelvoorkomende gedeeltelijke oplossingen die niet voldoende zijn
* **Hoe te diagnosticeren:** PowerShell-opdrachten om getroffen objecten te identificeren
* **Hoe op te lossen:** stapsgewijze herstelactie

> **Vereisten:** Voor alle PowerShell-opdrachten is de `ActiveDirectory` module vereist en ze moeten worden uitgevoerd als Domain Admin op een Domain Controller.
>
> ```powershell
> Import-Module ActiveDirectory
> ```

## A-LAPS-Not-Installed

#### Wat het betekent

Elke Windows-computer heeft een **ingebouwd lokaal Administrator-account**. Standaard heeft dit account vaak hetzelfde wachtwoord op alle machines, of een wachtwoord dat nooit verandert. Als een aanvaller één machine compromitteert, kunnen ze dat wachtwoord hergebruiken om toegang te krijgen tot alle andere.

**LAPS** (Local Administrator Password Solution) lost dit op door automatisch op elke computer een uniek, willekeurig gegenereerd wachtwoord in te stellen en dit veilig op te slaan in Active Directory. Alleen geautoriseerde beheerders kunnen het ophalen.

#### Wat de scan controleert

De AD-scan zoekt naar bewijs dat LAPS is ingesteld in uw Active Directory. Specifiek controleert hij of de benodigde LAPS-gegevensvelden aanwezig zijn in uw AD-configuratie. Als dat niet zo is, betekent dit dat LAPS nooit is geïnstalleerd.

#### Waarom het alarm kan aanhouden

* **Alleen via Intune beheerde LAPS:** Als u Microsoft Intune gebruikt om LAPS-wachtwoorden in de cloud te beheren (zonder de on-premises AD te configureren), kan de AD-scan dat niet detecteren. De scan kijkt alleen naar uw lokale Active Directory.
* **LAPS was gedeeltelijk geïnstalleerd:** De LAPS-installatie kan zijn gestart maar niet voltooid.

#### Hoe te diagnosticeren

```powershell
# Controleer of LAPS is ingesteld in uw Active Directory
Get-ADObject -SearchBase (Get-ADRootDSE).SchemaNamingContext `
  -Filter "name -like 'ms-Mcs-AdmPwd' -or name -eq 'ms-LAPS-Password'" |
  Select-Object Name, whenCreated
```

Als dit geen resultaten oplevert, is LAPS niet geïnstalleerd.

#### Hoe je het oplost

**Voor Windows Server 2019 en later (aanbevolen):** Moderne LAPS is ingebouwd in Windows. Schakel het in via Groepsbeleid:

1. Open `gpmc.msc` (Groepsbeleidbeheer)
2. Bewerk of maak een GPO die is gekoppeld aan uw computer-OU's
3. Navigeer naar: `Computerconfiguratie > Beheersjablonen > Systeem > LAPS`
4. Configureer de LAPS-instellingen (inschakelen, wachtwoordcomplexiteit instellen, enz.)

**Voor oudere omgevingen:** Download Legacy LAPS van Microsoft en voer de schema-uitbreiding uit:

```powershell
Update-LapsADSchema
```

> **Opmerking:** Als u lokale beheerderswachtwoorden beheert via een ander hulpmiddel (CyberArk, alleen-Intune LAPS, enz.), neem contact op met Stoïk-support om dit als een geaccepteerde uitzondering te documenteren.

## A-LAPS-Joined-Computers

#### Wat het betekent

Wanneer iemand een computer toevoegt ("joint") aan het Active Directory-domein, wordt die persoon de **maker** van het computerobject in AD. Standaard krijgt de maker speciale rechten op dat object.

Het probleem is: wanneer LAPS is geïnstalleerd, wordt het lokale beheerderswachtwoord opgeslagen op datzelfde computerobject. Als de maker nog steeds de juiste rechten heeft, kan die **het LAPS-wachtwoord lezen**, zelfs als die geen beheerder is. Dit betekent dat een gewone gebruiker die ooit een pc aan het domein heeft gekoppeld, het lokale beheerderswachtwoord van die machine kan ophalen.

#### Wat de scan controleert

Voor elke ingeschakelde computer waarop LAPS is uitgerold, controleert de AD-scan **twee dingen**:

1. **Is de persoon die de computer heeft gekoppeld nog steeds de "eigenaar" van het computerobject?** Eigenaars kunnen zichzelf elke machtiging geven, inclusief het lezen van het LAPS-wachtwoord.
2. **Heeft de maker nog steeds expliciete machtigingen** op het computerobject, zoals `Alle uitgebreide rechten` (waarmee het LAPS-wachtwoord kan worden gelezen), `WriteDacl` (waarmee machtigingen kunnen worden gewijzigd), `WriteOwner` (waarmee eigenaarschap kan worden teruggenomen), of `GenericWrite`?

Het alarm wordt geactiveerd als **een van beide** voorwaarden waar is.

#### Waarom het alarm kan aanhouden

Dit is de meest voorkomende bron van verwarring: **het wijzigen van de eigenaar is slechts de helft van de oplossing.**

Veel beheerders wijzigen de eigenaar naar "Domain Admins" en verwachten dat het alarm verdwijnt. Maar de AD-scan controleert ook op overgebleven machtigingen (ACE's, of Access Control Entries) die aan de oorspronkelijke maker zijn verleend. Deze machtigingen blijven bestaan, zelfs nadat de eigenaar is gewijzigd, en moeten apart worden verwijderd.

#### Hoe te diagnosticeren

```powershell
# Lijst computers op waar de maker nog risicovolle machtigingen heeft
Get-ADComputer -Filter "Enabled -eq `$true" `
  -Properties "mS-DS-CreatorSID", "nTSecurityDescriptor" |
  Where-Object { $_."mS-DS-CreatorSID" -ne $null } |
  ForEach-Object {
    $comp = $_
    $acl = $comp.nTSecurityDescriptor
    $creatorSid = $comp."mS-DS-CreatorSID"
    $owner = $acl.GetOwner([System.Security.Principal.SecurityIdentifier])

    $isOwner = ($owner.Value -eq $creatorSid.Value)

    $riskyAces = $acl.Access | Where-Object {
      -not $_.IsInherited -and
      $_.IdentityReference.Value -eq $creatorSid.Value -and
      ($_.ActiveDirectoryRights -match 'WriteDacl|WriteOwner|GenericWrite|ExtendedRight')
    }

    if ($isOwner -or $riskyAces) {
      [PSCustomObject]@{
        Computer       = $comp.Name
        CreatorIsOwner = $isOwner
        RiskyRights    = ($riskyAces | ForEach-Object { $_.ActiveDirectoryRights }) -join ", "
      }
    }
  } | Format-Table -AutoSize
```

#### Hoe je het oplost

U moet **beide** van deze acties voor elke getroffen computer uitvoeren:

1. **Wijzig de eigenaar** naar Domain Admins
2. **Verwijder de expliciete machtigingen van de maker**

Het volgende script doet beide automatisch:

```powershell
#Requires -Modules ActiveDirectory

$affectedComputers = Get-ADComputer -Filter "Enabled -eq `$true" `
  -Properties "mS-DS-CreatorSID", "nTSecurityDescriptor" |
  Where-Object { $_."mS-DS-CreatorSID" -ne $null }

foreach ($comp in $affectedComputers) {
  $path = "AD:$($comp.DistinguishedName)"
  $acl = Get-Acl -Path $path
  $creatorSid = $comp."mS-DS-CreatorSID"
  $modified = $false

  # Stap 1: wijzig de eigenaar naar Domain Admins
  $domainAdmins = New-Object System.Security.Principal.NTAccount("$env:USERDOMAIN", "Domain Admins")
  $acl.SetOwner($domainAdmins)
  $modified = $true

  # Stap 2: verwijder expliciete machtigingen die aan de maker zijn verleend (en verweesde SID's)
  $toRemove = @($acl.Access | Where-Object {
    -not $_.IsInherited -and
    ($_.IdentityReference.Value -eq $creatorSid.Value -or
     $_.IdentityReference.Value -match '^S-1-5-21-')  # Verweesde SID's (verwijderde accounts)
  })

  foreach ($ace in $toRemove) {
    $acl.RemoveAccessRuleSpecific($ace)
    Write-Host "$($comp.Name): Removed [$($ace.ActiveDirectoryRights)] for $($ace.IdentityReference)"
  }

  if ($modified) {
    Set-Acl -Path $path -AclObject $acl
    Write-Host "$($comp.Name): Fixed" -ForegroundColor Green
  }
}
```

> **Tip:** Voer eerst de diagnoseopdracht uit om de lijst met getroffen computers te bekijken voordat u de oplossing toepast.

## A-NoServicePolicy

#### Wat het betekent

**Service-accounts** zijn accounts die door applicaties en services worden gebruikt (bijv. SQL Server, back-upagents) om zich te authenticeren in Active Directory. In tegenstelling tot gewone gebruikersaccounts zijn service-accounts waardevolle doelwitten: ze hebben vaak verhoogde machtigingen en hun wachtwoorden worden zelden gewijzigd.

Een **Fijnmazig wachtwoordbeleid (PSO)** is een speciale wachtwoordregel die u kunt toepassen op specifieke groepen accounts. De AD-scan verwacht dat uw service-accounts worden gedekt door een PSO die wachtwoorden van ten minste **20 tekens**vereist, waardoor ze veel moeilijker te kraken zijn.

#### Wat de scan controleert

De AD-scan zoekt naar ten minste één wachtwoordbeleid (GPO of PSO) dat een minimale wachtwoordlengte afdwingt van **20 tekens of meer**.

#### Waarom het alarm kan aanhouden

1. **Het scanaccount heeft geen machtiging om de PSO te lezen.** Wachtwoordbeleiden worden opgeslagen in een beschermd deel van AD dat standaard alleen door Domain Admins kan worden gelezen. Als de scan wordt uitgevoerd met een account met minder rechten, kan het de PSO simpelweg niet zien, ook al bestaat deze.
2. **De PSO bestaat, maar de minimale lengte is lager dan 20** (bijv. 12 of 15 tekens).
3. **De PSO bestaat, maar is niet toegewezen aan een groep of gebruiker.**

#### Hoe te diagnosticeren

```powershell
# Lijst alle fijnmazige wachtwoordbeleidsregels en hun instellingen
Get-ADFineGrainedPasswordPolicy -Filter * |
  Select-Object Name, MinPasswordLength, @{N="AppliedTo"; E={$_.AppliesTo -join ", "}}, Precedence
```

Als dit niets teruggeeft, bestaat er geen PSO of heeft het account dat de opdracht uitvoert onvoldoende rechten om deze te zien. Probeer het uit te voeren met een Domain Admin-account.

#### Hoe je het oplost

**Als de PSO bestaat, maar de scan deze niet kan zien:** Voer de AD-scan uit met een Domain Admin-account.

**Als er geen PSO bestaat:** Maak er een aan en wijs deze toe aan uw service-accounts:

```powershell
# Maak een wachtwoordbeleid voor service-accounts
New-ADFineGrainedPasswordPolicy -Name "Service Accounts - Strong Password" `
  -Precedence 10 `
  -MinPasswordLength 20 `
  -MaxPasswordAge "90.00:00:00" `
  -MinPasswordAge "1.00:00:00" `
  -PasswordHistoryCount 24 `
  -ComplexityEnabled $true `
  -ReversibleEncryptionEnabled $false `
  -LockoutDuration "00:30:00" `
  -LockoutObservationWindow "00:30:00" `
  -LockoutThreshold 5

# Wijs het toe aan een beveiligingsgroep met uw service-accounts
Add-ADFineGrainedPasswordPolicySubject `
  -Identity "Service Accounts - Strong Password" `
  -Subjects "SG_ServiceAccounts"
```

> **Opmerking:** Het aanmaken van een PSO dwingt niet onmiddellijk wachtwoordwijzigingen af. Bestaande wachtwoorden blijven werken totdat ze verlopen of handmatig worden gereset. Vanaf dat moment geldt de nieuwe minimale lengte van 20 tekens.

## A-AuditDC

#### Wat het betekent

**Auditbeleid** bepaalt welke gebeurtenissen worden vastgelegd op uw Domain Controllers. Zonder de juiste auditing kunnen aanvallen zoals diefstal van inloggegevens, ongeautoriseerde groepswijzigingen of misbruik van replicatie (DCSync) plaatsvinden zonder een spoor in de logs achter te laten.

De AD-scan controleert of uw Domain Controllers zijn geconfigureerd om de belangrijkste beveiligingsgebeurtenissen te loggen.

#### Wat de scan controleert

De scan zoekt naar **13 specifieke audit-subcategorieën** die via Groepsbeleid op alle Domain Controllers moeten zijn ingeschakeld:

| Categorie                         | Wat het logt                                                   |
| --------------------------------- | -------------------------------------------------------------- |
| Kerberos-verificatiedienst        | Aanmeldpogingen via Kerberos                                   |
| Kerberos-servicetickethandelingen | Aanvragen van servicetickets (detecteert Kerberoasting)        |
| Beheer van computeraccounts       | Computerkoppelingen/wijzigingen in AD                          |
| Beheer van beveiligingsgroepen    | Wijzigingen in groepslidmaatschap                              |
| Beheer van gebruikersaccounts     | Aanmaken, verwijderen en wachtwoordresets van gebruikers       |
| DPAPI-activiteit                  | Gebruik van de Data Protection API (toegang tot inloggegevens) |
| Procesaanmaak                     | Nieuwe processen gestart (detecteert kwaadaardige tools)       |
| Aanmelden / Afmelden              | Interactieve en externe aanmeldingen                           |
| Speciale aanmelding               | Aanmeldingen met verhoogde privileges                          |
| Wijziging van authenticatiebeleid | Wijzigingen in authenticatie-instellingen                      |
| Gebruik van gevoelige privileges  | Gebruik van gevoelige machtigingen                             |
| Beveiligingssysteemuitbreiding    | Wijzigingen in de beveiligingssubsystemen                      |

#### Waarom het alarm kan aanhouden

1. **Instellingen toegepast via `auditpol` rechtstreeks op de DC** worden niet gedetecteerd. De AD-scan leest Groepsbeleid-bestanden, niet de lokale DC-configuratie. U moet een GPO gebruiken.
2. **Conflicterende GPO's:** Eén GPO schakelt de instelling in, maar een andere GPO met hogere prioriteit schakelt deze uit.
3. **GPO niet gekoppeld aan de OU Domain Controllers:** De GPO bestaat, maar is gekoppeld aan een andere OU.

#### Hoe te diagnosticeren

```powershell
# Controleer het effectieve auditbeleid op een Domain Controller
auditpol /get /category:*
```

Als de lokale instellingen correct lijken maar het alarm blijft bestaan, controleer dan of de instellingen uit een GPO komen (en niet uit een lokale overschrijving):

```powershell
# Controleer welke GPO's gekoppeld zijn aan de OU Domain Controllers
Get-GPInheritance -Target "OU=Domain Controllers,$($(Get-ADDomain).DistinguishedName)"
```

#### Hoe je het oplost

1. Open `gpmc.msc` (Groepsbeleidsbeheerconsole)
2. Maak of bewerk een GPO die gekoppeld is aan `OU=Domain Controllers`
3. Navigeer naar: `Computerconfiguratie > Beleid > Windows-instellingen > Beveiligingsinstellingen > Geavanceerde auditbeleidsconfiguratie > Auditbeleid`
4. Inschakelen **Succes en mislukking** voor alle hierboven vermelde subcategorieën
5. Voer `gpupdate /force` uit op alle Domain Controllers

Controleer de oplossing:

```powershell
auditpol /get /category:"Account Logon"
auditpol /get /category:"Account Management"
auditpol /get /category:"Logon/Logoff"
```

## A-BadSuccessor

#### Wat het betekent

Windows Server 2025 introduceerde een nieuw type service-account genaamd **dMSA** (Delegated Managed Service Account). Er werd een beveiligingslek ontdekt waarbij een gewone gebruiker met bepaalde machtigingen op een Active Directory-map (een Organizational Unit, of OU) een dMSA kon aanmaken en deze kon gebruiken om volledige beheerdersrechten op het domein te verkrijgen.

Deze aanval is alleen mogelijk wanneer:

* U ten minste één **Windows Server 2025** Domain Controller
* Een **KDS Root Key** bestaat (vereist voor beheerde service-accounts)
* Een niet-beheerder heeft het recht om objecten aan te maken in een OU

#### Wat de scan controleert

De AD-scan zoekt naar niet-geprivilegieerde gebruikers of groepen die machtigingen hebben om dMSA-objecten aan te maken of te beheren in een willekeurige OU, zoals `CreateChild`, `GenericAll`, `WriteDacl`, of `WriteOwner`.

#### Waarom het alarm kan aanhouden

* De oplossing moet worden toegepast op **elke** getroffen OU, niet slechts één.
* Machtigingen die van bovenliggende OU's zijn geërfd, gelden nog steeds voor onderliggende OU's.
* Aangepaste beheerdersgroepen worden mogelijk niet als "geprivilegieerd" herkend door de scan.

#### Hoe te diagnosticeren

```powershell
# Controleer de vereisten
Get-KdsRootKey  # KDS Root Key moet bestaan voordat de aanval mogelijk is

Get-ADDomainController -Filter * |
  Where-Object { $_.OperatingSystem -like "*2025*" } |
  Select-Object Name, OperatingSystem  # Minstens één Win2025-DC

# Zoek OU's met risicovolle delegaties
Get-ADOrganizationalUnit -Filter * -Properties nTSecurityDescriptor |
  ForEach-Object {
    $ou = $_
    $ou.nTSecurityDescriptor.Access |
      Where-Object {
        -not $_.IsInherited -and
        $_.ActiveDirectoryRights -match 'GenericAll|CreateChild|WriteDacl|WriteOwner'
      } | ForEach-Object {
        [PSCustomObject]@{
          OU        = $ou.Name
          Principal = $_.IdentityReference
          Rights    = $_.ActiveDirectoryRights
        }
      }
  } | Format-Table -AutoSize
```

#### Hoe je het oplost

Verwijder voor elke gemarkeerde OU de risicovolle machtigingen van niet-beheerders:

```powershell
$ouDN = "OU=Servers,DC=yourdomain,DC=com"  # Vervang door uw OU
$path = "AD:$ouDN"
$acl = Get-Acl -Path $path

# Verwijder risicovolle rechten voor een specifieke groep
$identity = New-Object System.Security.Principal.NTAccount("YOURDOMAIN", "HelpDeskTeam")
$toRemove = $acl.Access | Where-Object {
  $_.IdentityReference -eq $identity -and
  $_.ActiveDirectoryRights -match 'CreateChild|GenericAll'
}

foreach ($ace in $toRemove) {
  $acl.RemoveAccessRuleSpecific($ace)
}
Set-Acl -Path $path -AclObject $acl
```

## A-AdminSDHolder

#### Wat het betekent

Wanneer een gebruiker wordt toegevoegd aan een geprivilegieerde groep in Active Directory (zoals Domain Admins), markeert het systeem hun account automatisch met een vlag genaamd `adminCount = 1`. Deze vlag maakt deel uit van een ingebouwd beschermingsmechanisme.

Het probleem is: **wanneer u die gebruiker uit de beheerdersgroep verwijdert, wordt de vlag NIET automatisch verwijderd.** Die blijft voor altijd staan, tenzij u deze expliciet verwijdert.

De AD-scan markeert accounts die deze achtergebleven `adminCount` markering hebben, maar geen echte beheerders meer zijn. Dit kan wijzen op:

* Een gebruiker die tijdelijk beheerder is gemaakt en waarvan de opschoning onvolledig was
* Een mogelijk beveiligingsrisico: deze accounts kunnen nog steeds verhoogde machtigingen hebben in bepaalde gebieden

#### Wat de scan controleert

De scan vindt ingeschakelde gebruikersaccounts waarbij `adminCount = 1` maar het account momenteel geen lid is van een geprivilegieerde groep.

#### Hoe te diagnosticeren

```powershell
# Maak een lijst van alle huidige geprivilegieerde gebruikers
$privilegedMembers = @()
@("Domain Admins", "Enterprise Admins", "Schema Admins", "Administrators",
  "Account Operators", "Server Operators", "Backup Operators", "Print Operators"
) | ForEach-Object {
  try { $privilegedMembers += (Get-ADGroupMember $_ -Recursive).DistinguishedName } catch {}
}

# Zoek accounts met de achtergebleven adminCount-vlag
Get-ADUser -LDAPFilter "(&(admincount=1)(!(userAccountControl:1.2.840.113556.1.4.803:=2)))" `
  -Properties adminCount |
  Where-Object { $_.DistinguishedName -notin $privilegedMembers } |
  Select-Object SamAccountName, Name
```

#### Hoe je het oplost

Nadat u hebt bevestigd dat deze accounts geen beheerders meer hoeven te zijn, verwijdert u de vlag:

```powershell
# Verwijder adminCount voor één gebruiker
Set-ADUser -Identity "username" -Clear adminCount

# Of verwijder het in één keer voor alle niet-geprivilegieerde gebruikers
Get-ADUser -LDAPFilter "(&(admincount=1)(!(userAccountControl:1.2.840.113556.1.4.803:=2)))" |
  Where-Object { $_.DistinguishedName -notin $privilegedMembers } |
  ForEach-Object {
    Set-ADUser -Identity $_ -Clear adminCount
    Write-Host "adminCount verwijderd voor $($_.SamAccountName)"
  }
```

## P-Kerberoasting

#### Wat het betekent

In Active Directory zijn sommige accounts geregistreerd om services uit te voeren zoals een SQL Server of een webapplicatie. Deze accounts hebben een **Service Principal Name (SPN)**, wat in wezen een label is dat zegt: "dit account draait een netwerkservice."

Het beveiligingsrisico is: **elke geverifieerde gebruiker** in het domein kan een Kerberos-ticket aanvragen voor elk account met een SPN. Dat ticket is versleuteld met het wachtwoord van het account, en de aanvaller kan het vervolgens offline proberen te kraken, zonder een alarm te activeren.

Dit heet een **Kerberoasting** aanval. Het is vooral gevaarlijk wanneer het account met de SPN ook een **Domain Admin**is, omdat het kraken van dat wachtwoord volledige controle over het domein betekent.

#### Wat de scan controleert

De AD Scan markeert accounts die aan **alle drie** de voorwaarden voldoen:

1. Het account is lid van een **bevoorrechte groep** (Domain Admins, Enterprise Admins, enz.)
2. Het account heeft een **Service Principal Name (SPN)**
3. Het wachtwoord van het account **is al meer dan 40 dagen niet gewijzigd** (waardoor aanvallers meer tijd hebben om het te kraken)

#### Waarom het alarm kan aanhouden

Je moet **alle drie** voorwaarden aanpakken. Veelvoorkomende onvolledige oplossingen:

* **Wachtwoord gewijzigd maar SPN behouden:** De waarschuwing verdwijnt tijdelijk, maar keert na 40 dagen terug.
* **SPN verwijderd maar het account zit nog steeds in Domain Admins:** De waarschuwing verdwijnt, maar het onderliggende risico blijft bestaan.

#### Hoe te diagnosticeren

```powershell
$privilegedGroups = @("Domain Admins", "Enterprise Admins", "Schema Admins", "Administrators")
$threshold = (Get-Date).AddDays(-40)

foreach ($group in $privilegedGroups) {
  Get-ADGroupMember -Identity $group -Recursive |
    Where-Object { $_.objectClass -eq "user" } |
    ForEach-Object { Get-ADUser $_ -Properties ServicePrincipalName, PasswordLastSet } |
    Where-Object { $_.ServicePrincipalName.Count -gt 0 -and $_.PasswordLastSet -lt $threshold } |
    Select-Object SamAccountName,
      @{N="PasswordLeeftijd (dagen)"; E={[math]::Round(((Get-Date) - $_.PasswordLastSet).TotalDays)}},
      @{N="SPN's"; E={$_.ServicePrincipalName -join "; "}}
}
```

#### Hoe je het oplost

**Beste optie: verwijder het account uit bevoorrechte groepen.** Serviceaccounts hoeven zelden Domain Admins te zijn. Maak een apart, niet-bevoorrecht account aan met alleen de rechten die de service werkelijk nodig heeft:

```powershell
Remove-ADGroupMember -Identity "Domain Admins" -Members "svc_account" -Confirm:$false
```

**Als je het niet uit de admin-groep kunt verwijderen:** Stel in ieder geval het wachtwoord regelmatig opnieuw in (elke 30 dagen of minder):

```powershell
Set-ADAccountPassword -Identity "svc_account" `
  -NewPassword (ConvertTo-SecureString "YourNewStr0ngP@ssw0rd!" -AsPlainText -Force) -Reset
```

**Beste langetermijnoplossing:** Converteer naar een **Group Managed Service Account (gMSA)**, dat het wachtwoord automatisch elke 30 dagen roteert:

```powershell
New-ADServiceAccount -Name "gMSA_SQLService" `
  -DNSHostName "gmsa_sqlservice.yourdomain.com" `
  -PrincipalsAllowedToRetrieveManagedPassword "SQLServersGroup"
```

## P-AdminLogin

#### Wat het betekent

Elk Active Directory-domein heeft een **ingebouwd Administrator-account** dat automatisch wordt aangemaakt wanneer het domein wordt ingesteld. Dit account heeft volledige controle over het hele domein en kan niet worden uitgesloten van vergrendeling.

Vanwege zijn macht en voorspelbaarheid (aanvallers weten dat het altijd bestaat) moet het alleen worden gebruikt voor **noodsituaties**, zoals herstel na een ramp. Voor dagelijkse administratie moeten persoonlijke admin-accounts worden gebruikt (bijv. `adm_john`) zodat acties aan individuen kunnen worden toegewezen.

#### Wat de scan controleert

De AD Scan controleert of het ingebouwde Administrator-account zich de afgelopen **35 dagen**heeft aangemeld bij een Domain Controller. Als dat zo is, wordt de waarschuwing geactiveerd, wat aangeeft dat het account voor routinetaken wordt gebruikt in plaats van voor noodgevallen te worden bewaard.

#### Waarom het alarm kan aanhouden

* **Het hernoemen van het account helpt niet.** De scan identificeert de ingebouwde Administrator aan de hand van zijn interne identificatie (RID-500), niet aan de hand van zijn naam.
* **Het wijzigen van het wachtwoord helpt niet.** De scan controleert op aanmeldactiviteit, niet op de leeftijd van het wachtwoord.
* **Geautomatiseerde scripts of geplande taken** die draaien als de ingebouwde Administrator blijven de waarschuwing activeren.
* **Je hoeft alleen maar te wachten.** Nadat je het account niet meer gebruikt, verdwijnt de waarschuwing automatisch na 35 dagen.

#### Hoe te diagnosticeren

```powershell
# Controleer wanneer de ingebouwde Administrator zich voor het laatst heeft aangemeld op elke DC
$domainSID = (Get-ADDomain).DomainSID
$adminSID = "$domainSID-500"

Get-ADDomainController -Filter * | ForEach-Object {
  $dc = $_
  $admin = Get-ADUser -Identity $adminSID -Server $dc.HostName -Properties LastLogon
  $lastLogon = [DateTime]::FromFileTime($admin.LastLogon)
  $daysAgo = [math]::Round(((Get-Date) - $lastLogon).TotalDays, 1)

  [PSCustomObject]@{
    DC        = $dc.HostName
    LastLogon = $lastLogon
    DaysAgo   = $daysAgo
    Status    = if ($daysAgo -le 35) { "ALERT - Recent gebruikt" } else { "OK" }
  }
} | Format-Table -AutoSize
```

Controleer ook op geplande taken die mogelijk de ingebouwde Administrator gebruiken:

```powershell
Get-ADDomainController -Filter * | ForEach-Object {
  Invoke-Command -ComputerName $_.HostName -ScriptBlock {
    Get-ScheduledTask | Where-Object {
      $_.Principal.UserId -match "Administrator"
    } | Select-Object TaskName, @{N="RunAs"; E={$_.Principal.UserId}}
  }
}
```

#### Hoe je het oplost

1. **Maak persoonlijke admin-accounts aan** voor elke beheerder (bijv. `adm_john`, `adm_jane`)
2. **Werk alle geplande taken bij** om een apart serviceaccount te gebruiken in plaats van de ingebouwde Administrator
3. **Log niet langer in** met de ingebouwde Administrator voor routinetaken
4. De waarschuwing wordt automatisch verwijderd **35 dagen** na de laatste aanmelding

## P-AdminNum

#### Wat het betekent

Hoe meer accounts met beheerdersrechten er in je domein zijn, hoe groter het aanvalsoppervlak. Elk admin-account is een potentiële toegangspoort voor een aanvaller. Veel organisaties eindigen in de loop van de tijd met te veel admin-accounts: tijdelijke toegang die nooit is ingetrokken, serviceaccounts die voor het gemak aan Domain Admins zijn toegevoegd, enz.

#### Wat de scan controleert

De AD Scan telt het totale aantal **unieke gebruikers** over alle bevoorrechte groepen heen (Domain Admins, Enterprise Admins, Administrators, Account Operators, Server Operators, Backup Operators, enz.). Als dezelfde gebruiker in meerdere groepen zit, wordt die maar één keer geteld.

De waarschuwing wordt geactiveerd als:

* Meer dan **10%** van de actieve gebruikers bevoorrecht is, OF
* Meer dan **50** bevoorrechte accounts bestaan

> Deze controle wordt overgeslagen voor kleine organisaties met minder dan 100 actieve gebruikers.

#### Hoe te diagnosticeren

```powershell
$privilegedGroups = @(
  "Domain Admins", "Enterprise Admins", "Schema Admins", "Administrators",
  "Account Operators", "Server Operators", "Backup Operators", "Print Operators"
)

$uniqueMembers = @{}
foreach ($group in $privilegedGroups) {
  try {
    Get-ADGroupMember -Identity $group -Recursive |
      Where-Object { $_.objectClass -eq "user" } |
      ForEach-Object { $uniqueMembers[$_.DistinguishedName] = $_.SamAccountName }
  } catch {}
}

$activeUsers = (Get-ADUser -Filter "Enabled -eq `$true" | Measure-Object).Count
$pct = [math]::Round(($uniqueMembers.Count / $activeUsers) * 100, 1)

Write-Host "Bevoorrechte accounts: $($uniqueMembers.Count)"
Write-Host "Actieve gebruikers: $activeUsers"
Write-Host "Verhouding: $pct% (waarschuwing als >10% of >50 accounts)"
Write-Host ""
$uniqueMembers.Values | Sort-Object | ForEach-Object { Write-Host "  - $_" }
```

#### Hoe je het oplost

Bekijk de lijst en verwijder accounts die niet echt admin-toegang nodig hebben:

```powershell
Remove-ADGroupMember -Identity "Domain Admins" -Members "username" -Confirm:$false
```

Best practices:

* Gebruik **aparte admin-accounts** (`adm_john`) die verschillen van accounts voor dagelijks gebruik
* **Verwijder serviceaccounts** uit admin-groepen en geef alleen de specifieke rechten die ze nodig hebben
* **Controleer het lidmaatschap van bevoorrechte groepen** regelmatig

## P-ProtectedUsers

#### Wat het betekent

De **Protected Users** groep is een speciale beveiligingsgroep die is geïntroduceerd in Windows Server 2012 R2. Leden van deze groep krijgen extra bescherming:

* Ze kunnen **alleen authenticeren met Kerberos** (het veiligere protocol), niet met het oudere NTLM-protocol
* Hun **referenties worden niet gecachet** op machines waarop ze inloggen: een aanvaller die een werkstation compromitteert, kan hun referenties niet uit het geheugen stelen
* **Delegatie is uitgeschakeld:** hun account kan niet worden geïmiteerd door services

Deze beschermingen zijn cruciaal voor beheerdersaccounts, de primaire doelwitten bij de meeste aanvallen.

#### Wat de scan controleert

De AD Scan controleert of alle **ingeschakelde admin-accounts** (leden van Domain Admins, Enterprise Admins, enz.) ook lid zijn van de **Protected Users** groep.

#### Waarom het alarm kan aanhouden

* **Gebruikers toegevoegd via geneste groepen** worden mogelijk niet gedetecteerd. Voeg gebruikers **rechtstreeks** toe aan de Protected Users-groep.
* **Replicatievertragingen** tussen Domain Controllers kunnen tijdelijke inconsistenties veroorzaken.
* **Managed Service Accounts (gMSA)** worden uitgesloten van deze controle: ze hoeven niet in Protected Users te zitten.

#### Hoe te diagnosticeren

```powershell
$protectedUsers = (Get-ADGroupMember -Identity "Protected Users").DistinguishedName
$privilegedGroups = @("Domain Admins", "Enterprise Admins", "Schema Admins", "Administrators")

$notProtected = foreach ($group in $privilegedGroups) {
  Get-ADGroupMember -Identity $group -Recursive |
    Where-Object { $_.objectClass -eq "user" } |
    ForEach-Object { Get-ADUser $_ -Properties Enabled } |
    Where-Object { $_.Enabled -and $_.DistinguishedName -notin $protectedUsers }
}

$notProtected | Select-Object -Unique SamAccountName, Name | Format-Table -AutoSize
```

#### Hoe je het oplost

```powershell
Add-ADGroupMember -Identity "Protected Users" -Members "adm_john", "adm_jane"
```

> **Belangrijk:** Door accounts toe te voegen aan Protected Users, dwing je **alleen Kerberos-authenticatie af**. Sommige oudere applicaties die NTLM vereisen, kunnen voor deze accounts stoppen met werken. **Test eerst met één account** voordat je alle beheerders toevoegt.
>
> Best practice: admin-accounts moeten worden gebruikt **alleen voor beheertaken** (niet voor e-mail, webbrowsen of het draaien van zakelijke applicaties), dus NTLM-compatibiliteit is zelden een probleem.

## S-OldNtlm

#### Wat het betekent

Windows ondersteunt meerdere authenticatieprotocollen, van zeer oud en onveilig (LM, NTLMv1) tot modern en veilig (NTLMv2, Kerberos). De oudere protocollen hebben bekende kwetsbaarheden die aanvallers kunnen misbruiken om wachtwoorden op het netwerk te onderscheppen en te kraken.

De **LAN Manager-authenticatieniveau** bepaalt welke protocollen zijn toegestaan. Het moet worden ingesteld op **niveau 5**, wat betekent: "alleen NTLMv2 accepteren, alle oudere protocollen weigeren."

#### Wat de scan controleert

De AD Scan leest Group Policy Objects (GPO's) om te verifiëren dat de `LmCompatibilityLevel` instelling is ingesteld op **5**. Als geen enkele GPO deze instelling definieert, gebruikt Windows standaard **niveau 3**, wat nog steeds enkele zwakkere protocollen accepteert.

| Niveau | Wat het toestaat                            | Veilig? |
| ------ | ------------------------------------------- | ------- |
| 0-2    | LM en/of NTLMv1                             | Nee     |
| 3      | NTLMv2 (maar weigert oude protocollen niet) | Nee     |
| **5**  | **alleen NTLMv2, weiger LM & NTLMv1**       | **Ja**  |

#### Waarom het alarm kan aanhouden

1. **Je hebt rechtstreeks het register gewijzigd** in plaats van een GPO te gebruiken. De AD Scan leest GPO-bestanden, niet lokale registerinstellingen. Zelfs als de DC de juiste waarde in het register heeft, blijft de waarschuwing bestaan als deze niet via Group Policy is ingesteld.
2. **Conflicterende GPO's:** Eén GPO stelt niveau 5 in, maar een andere GPO overschrijft dit met een lager niveau.
3. **Helemaal geen GPO:** Zonder GPO is de standaard niveau 3 (onveilig).

#### Hoe te diagnosticeren

```powershell
# Controleer de effectieve instelling op elke DC
Get-ADDomainController -Filter * | ForEach-Object {
  $level = Invoke-Command -ComputerName $_.HostName -ScriptBlock {
    (Get-ItemProperty "HKLM:\System\CurrentControlSet\Control\Lsa" `
      -Name LmCompatibilityLevel -ErrorAction SilentlyContinue).LmCompatibilityLevel
  }
  Write-Host "$($_.HostName): LmCompatibilityLevel = $level"
}

# Controleer welke GPO's deze instelling definiëren
Import-Module GroupPolicy
Get-GPO -All | ForEach-Object {
  [xml]$r = Get-GPOReport -Guid $_.Id -ReportType Xml
  if ($r.InnerXml -match "LmCompatibilityLevel") {
    Write-Host "GPO: $($_.DisplayName)"
  }
}
```

#### Hoe je het oplost

**Via Groepsbeleidsbeheerconsole (aanbevolen):**

1. Open `gpmc.msc`
2. Bewerk de GPO die gekoppeld is aan `OU=Domain Controllers`
3. Navigeer naar: `Computer Configuration > Policies > Windows Settings > Security Settings > Local Policies > Security Options`
4. Stel **"Netwerkbeveiliging: LAN Manager-authenticatieniveau"** in op `Stuur alleen een NTLMv2-reactie. Weiger LM & NTLM`
5. Stel **"Netwerkbeveiliging: sla de LAN Manager-hashwaarde niet op bij de volgende wachtwoordwijziging"** in op `Ingeschakeld`
6. Voer `gpupdate /force` uit op alle Domain Controllers

**Via PowerShell:**

```powershell
$gpoName = "DC - Enforce NTLMv2"
$gpo = Get-GPO -Name $gpoName -ErrorAction SilentlyContinue
if (-not $gpo) { $gpo = New-GPO -Name $gpoName }

Set-GPRegistryValue -Name $gpoName `
  -Key "HKLM\System\CurrentControlSet\Control\Lsa" `
  -ValueName "LmCompatibilityLevel" -Type DWord -Value 5

Set-GPRegistryValue -Name $gpoName `
  -Key "HKLM\System\CurrentControlSet\Control\Lsa" `
  -ValueName "NoLMHash" -Type DWord -Value 1

New-GPLink -Name $gpoName `
  -Target "OU=Domain Controllers,$($(Get-ADDomain).DistinguishedName)" `
  -LinkEnabled Yes
```

## S-AesNotEnabled

#### Wat het betekent

Wanneer je je authenticatie uitvoert in Active Directory, wordt je wachtwoord gebruikt om communicatie te versleutelen met een specifiek algoritme. Oudere algoritmen (**DES**, **RC4**) zijn zwak en kunnen relatief eenvoudig worden gekraakt. Moderne algoritmen (**AES-128**, **AES-256**) zijn veel sterker.

AES-ondersteuning werd geïntroduceerd met Windows Server 2008. Accounts die vóór de upgrade bestonden, of accounts met specifieke configuraties, gebruiken mogelijk nog steeds de oude, zwakkere versleuteling.

#### Wat de scan controleert

Een account wordt in twee situaties gemarkeerd:

1. **Het wachtwoord van het account werd ingesteld vóórdat je domein werd geüpgraded naar Server 2008.** Omdat AES-versleutelingssleutels alleen worden gegenereerd wanneer een wachtwoord wordt ingesteld op een moderne DC, hebben deze oude wachtwoorden alleen zwakke RC4/DES-sleutels.
2. **Het account heeft een Service Principal Name (SPN)** en de versleutelingsinstellingen bevatten geen AES (het `msDS-SupportedEncryptionTypes` attribuut mist AES-vlaggen).

#### Hoe te diagnosticeren

```powershell
# Zoek serviceaccounts zonder AES-ondersteuning
Get-ADUser -Filter 'ServicePrincipalName -like "*"' `
  -Properties ServicePrincipalName, "msDS-SupportedEncryptionTypes", PasswordLastSet |
  Where-Object { ([int]$_."msDS-SupportedEncryptionTypes" -band 24) -eq 0 } |
  Select-Object SamAccountName,
    @{N="Versleutelingstypen"; E={$_."msDS-SupportedEncryptionTypes"}},
    PasswordLastSet

# Hetzelfde voor computeraccounts
Get-ADComputer -Filter 'ServicePrincipalName -like "*"' `
  -Properties "msDS-SupportedEncryptionTypes" |
  Where-Object { ([int]$_."msDS-SupportedEncryptionTypes" -band 24) -eq 0 } |
  Select-Object Name, @{N="Versleutelingstypen"; E={$_."msDS-SupportedEncryptionTypes"}}
```

#### Hoe je het oplost

**Voor accounts met oude wachtwoorden:** Stel gewoon het wachtwoord opnieuw in. Dit genereert nieuwe AES-sleutels:

```powershell
Set-ADAccountPassword -Identity "svc_account" `
  -NewPassword (ConvertTo-SecureString "YourNewStr0ngP@ssw0rd!" -AsPlainText -Force) -Reset
```

**Voor accounts die AES-versleutelingsinstellingen missen:** Schakel AES in voor de versleutelingstypen van het account:

```powershell
# Schakel AES in voor een specifiek account (24 = AES-128 + AES-256)
Set-ADUser -Identity "svc_account" -Replace @{"msDS-SupportedEncryptionTypes" = 24}

# Voor een computeraccount
Set-ADComputer -Identity "server01" -Replace @{"msDS-SupportedEncryptionTypes" = 24}

# Bulkfix voor alle serviceaccounts zonder AES
Get-ADUser -Filter 'ServicePrincipalName -like "*"' `
  -Properties "msDS-SupportedEncryptionTypes" |
  Where-Object { ([int]$_."msDS-SupportedEncryptionTypes" -band 24) -eq 0 } |
  ForEach-Object {
    Set-ADUser $_ -Replace @{"msDS-SupportedEncryptionTypes" = 24}
    Write-Host "AES ingeschakeld voor $($_.SamAccountName)"
  }
```

> **Opmerking:** Het inschakelen van AES is niet-destructief: bestaande authenticatie blijft werken. Test echter eerst met kritieke services voordat je het in bulk toepast.

## A-NoGPOLLMNR

#### Wat het betekent

**LLMNR** (Link-Local Multicast Name Resolution) is een protocol dat Windows gebruikt om andere computers op het netwerk te vinden wanneer DNS het antwoord niet weet. Het werkt door een vraag uit te zenden naar alle nabijgelegen machines: "Weet iemand waar `servername` is?"

Het probleem is: een aanvaller op hetzelfde netwerk kan **op deze uitzendingen reageren alsof hij de doelserver is**, waardoor het slachtoffer zijn referenties naar de aanvaller stuurt. Dit heet een **LLMNR-poisoning** aanval en is een van de meest voorkomende technieken die worden gebruikt bij interne netwerkaanvallen.

LLMNR is een verouderd protocol dat moderne netwerken niet nodig hebben (DNS regelt alles). Het moet via Groepsbeleid worden uitgeschakeld.

#### Wat de scan controleert

De AD Scan zoekt naar een **ingeschakelde en gekoppelde GPO** die LLMNR uitschakelt door de `EnableMulticast` registerwaarde in te stellen op `0`.

#### Waarom het alarm kan aanhouden

1. **GPO bestaat maar is niet gekoppeld** aan een OU.
2. **GPO is uitgeschakeld**, zelfs als deze gekoppeld is.
3. **LLMNR is handmatig uitgeschakeld** (via register of `netsh`) maar niet via Groepsbeleid. De AD Scan leest GPO-bestanden, niet lokale machine-instellingen.

#### Hoe te diagnosticeren

```powershell
Import-Module GroupPolicy
Get-GPO -All | ForEach-Object {
  [xml]$r = Get-GPOReport -Guid $_.Id -ReportType Xml
  if ($r.InnerXml -match "EnableMulticast") {
    Write-Host "GPO '$($_.DisplayName)' - Status: $($_.GpoStatus) - Bevat LLMNR-instelling"
  }
}
```

#### Hoe je het oplost

```powershell
$gpoName = "Disable LLMNR"
$gpo = Get-GPO -Name $gpoName -ErrorAction SilentlyContinue
if (-not $gpo) { $gpo = New-GPO -Name $gpoName }

Set-GPRegistryValue -Name $gpoName `
  -Key "HKLM\Software\Policies\Microsoft\Windows NT\DNSClient" `
  -ValueName "EnableMulticast" -Type DWord -Value 0

# Koppel aan de domeinwortel zodat het op alle computers wordt toegepast
New-GPLink -Name $gpoName `
  -Target (Get-ADDomain).DistinguishedName `
  -LinkEnabled Yes
```

Nadat je de GPO hebt gekoppeld, voer `gpupdate /force` uit op machines of wacht op de volgende vernieuwing van Groepsbeleid (meestal 90 minuten).

## Veelgestelde vragen

#### De waarschuwing wordt nog steeds weergegeven nadat ik de oplossing heb toegepast. Waarom?

De AD Scan draait niet periodiek. Na het toepassen van een oplossing moet je **het script opnieuw uitvoeren** om de waarschuwing te laten verdwijnen. Als de waarschuwing na een nieuwe scan blijft bestaan, was de oplossing waarschijnlijk slechts gedeeltelijk. Raadpleeg de sectie "Waarom de waarschuwing kan blijven bestaan" van de relevante kwetsbaarheid. Zorg ervoor dat je de details van de kwetsbaarheid in je rapport leest; die bevatten vaak details over de getroffen assets.

#### Heb ik Domain Admin-rechten nodig om de scan uit te voeren?

Sommige kwetsbaarheden (bijv. A-NoServicePolicy) vereisen verhoogde rechten om bepaalde AD-objecten te lezen. Het uitvoeren van de scan met een **Domain Admin-account** zorgt ervoor dat alle objecten zichtbaar zijn en voorkomt fout-positieve waarschuwingen veroorzaakt door onvoldoende machtigingen. Als dat niet mogelijk is, kunt u het script nog steeds uitvoeren als een gewone domeingebruiker, hoewel sommige kwetsbaarheden kunnen verschijnen door een gebrek aan zichtbaarheid op AD-objecten.

#### Ik heb één kwetsbaarheid opgelost, maar er verscheen een nieuwe. Is dat normaal?

Ja. Sommige oplossingen kunnen andere problemen aan het licht brengen. Bijvoorbeeld, het installeren van LAPS (het oplossen van A-LAPS-Not-Installed) kan A-LAPS-Joined-Computers triggeren als computerobjecten onjuiste machtigingen hebben. Dit is te verwachten: werk elke waarschuwing af in volgorde van ernst.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.stoik.io/cyber-best-practices/nl/handleidingen-voor-het-verhelpen-van-kwetsbaarheden/ad-scan-vulnerability-remediation-guide.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
