# Scan AD : guide de remédiation des vulnérabilités

Chaque section de vulnérabilité comprend :

* **Ce que cela signifie :** une explication du risque en langage clair
* **Ce que l'analyse vérifie :** les conditions spécifiques qui déclenchent l'alerte
* **Pourquoi l'alerte peut persister :** des correctifs partiels courants qui ne suffisent pas
* **Comment diagnostiquer :** Commandes PowerShell pour identifier les objets concernés
* **Comment corriger :** remédiation étape par étape

> **Prérequis :** Toutes les commandes PowerShell nécessitent le `ActiveDirectory` module et doivent être exécutées en tant qu'administrateur du domaine sur un contrôleur de domaine.
>
> ```powershell
> Import-Module ActiveDirectory
> ```

## A-LAPS-Not-Installed

#### Ce que cela signifie

Chaque ordinateur Windows dispose d'un **compte Administrateur local intégré**. Par défaut, ce compte a souvent le même mot de passe sur toutes les machines, ou un mot de passe qui ne change jamais. Si un attaquant compromet une machine, il peut réutiliser ce mot de passe pour accéder à toutes les autres.

**LAPS** (Local Administrator Password Solution) résout ce problème en définissant automatiquement un mot de passe unique, généré aléatoirement, sur chaque ordinateur et en le stockant de manière sécurisée dans Active Directory. Seuls les administrateurs autorisés peuvent le récupérer.

#### Ce que l'analyse vérifie

L'analyse AD recherche des preuves que LAPS a été configuré dans votre Active Directory. Plus précisément, elle vérifie si les champs de données LAPS nécessaires existent dans votre configuration AD. S'ils n'existent pas, cela signifie que LAPS n'a jamais été installé.

#### Pourquoi l'alerte peut persister

* **LAPS géré uniquement via Intune :** Si vous utilisez Microsoft Intune pour gérer les mots de passe LAPS dans le cloud (sans configurer l'AD sur site), l'analyse AD ne peut pas le détecter. L'analyse ne vérifie que votre Active Directory local.
* **LAPS a été partiellement installé :** La configuration de LAPS a peut-être été commencée mais non terminée.

#### Comment diagnostiquer

```powershell
# Vérifier si LAPS est configuré dans votre Active Directory
Get-ADObject -SearchBase (Get-ADRootDSE).SchemaNamingContext `
  -Filter "name -like 'ms-Mcs-AdmPwd' -or name -eq 'ms-LAPS-Password'" |
  Select-Object Name, whenCreated
```

Si cela ne renvoie aucun résultat, LAPS n'est pas installé.

#### Comment corriger

**Pour Windows Server 2019 et versions ultérieures (recommandé) :** Le LAPS moderne est intégré à Windows. Activez-le via la stratégie de groupe :

1. Ouvrez `gpmc.msc` (Gestion des stratégies de groupe)
2. Modifiez ou créez un GPO lié à vos UO d'ordinateurs
3. Accédez à : `Configuration ordinateur > Modèles d'administration > Système > LAPS`
4. Configurez les paramètres LAPS (activation, complexité du mot de passe, etc.)

**Pour les environnements plus anciens :** Téléchargez l'ancien LAPS de Microsoft et exécutez l'extension de schéma :

```powershell
Update-LapsADSchema
```

> **Remarque :** Si vous gérez les mots de passe des administrateurs locaux avec un autre outil (CyberArk, LAPS uniquement via Intune, etc.), contactez le support Stoïk pour documenter cela comme une exception acceptée.

## A-LAPS-Joined-Computers

#### Ce que cela signifie

Lorsqu'une personne ajoute ("joint") un ordinateur au domaine Active Directory, cette personne devient le **créateur** de l'objet ordinateur dans AD. Par défaut, le créateur obtient des autorisations spéciales sur cet objet.

Le problème est le suivant : lorsque LAPS est installé, le mot de passe de l'administrateur local est stocké sur ce même objet ordinateur. Si le créateur conserve les bonnes autorisations, il peut **lire le mot de passe LAPS**, même s'il n'est pas administrateur. Cela signifie qu'un utilisateur ordinaire qui a un jour joint un PC au domaine pourrait récupérer le mot de passe de l'administrateur local de cette machine.

#### Ce que l'analyse vérifie

Pour chaque ordinateur activé sur lequel LAPS est déployé, l'analyse AD vérifie **deux choses**:

1. **La personne qui a joint l'ordinateur est-elle toujours le "propriétaire" de l'objet ordinateur ?** Les propriétaires peuvent s'accorder n'importe quelle autorisation, y compris la lecture du mot de passe LAPS.
2. **Le créateur dispose-t-il toujours d'autorisations explicites** sur l'objet ordinateur, telles que `Tous les droits étendus` (ce qui permet de lire le mot de passe LAPS), `WriteDacl` (ce qui permet de modifier les autorisations), `WriteOwner` (ce qui permet de reprendre la propriété), ou `GenericWrite`?

L'alerte se déclenche si **l'une ou l'autre** condition est vraie.

#### Pourquoi l'alerte peut persister

C'est la source de confusion la plus courante : **changer le propriétaire n'est que la moitié du correctif.**

De nombreux administrateurs changent le propriétaire en « Domain Admins » et s'attendent à ce que l'alerte disparaisse. Mais l'analyse AD vérifie aussi les autorisations restantes (appelées ACE, ou Access Control Entries) qui ont été accordées au créateur d'origine. Ces autorisations restent en place même après le changement de propriétaire et doivent être supprimées séparément.

#### Comment diagnostiquer

```powershell
# Lister les ordinateurs où le créateur a encore des autorisations risquées
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
```

#### Comment corriger

Vous devez faire **les deux** actions suivantes pour chaque ordinateur concerné :

1. **Changer le propriétaire** en Administrateurs du domaine
2. **Supprimer les autorisations explicites du créateur**

Le script suivant fait les deux automatiquement :

```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

  # Étape 1 : changer le propriétaire en Administrateurs du domaine
  $domainAdmins = New-Object System.Security.Principal.NTAccount("$env:USERDOMAIN", "Domain Admins")
  $acl.SetOwner($domainAdmins)
  $modified = $true

  # Étape 2 : supprimer les autorisations explicites accordées au créateur (et les SID orphelins)
  $toRemove = @($acl.Access | Where-Object {
    -not $_.IsInherited -and
    ($_.IdentityReference.Value -eq $creatorSid.Value -or
     $_.IdentityReference.Value -match '^S-1-5-21-')  # SID orphelins (comptes supprimés)
  })

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

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

> **Astuce :** Exécutez d'abord la commande de diagnostic pour examiner la liste des ordinateurs concernés avant d'appliquer le correctif.

## A-NoServicePolicy

#### Ce que cela signifie

**Comptes de service** sont des comptes utilisés par les applications et les services (par ex. SQL Server, les agents de sauvegarde) pour s'authentifier dans Active Directory. Contrairement aux comptes utilisateur ordinaires, les comptes de service sont des cibles de grande valeur : ils disposent souvent d'autorisations élevées et leurs mots de passe sont rarement modifiés.

Une **stratégie de mot de passe à granularité fine (PSO)** est une règle de mot de passe spéciale que vous pouvez appliquer à des groupes de comptes spécifiques. L'analyse AD s'attend à ce que vos comptes de service soient couverts par une PSO exigeant des mots de passe d'au moins **20 caractères**, ce qui les rend beaucoup plus difficiles à craquer.

#### Ce que l'analyse vérifie

L'analyse AD recherche au moins une stratégie de mot de passe (GPO ou PSO) qui impose une longueur minimale du mot de passe de **20 caractères ou plus**.

#### Pourquoi l'alerte peut persister

1. **Le compte d'analyse n'a pas l'autorisation de lire la PSO.** Les stratégies de mot de passe sont stockées dans une zone protégée d'AD que seuls les administrateurs du domaine peuvent lire par défaut. Si l'analyse s'exécute avec un compte moins privilégié, elle ne peut tout simplement pas voir la PSO, même si elle existe.
2. **La PSO existe, mais la longueur minimale est inférieure à 20** (par ex. 12 ou 15 caractères).
3. **La PSO existe mais n'est assignée à aucun groupe ni utilisateur.**

#### Comment diagnostiquer

```powershell
# Lister toutes les stratégies de mot de passe à granularité fine et leurs paramètres
Get-ADFineGrainedPasswordPolicy -Filter * |
  Select-Object Name, MinPasswordLength, @{N="AppliedTo"; E={$_.AppliesTo -join ", "}}, Precedence
```

Si cela ne renvoie rien, soit aucune PSO n'existe, soit le compte qui exécute la commande n'a pas les autorisations pour la voir. Essayez d'exécuter avec un compte d'administrateur du domaine.

#### Comment corriger

**Si la PSO existe mais que l'analyse ne peut pas la voir :** Exécutez l'analyse AD avec un compte d'administrateur du domaine.

**Si aucune PSO n'existe :** Créez-en une et attribuez-la à vos comptes de service :

```powershell
# Créer une stratégie de mot de passe pour les comptes de service
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

# L'attribuer à un groupe de sécurité contenant vos comptes de service
Add-ADFineGrainedPasswordPolicySubject `
  -Identity "Service Accounts - Strong Password" `
  -Subjects "SG_ServiceAccounts"
```

> **Remarque :** La création d'une PSO ne force pas immédiatement les changements de mot de passe. Les mots de passe existants continueront de fonctionner jusqu'à leur expiration ou jusqu'à leur réinitialisation manuelle. À ce moment-là, la nouvelle longueur minimale de 20 caractères s'appliquera.

## A-AuditDC

#### Ce que cela signifie

**Stratégies d'audit** déterminent quels événements sont consignés sur vos contrôleurs de domaine. Sans audit approprié, des attaques comme le vol d'identifiants, des changements de groupe non autorisés ou l'abus de réplication (DCSync) peuvent se produire sans laisser la moindre trace dans les journaux.

L'analyse AD vérifie que vos contrôleurs de domaine sont configurés pour enregistrer les événements de sécurité les plus importants.

#### Ce que l'analyse vérifie

L'analyse recherche **13 sous-catégories d'audit spécifiques** qui devraient être activées via la stratégie de groupe sur tous les contrôleurs de domaine :

| Catégorie                                       | Ce qu'elle consigne                                                     |
| ----------------------------------------------- | ----------------------------------------------------------------------- |
| Service d'authentification Kerberos             | Tentatives de connexion via Kerberos                                    |
| Opérations de tickets de service Kerberos       | Demandes de tickets de service (détecte le Kerberoasting)               |
| Gestion des comptes ordinateur                  | Jonctions/modifications d'ordinateurs dans AD                           |
| Gestion des groupes de sécurité                 | Modifications d'appartenance aux groupes                                |
| Gestion des comptes utilisateur                 | Création d'utilisateurs, suppression, réinitialisations de mot de passe |
| Activité DPAPI                                  | Utilisation de l'API de protection des données (accès aux identifiants) |
| Création de processus                           | Nouveaux processus lancés (détecte les outils malveillants)             |
| Ouverture / fermeture de session                | Connexions interactives et à distance                                   |
| Connexion spéciale                              | Connexions avec privilèges élevés                                       |
| Modification de la stratégie d'authentification | Modifications des paramètres d'authentification                         |
| Utilisation de privilèges sensibles             | Utilisation d'autorisations sensibles                                   |
| Extension du système de sécurité                | Modifications du sous-système de sécurité                               |

#### Pourquoi l'alerte peut persister

1. **Paramètres appliqués via `auditpol` directement sur le DC** ne sont pas détectés. L'analyse AD lit les fichiers de stratégie de groupe, pas la configuration locale du DC. Vous devez utiliser un GPO.
2. **GPO en conflit :** Un GPO active le paramètre, mais un autre GPO de priorité supérieure le désactive.
3. **GPO non lié à l'UO des contrôleurs de domaine :** Le GPO existe mais est lié à une autre UO.

#### Comment diagnostiquer

```powershell
# Vérifier la stratégie d'audit effective sur un contrôleur de domaine
auditpol /get /category:*
```

Si les paramètres locaux semblent corrects mais que l'alerte persiste, vérifiez que les paramètres proviennent d'un GPO (et non d'une substitution locale) :

```powershell
# Vérifier quels GPO sont liés à l'UO des contrôleurs de domaine
Get-GPInheritance -Target "OU=Domain Controllers,$($(Get-ADDomain).DistinguishedName)"
```

#### Comment corriger

1. Ouvrez `gpmc.msc` (Console de gestion des stratégies de groupe)
2. Créez ou modifiez un GPO lié à `OU=Domain Controllers`
3. Accédez à : `Configuration ordinateur > Stratégies > Paramètres Windows > Paramètres de sécurité > Configuration avancée de la stratégie d'audit > Stratégies d'audit`
4. Activez **Succès et échec** pour toutes les sous-catégories listées ci-dessus
5. Exécutez `gpupdate /force` sur tous les contrôleurs de domaine

Vérifiez le correctif :

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

## A-BadSuccessor

#### Ce que cela signifie

Windows Server 2025 a introduit un nouveau type de compte de service appelé **dMSA** (Delegated Managed Service Account). Une faille de sécurité a été découverte : un utilisateur ordinaire disposant de certaines autorisations sur un dossier Active Directory (appelé unité d'organisation, ou OU) pouvait créer un dMSA et l'utiliser pour obtenir un accès administrateur complet au domaine.

Cette attaque n'est possible que lorsque :

* Vous avez au moins un **Windows Server 2025** contrôleur de domaine
* Une **KDS Root Key** existe (nécessaire pour les comptes de service gérés)
* Un utilisateur non administrateur a le droit de créer des objets dans une OU

#### Ce que l'analyse vérifie

L'analyse AD recherche des utilisateurs ou des groupes non privilégiés qui ont des autorisations pour créer ou contrôler des objets dMSA dans n'importe quelle OU, telles que `CreateChild`, `GenericAll`, `WriteDacl`, ou `WriteOwner`.

#### Pourquoi l'alerte peut persister

* Le correctif doit être appliqué sur **chaque** OU concernée, et pas seulement une.
* Les autorisations héritées des UO parentes s'appliquent toujours aux UO enfants.
* Les groupes d'administration personnalisés peuvent ne pas être reconnus comme « privilégiés » par l'analyse.

#### Comment diagnostiquer

```powershell
# Vérifier les prérequis
Get-KdsRootKey  # La KDS Root Key doit exister pour que l'attaque soit possible

Get-ADDomainController -Filter * |
  Where-Object { $_.OperatingSystem -like "*2025*" } |
  Select-Object Name, OperatingSystem  # Au moins un DC Win2025

# Trouver les UO avec des délégations risquées
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
```

#### Comment corriger

Pour chaque OU signalée, supprimez les autorisations risquées des utilisateurs non administrateurs :

```powershell
$ouDN = "OU=Servers,DC=yourdomain,DC=com"  # Remplacez par votre OU
$path = "AD:$ouDN"
$acl = Get-Acl -Path $path

# Supprimer les droits risqués pour un groupe spécifique
$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

#### Ce que cela signifie

Lorsqu'un utilisateur est ajouté à un groupe privilégié dans Active Directory (comme les administrateurs du domaine), le système marque automatiquement son compte avec un indicateur appelé `adminCount = 1`. Cet indicateur fait partie d'un mécanisme de protection intégré.

Le problème est le suivant : **lorsque vous retirez cet utilisateur du groupe d'administration, l'indicateur n'est PAS effacé automatiquement.** Il reste indéfiniment, sauf si vous le supprimez explicitement.

L'analyse AD signale les comptes qui conservent cet `adminCount` indicateur, mais ne sont plus de vrais administrateurs. Cela peut indiquer :

* Un utilisateur qui a été temporairement promu administrateur et dont le nettoyage a été incomplet
* Un risque potentiel pour la sécurité : ces comptes peuvent encore disposer d'autorisations élevées dans certains domaines

#### Ce que l'analyse vérifie

L'analyse trouve des comptes utilisateur activés pour lesquels `adminCount = 1` mais le compte n'est actuellement membre d'aucun groupe privilégié.

#### Comment diagnostiquer

```powershell
# Construire une liste de tous les utilisateurs privilégiés actuels
$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 {}
}

# Trouver les comptes avec l'indicateur adminCount résiduel
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
```

#### Comment corriger

Après avoir confirmé que ces comptes ne doivent plus être administrateurs, effacez l'indicateur :

```powershell
# Effacer adminCount pour un seul utilisateur
Set-ADUser -Identity "username" -Clear adminCount

# Ou l'effacer pour tous les utilisateurs non privilégiés en une seule fois
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 effacé pour $($_.SamAccountName)"
  }
```

## P-Kerberoasting

#### Ce que cela signifie

Dans Active Directory, certains comptes sont enregistrés pour exécuter des services tels qu'un serveur SQL ou une application web. Ces comptes ont un **Nom principal du service (SPN)**, qui est essentiellement une étiquette indiquant « ce compte exécute un service réseau. »

Le risque de sécurité est : **tout utilisateur authentifié** dans le domaine peut demander un ticket Kerberos pour n'importe quel compte disposant d'un SPN. Ce ticket est chiffré avec le mot de passe du compte, et l'attaquant peut alors tenter de le casser hors ligne, sans déclencher aucune alerte.

C'est ce qu'on appelle une **Kerberoasting** attaque. Elle est particulièrement dangereuse lorsque le compte avec le SPN est aussi un **administrateur de domaine**, car craquer ce mot de passe signifie un contrôle total du domaine.

#### Ce que l'analyse vérifie

La vérification AD signale les comptes qui remplissent **les trois** conditions :

1. Le compte est membre d'un **groupe privilégié** (Administrateurs de domaine, Administrateurs d'entreprise, etc.)
2. Le compte a un **Nom principal du service (SPN)**
3. Le **mot de passe du compte n'a pas été modifié depuis plus de 40 jours** (laissant plus de temps aux attaquants pour le casser)

#### Pourquoi l'alerte peut persister

Vous devez corriger **les trois** ces conditions. Corrections incomplètes courantes :

* **Mot de passe changé mais SPN conservé :** L'alerte disparaît temporairement, mais revient au bout de 40 jours.
* **SPN supprimé mais le compte est toujours dans Administrateurs de domaine :** L'alerte disparaît, mais le risque sous-jacent demeure.

#### Comment diagnostiquer

```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="Âge du mot de passe (jours)"; E={[math]::Round(((Get-Date) - $_.PasswordLastSet).TotalDays)}},
      @{N="SPN"; E={$_.ServicePrincipalName -join "; "}}
}
```

#### Comment corriger

**Meilleure option : supprimer le compte des groupes privilégiés.** Les comptes de service ont rarement besoin d'être administrateurs de domaine. Créez un compte dédié, non privilégié, avec uniquement les autorisations réellement nécessaires au service :

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

**Si vous ne pouvez pas le retirer du groupe d'administration :** Au minimum, réinitialisez régulièrement le mot de passe (tous les 30 jours ou moins) :

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

**Meilleure solution à long terme :** Convertir en un **compte de service géré de groupe (gMSA)**, qui fait automatiquement tourner son mot de passe tous les 30 jours :

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

## P-Connexion administrateur

#### Ce que cela signifie

Chaque domaine Active Directory possède un **compte Administrateur intégré** créé automatiquement lors de la configuration du domaine. Ce compte a un contrôle total sur l'ensemble du domaine et ne peut pas être verrouillé.

En raison de sa puissance et de sa prévisibilité (les attaquants savent qu'il existe toujours), il doit être réservé aux **situations d'urgence uniquement**, par exemple lors d'une reprise après sinistre. L'administration quotidienne devrait utiliser des comptes admin personnels (par ex., `adm_john`) afin que les actions puissent être attribuées à des personnes.

#### Ce que l'analyse vérifie

La vérification AD contrôle si le compte Administrateur intégré s'est connecté à un contrôleur de domaine quelconque au cours des **35 derniers jours**. Si c'est le cas, l'alerte se déclenche, indiquant que le compte est utilisé pour des tâches courantes au lieu d'être conservé pour les situations d'urgence.

#### Pourquoi l'alerte peut persister

* **Renommer le compte n'aide pas.** La vérification identifie l'Administrateur intégré par son identifiant interne (RID-500), et non par son nom.
* **Changer le mot de passe n'aide pas.** La vérification contrôle l'activité de connexion, pas l'ancienneté du mot de passe.
* **Les scripts automatisés ou les tâches planifiées** exécutés sous l'Administrateur intégré continueront à déclencher l'alerte.
* **Il suffit d'attendre.** Après avoir cessé d'utiliser le compte, l'alerte disparaît automatiquement au bout de 35 jours.

#### Comment diagnostiquer

```powershell
# Vérifier quand l'Administrateur intégré s'est connecté pour la dernière fois sur chaque 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) { "ALERTE - Utilisé récemment" } else { "OK" }
  }
} | Format-Table -AutoSize
```

Vérifiez aussi les tâches planifiées qui pourraient utiliser l'Administrateur intégré :

```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}}
  }
}
```

#### Comment corriger

1. **Créer des comptes d'administration personnels** pour chaque administrateur (par ex., `adm_john`, `adm_jane`)
2. **Mettre à jour toutes les tâches planifiées** pour qu'elles utilisent un compte de service dédié au lieu de l'Administrateur intégré
3. **Arrêter de se connecter** avec l'Administrateur intégré pour les tâches courantes
4. L'alerte disparaîtra automatiquement **35 jours** après la dernière connexion

## P-Nombre d'administrateurs

#### Ce que cela signifie

Plus il y a de comptes disposant de privilèges d'administrateur dans votre domaine, plus la surface d'attaque est grande. Chaque compte admin est un point d'entrée potentiel pour un attaquant. De nombreuses organisations finissent avec trop de comptes admin au fil du temps : accès temporaire jamais révoqué, comptes de service ajoutés à Administrateurs de domaine par commodité, etc.

#### Ce que l'analyse vérifie

La vérification AD compte le nombre total de **utilisateurs uniques** dans tous les groupes privilégiés (Administrateurs de domaine, Administrateurs d'entreprise, Administrateurs, Opérateurs de compte, Opérateurs de serveur, Opérateurs de sauvegarde, etc.). Si le même utilisateur appartient à plusieurs groupes, il n'est compté qu'une seule fois.

L'alerte se déclenche si :

* Plus de **10%** des utilisateurs actifs sont privilégiés, OU
* Plus de **50** de comptes privilégiés existent

> Cette vérification est ignorée pour les petites organisations ayant moins de 100 utilisateurs actifs.

#### Comment diagnostiquer

```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 "Comptes privilégiés : $($uniqueMembers.Count)"
Write-Host "Utilisateurs actifs : $activeUsers"
Write-Host "Ratio : $pct% (alerte si >10 % ou >50 comptes)"
Write-Host ""
$uniqueMembers.Values | Sort-Object | ForEach-Object { Write-Host "  - $_" }
```

#### Comment corriger

Passez la liste en revue et supprimez les comptes qui n'ont pas réellement besoin d'un accès administrateur :

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

Bonnes pratiques :

* Utilisez **des comptes d'administration distincts** (`adm_john`) qui sont différents des comptes utilisés au quotidien
* **Retirez les comptes de service** des groupes d'administration, en ne leur accordant que les autorisations spécifiques dont ils ont besoin
* **Passez en revue l'appartenance aux groupes privilégiés** régulièrement

## P-Utilisateurs protégés

#### Ce que cela signifie

Le **groupe Utilisateurs protégés** est un groupe de sécurité spécial introduit dans Windows Server 2012 R2. Les membres de ce groupe bénéficient de protections supplémentaires :

* Ils peuvent **s'authentifier uniquement avec Kerberos** (le protocole le plus sûr), et non avec l'ancien protocole NTLM
* Leurs **identifiants ne sont pas mis en cache** sur les machines sur lesquelles ils se connectent : un attaquant qui compromet un poste de travail ne peut pas voler leurs identifiants depuis la mémoire
* **La délégation est désactivée :** leur compte ne peut pas être usurpé par des services

Ces protections sont essentielles pour les comptes d'administrateur, qui sont les cibles principales de la plupart des attaques.

#### Ce que l'analyse vérifie

La vérification AD confirme que tous les **les comptes d'administration activés** (membres des Administrateurs de domaine, Administrateurs d'entreprise, etc.) sont également membres du **groupe Utilisateurs protégés** groupe.

#### Pourquoi l'alerte peut persister

* **Les utilisateurs ajoutés via des groupes imbriqués** peuvent ne pas être détectés. Ajoutez les utilisateurs **directement** au groupe Utilisateurs protégés.
* **Des retards de réplication** entre les contrôleurs de domaine peuvent provoquer des incohérences temporaires.
* **Les comptes de service gérés (gMSA)** sont exclus de cette vérification : ils n'ont pas besoin d'être dans Utilisateurs protégés.

#### Comment diagnostiquer

```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
```

#### Comment corriger

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

> **Important :** L'ajout de comptes à Utilisateurs protégés impose **une authentification Kerberos uniquement**. Certaines applications héritées qui nécessitent NTLM peuvent cesser de fonctionner pour ces comptes. **Testez d'abord avec un seul compte** avant d'ajouter tous les administrateurs.
>
> Bonne pratique : les comptes d'administration doivent être utilisés **uniquement pour des tâches d'administration** (pas pour l'e-mail, la navigation web ou l'exécution d'applications métier), la compatibilité NTLM est donc rarement un problème.

## S-NTLM ancien

#### Ce que cela signifie

Windows prend en charge plusieurs protocoles d'authentification, des plus anciens et les moins sûrs (LM, NTLMv1) aux plus modernes et sécurisés (NTLMv2, Kerberos). Les anciens protocoles présentent des vulnérabilités connues que les attaquants peuvent exploiter pour capturer et casser des mots de passe sur le réseau.

Le **Niveau d'authentification LAN Manager** contrôle les protocoles autorisés. Il doit être défini sur **le niveau 5**, c'est-à-dire « accepter uniquement NTLMv2, refuser tous les protocoles plus anciens. »

#### Ce que l'analyse vérifie

La vérification AD lit les objets de stratégie de groupe (GPO) pour vérifier que le `LmCompatibilityLevel` paramètre est défini sur **5**. Si aucune GPO ne définit ce paramètre, Windows utilise par défaut le **niveau 3**, qui accepte encore certains protocoles plus faibles.

| Niveau | Ce qu'il autorise                                  | Sûr ?   |
| ------ | -------------------------------------------------- | ------- |
| 0-2    | LM et/ou NTLMv1                                    | Non     |
| 3      | NTLMv2 (mais ne refuse pas les anciens protocoles) | Non     |
| **5**  | **NTLMv2 uniquement, refuser LM et NTLMv1**        | **Oui** |

#### Pourquoi l'alerte peut persister

1. **Vous avez modifié directement le registre** au lieu d'utiliser une GPO. La vérification AD lit les fichiers GPO, pas les paramètres du registre local. Même si le contrôleur de domaine possède la bonne valeur dans le registre, l'alerte persiste si elle n'a pas été définie via la stratégie de groupe.
2. **GPO en conflit :** Une GPO définit le niveau 5, mais une autre GPO l'écrase avec un niveau plus faible.
3. **Aucune GPO du tout :** Sans aucune GPO, la valeur par défaut est le niveau 3 (non sécurisé).

#### Comment diagnostiquer

```powershell
# Vérifier le paramètre effectif sur chaque 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"
}

# Vérifier quelles GPO définissent ce paramètre
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)"
  }
}
```

#### Comment corriger

**Via la console de gestion de la stratégie de groupe (recommandé) :**

1. Ouvrez `gpmc.msc`
2. Modifiez la GPO liée à `OU=Domain Controllers`
3. Accédez à : `Configuration ordinateur > Stratégies > Paramètres Windows > Paramètres de sécurité > Stratégies locales > Options de sécurité`
4. Définissez **"Sécurité réseau : niveau d'authentification LAN Manager"** sur `Envoyer uniquement une réponse NTLMv2. Refuser LM et NTLM`
5. Définissez **"Sécurité réseau : ne pas stocker la valeur de hachage LAN Manager lors du prochain changement de mot de passe"** sur `Activé`
6. Exécutez `gpupdate /force` sur tous les contrôleurs de domaine

**Via PowerShell :**

```powershell
$gpoName = "DC - Forcer 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-AES non activé

#### Ce que cela signifie

Lorsque vous vous authentifiez dans Active Directory, votre mot de passe sert à chiffrer les communications à l'aide d'un algorithme spécifique. Les anciens algorithmes (**DES**, **RC4**) sont faibles et peuvent être cassés relativement facilement. Les algorithmes modernes (**AES-128**, **AES-256**) sont beaucoup plus robustes.

La prise en charge d'AES a été introduite avec Windows Server 2008. Cependant, les comptes qui existaient avant la mise à niveau, ou les comptes avec des configurations spécifiques, peuvent encore utiliser l'ancien chiffrement plus faible.

#### Ce que l'analyse vérifie

Un compte est signalé dans deux situations :

1. **Le mot de passe du compte a été défini avant la mise à niveau de votre domaine vers Server 2008.** Comme les clés de chiffrement AES ne sont générées que lorsqu'un mot de passe est défini sur un contrôleur de domaine moderne, ces anciens mots de passe n'ont que des clés RC4/DES faibles.
2. **Le compte possède un nom principal de service (SPN)** et ses paramètres de chiffrement n'incluent pas AES (l' `msDS-SupportedEncryptionTypes` attribut ne comporte pas les indicateurs AES).

#### Comment diagnostiquer

```powershell
# Rechercher les comptes de service sans prise en charge d'AES
Get-ADUser -Filter 'ServicePrincipalName -like "*"' `
  -Properties ServicePrincipalName, "msDS-SupportedEncryptionTypes", PasswordLastSet |
  Where-Object { ([int]$_."msDS-SupportedEncryptionTypes" -band 24) -eq 0 } |
  Select-Object SamAccountName,
    @{N="Types de chiffrement"; E={$_."msDS-SupportedEncryptionTypes"}},
    PasswordLastSet

# Même chose pour les comptes d'ordinateur
Get-ADComputer -Filter 'ServicePrincipalName -like "*"' `
  -Properties "msDS-SupportedEncryptionTypes" |
  Where-Object { ([int]$_."msDS-SupportedEncryptionTypes" -band 24) -eq 0 } |
  Select-Object Name, @{N="Types de chiffrement"; E={$_."msDS-SupportedEncryptionTypes"}}
```

#### Comment corriger

**Pour les comptes avec d'anciens mots de passe :** Réinitialisez simplement le mot de passe. Cela génère de nouvelles clés AES :

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

**Pour les comptes auxquels il manque les paramètres de chiffrement AES :** Activez AES dans les types de chiffrement du compte :

```powershell
# Activer AES pour un compte spécifique (24 = AES-128 + AES-256)
Set-ADUser -Identity "svc_account" -Replace @{"msDS-SupportedEncryptionTypes" = 24}

# Pour un compte d'ordinateur
Set-ADComputer -Identity "server01" -Replace @{"msDS-SupportedEncryptionTypes" = 24}

# Correction en masse pour tous les comptes de service dépourvus d'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 activé pour $($_.SamAccountName)"
  }
```

> **Remarque :** L'activation d'AES n'est pas destructive : l'authentification existante continue de fonctionner. Cependant, testez avec les services critiques avant un déploiement en masse.

## A-LLMNR sans GPO

#### Ce que cela signifie

**LLMNR** (Link-Local Multicast Name Resolution) est un protocole que Windows utilise pour trouver d'autres ordinateurs sur le réseau lorsque DNS n'a pas la réponse. Il fonctionne en diffusant une question à toutes les machines à proximité : « Quelqu'un sait où se trouve `servername` ? »

Le problème est qu'un attaquant sur le même réseau peut **répondre à ces diffusions en se faisant passer pour le serveur cible**, en incitant la victime à envoyer ses identifiants à l'attaquant. Cela s'appelle un **empoisonnement LLMNR** attaque et c'est l'une des techniques les plus couramment utilisées lors des attaques sur un réseau interne.

LLMNR est un protocole hérité dont les réseaux modernes n'ont pas besoin (DNS gère tout). Il doit être désactivé via la stratégie de groupe.

#### Ce que l'analyse vérifie

La vérification AD recherche une **GPO activée et liée** qui désactive LLMNR en définissant la `EnableMulticast` valeur de registre `0`.

#### Pourquoi l'alerte peut persister

1. **La GPO existe mais n'est pas liée** à aucune unité d'organisation.
2. **La GPO est désactivée**, même si elle est liée.
3. **LLMNR a été désactivé manuellement** (via le registre ou `netsh`) mais pas via la stratégie de groupe. La vérification AD lit les fichiers GPO, pas les paramètres de la machine locale.

#### Comment diagnostiquer

```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)' - État : $($_.GpoStatus) - Contient le paramètre LLMNR"
  }
}
```

#### Comment corriger

```powershell
$gpoName = "Désactiver 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

# Lier à la racine du domaine pour que cela s'applique à tous les ordinateurs
New-GPLink -Name $gpoName `
  -Target (Get-ADDomain).DistinguishedName `
  -LinkEnabled Yes
```

Après avoir lié la GPO, exécutez `gpupdate /force` sur les machines ou attendre le prochain cycle d'actualisation de la stratégie de groupe (généralement 90 minutes).

## Foire aux questions

#### L'alerte s'affiche toujours après que j'ai appliqué le correctif. Pourquoi ?

Le scan AD ne s'exécute pas périodiquement. Après avoir appliqué un correctif, vous devez **exécuter le script à nouveau** pour que l'alerte disparaisse. Si l'alerte persiste après un nouveau scan, le correctif était probablement partiel. Reportez-vous à la section « Pourquoi l'alerte peut persister » de la vulnérabilité concernée. Assurez-vous de lire les détails de la vulnérabilité dans votre rapport, ils contiennent souvent des informations sur les actifs impactés.

#### Ai-je besoin des droits d'administrateur de domaine pour exécuter le scan ?

Certaines vulnérabilités (par ex. A-NoServicePolicy) nécessitent des autorisations élevées pour lire certains objets AD. Exécuter le scan avec un **compte d'administrateur de domaine** garantit que tous les objets sont visibles et évite les fausses alertes causées par des autorisations insuffisantes. Si ce n'est pas possible, vous pouvez tout de même exécuter le script en tant que simple utilisateur du domaine, bien que certaines vulnérabilités puissent apparaître en raison d'un manque de visibilité sur les objets AD.

#### J'ai corrigé une vulnérabilité mais une nouvelle est apparue. Est-ce normal ?

Oui. Certains correctifs peuvent révéler d'autres problèmes. Par exemple, l'installation de LAPS (corrigeant A-LAPS-Not-Installed) peut déclencher A-LAPS-Joined-Computers si les objets ordinateur disposent d'autorisations incorrectes. C'est attendu : traitez chaque alerte dans l'ordre de gravité.


---

# Agent Instructions: 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:

```
GET https://docs.stoik.io/help/help-center-fr/outils-de-prevention/what-is-the-active-directory-scan/ad-scan-vulnerability-remediation-guide.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
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.
