Trouver et supprimer les mots de passe GPP (cpassword)
Trouver chaque cpassword des Group Policy Preferences dans SYSVOL, les sauvegardes et caches clients, identifier le compte exposé, le renouveler et empêcher son retour.
Les Group Policy Preferences permettaient autrefois aux administrateurs de définir via une GPO des mots de passe de comptes locaux, des identifiants de services, des comptes d'exécution de tâches planifiées, des identifiants de lecteurs mappés et des mots de passe de sources de données. Le mot de passe était stocké dans SYSVOL dans un attribut cpassword, chiffré en AES-256 avec une clé que Microsoft a publiée dans sa documentation de protocole. SYSVOL est lisible par tout utilisateur authentifié, et des outils comme Get-GPPPassword et les modules équivalents des frameworks d'attaque courants déchiffrent la valeur en une seconde. La charge utile habituelle est un mot de passe d'administrateur local partagé entre tous les postes de travail et serveurs, ce qui transforme un seul utilisateur victime d'hameçonnage en mouvement latéral sur l'ensemble du parc.
MS14-025 a fermé l'éditeur en mai 2014 mais a laissé en place les valeurs existantes, que l'on retrouve encore aujourd'hui lors des audits. Le pilier Stratégie de groupe et SYSVOL présente la recherche de base dans SYSVOL. Ce guide couvre le travail complet : tous les endroits où un cpassword peut se cacher, l'identification du compte exposé par chacun, son renouvellement correct, et la garantie qu'il ne reviendra pas.
Où se trouvent les valeurs cpassword
Les éléments de préférence pouvant contenir un mot de passe l'écrivent dans ces fichiers, à l'intérieur des dossiers Machine\Preferences ou User\Preferences d'une GPO :
| Fichier | Type de préférence | Attribut de compte à lire |
|---|---|---|
Groups\Groups.xml | Local Users and Groups | userName, newName |
Services\Services.xml | Services | accountName |
ScheduledTasks\ScheduledTasks.xml | Scheduled Tasks | runAs |
Drives\Drives.xml | Drive Maps | userName |
DataSources\DataSources.xml | Data Sources | username |
Printers\Printers.xml | Printers | username |
Les mêmes fichiers XML existent aussi en dehors du dossier Policies actif :
- Les sauvegardes de GPO réalisées avec la GPMC ou
Backup-GPO, souvent sur des partages de fichiers d'administration ou dans des dépôts de contrôle des changements. - Les caches côté client : chaque client conserve une copie du XML de préférences appliqué sous
%ProgramData%\Microsoft\Group Policy\History\{GUID}\(paramètres ordinateur) et%LocalAppData%\Microsoft\Group Policy\History\(paramètres utilisateur), copie qui se retrouve aussi dans les modèles de VM et les images disque. - Les copies obsolètes de SYSVOL laissées par une migration de FRS vers DFSR ou par des copies manuelles sur les DC (
SYSVOL.bak,SYSVOL_old). - Les scripts dans
NETLOGONet les dossiers de scripts des GPO, qui ne contiennent pas de cpassword mais souvent des identifiants en clair pour les mêmes comptes.
Mesurer : trouver chaque occurrence
Analysez le XML plutôt que de faire un simple grep, afin d'extraire le compte auquel appartient chaque valeur. Le script signale la présence de la valeur, jamais la valeur elle-même.
function Find-GppCpassword {
param([Parameter(Mandatory)] [string[]] $Path)
Get-ChildItem -Path $Path -Recurse -Include Groups.xml, Services.xml, ScheduledTasks.xml,
Drives.xml, DataSources.xml, Printers.xml -ErrorAction SilentlyContinue |
ForEach-Object {
$file = $_.FullName
Select-Xml -Path $file -XPath '//*[@cpassword]' | ForEach-Object {
$n = $_.Node
if ($n.cpassword) {
[pscustomobject]@{
File = $file
GpoGuid = if ($file -match '\{([0-9A-Fa-f-]{36})\}') { $Matches[1] }
Item = $n.ParentNode.name
Account = @($n.userName, $n.accountName, $n.runAs, $n.username, $n.newName) |
Where-Object { $_ } | Select-Object -First 1
Changed = $n.ParentNode.changed
}
}
}
}
}
$dns = (Get-ADDomain).DNSRoot
$hits = Find-GppCpassword -Path "\\$dns\SYSVOL\$dns\Policies", 'D:\GPOBackups'
$hits | ForEach-Object {
$gpo = if ($_.GpoGuid) { Get-GPO -Guid $_.GpoGuid -ErrorAction SilentlyContinue }
$_ | Add-Member -NotePropertyName GpoName -NotePropertyValue $gpo.DisplayName -PassThru
} | Format-Table GpoName, Item, Account, Changed, File -AutoSizeLes attributs vides cpassword="" sont ignorés, car ils ne contiennent aucun secret. Un résultat sans GpoName résoluble désigne généralement une sauvegarde ou un dossier GPT orphelin dont le GPC a été supprimé ; les dossiers orphelins restent lisibles par tous et doivent aussi être supprimés.
Recherchez les copies résiduelles de SYSVOL sur chaque DC, ainsi que les copies en cache sur un échantillon de clients et sur vos images de référence :
# Sur chaque DC
Get-ChildItem C:\Windows -Directory -Filter 'SYSVOL*' | Select-Object FullName
# Sur un client ou une image montée
Find-GppCpassword -Path "$env:ProgramData\Microsoft\Group Policy\History"Auditer : déterminer ce que chaque valeur expose
Pour chaque résultat, répondez à trois questions avant de toucher à la GPO :
- Quel compte ? Un élément
Groups.xmlavecuserName="Administrator"(ou un compte intégré renommé vianewName) expose l'administrateur local de chaque ordinateur dans le périmètre de la GPO. Un élémentServices.xmlouScheduledTasks.xmlexpose généralement un compte de service de domaine. - Où s'est-il appliqué ? Vérifiez les liaisons et le filtrage de sécurité de la GPO avec
Get-GPOReport -Guid <id> -ReportType Html. Un mot de passe d'administrateur local appliqué aussi bien aux serveurs qu'aux postes de travail signifie que le même identifiant fonctionne sur les deux tiers. - Est-il toujours valide ? Pour les comptes de domaine, comparez
pwdLastSetà l'horodatagechangedde l'élément. Si le mot de passe a été défini pour la dernière fois avant ou à cette date, la valeur de SYSVOL est presque certainement celle en vigueur.
Get-ADUser svc-backup -Properties pwdLastSet, lastLogonTimestamp, memberOf |
Select-Object Name, @{n='PwdLastSet';e={[datetime]::FromFileTime($_.pwdLastSet)}},
@{n='LastLogon';e={[datetime]::FromFileTime($_.lastLogonTimestamp)}}, memberOfPour mesurer le rayon d'impact d'une entrée d'administrateur local, comptez les ordinateurs dans le périmètre de la GPO. La requête ci-dessous parcourt chaque UO où la GPO est liée ; adaptez-la si la GPO est aussi filtrée par sécurité sur un groupe.
$guid = '<GpoGuid from the scan>' # par ex. 6AC1786C-016F-11D2-945F-00C04FB984F9
Get-ADObject -LDAPFilter "(gPLink=*$guid*)" -SearchBase (Get-ADDomain).DistinguishedName |
ForEach-Object {
[pscustomobject]@{
LinkedTo = $_.DistinguishedName
Computers = (Get-ADComputer -SearchBase $_.DistinguishedName -Filter * | Measure-Object).Count
}
}Un décompte qui inclut à la fois des serveurs et des postes de travail vous indique que le mot de passe faisait le pont entre les tiers : quiconque l'a récupéré sur un poste de travail pouvait ouvrir une session sur des serveurs avec le même compte. Consignez ce fait dans le constat, car il détermine quelle part du parc vous devez considérer comme potentiellement accédée.
Si le compte exposé est privilégié (membre d'un groupe d'administration, ou compte de service disposant de droits sur des systèmes Tier 0), traitez la situation comme un incident potentiel : examinez son historique d'ouvertures de session sur les DC (événements 4624 et 4768) avant que le renouvellement ne détruise les preuves de réutilisation.
Imposer : remplacer, supprimer, renouveler
L'ordre compte. Remplacez d'abord le mécanisme, sinon la suppression de la préférence casse ce qu'elle faisait. Planifiez le travail sous forme d'un changement par compte exposé plutôt que d'un changement par GPO : le même compte de service apparaît souvent dans plusieurs GPO, et le renouveler alors que l'une d'elles pousse encore l'ancien mot de passe signifie qu'à la prochaine actualisation de la stratégie de groupe, soit le service casse, soit, pour les comptes locaux, le mot de passe est réinitialisé à la valeur exposée.
- Mots de passe d'administrateur local → déployez Windows LAPS sur les mêmes UO, vérifiez que les mots de passe sont bien sauvegardés, puis supprimez l'élément Local Users and Groups. LAPS renouvelle immédiatement le mot de passe local sur chaque machine, ce qui constitue aussi votre étape de renouvellement.
- Comptes de service et de tâches planifiées → passez à un gMSA lorsque l'application le permet. Les tâches planifiées peuvent s'exécuter sous un gMSA (
New-ScheduledTaskPrincipal -UserId 'CORP\svc-task$' -LogonType Password) ou en tant que SYSTEM si la tâche n'a besoin que de droits locaux. - Mappages de lecteurs et imprimantes avec identifiants → supprimez l'identifiant ; l'accès doit utiliser l'identité propre de l'utilisateur, avec des autorisations de partage qui accordent ce dont il a besoin.
- Sources de données → utilisez l'authentification intégrée ou un coffre de secrets géré par l'application.
Supprimez ensuite l'élément. Utilisez l'éditeur de gestion des stratégies de groupe (Computer ou User Configuration > Preferences > le nœud concerné > supprimer l'élément) plutôt que de modifier le XML à la main, afin que le numéro de version de la GPO s'incrémente et que les clients traitent le changement. Si la GPO ne contient rien d'autre, déliez-la et supprimez-la après l'avoir sauvegardée dans un emplacement à accès contrôlé.
Enfin, renouvelez. Pour les comptes de domaine, réinitialisez le mot de passe avec une nouvelle valeur aléatoire et mettez à jour chaque consommateur ; si vous soupçonnez que le compte a été utilisé par un attaquant, examinez aussi ce à quoi il avait accès au lieu de considérer la réinitialisation comme la fin de l'affaire. Pour les comptes locaux non couverts par LAPS, renouvelez-les sur chaque machine du périmètre. Supprimer une préférence ne rétablit ni ne modifie jamais le mot de passe qu'elle a déjà défini.
Supprimez ou assainissez les sauvegardes de GPO contenant ces valeurs, supprimez les copies résiduelles de SYSVOL, et reconstruisez ou nettoyez les images de référence qui ont capturé l'historique côté client.
Vérifier
Relancez Find-GppCpassword sur SYSVOL, les emplacements de sauvegarde et un échantillon de clients après leur prochaine actualisation de la stratégie de groupe ; tous doivent ne rien renvoyer. Pour les comptes de domaine, vérifiez que pwdLastSet est postérieur à la date de renouvellement. Pour les machines couvertes par LAPS, vérifiez qu'un mot de passe LAPS existe et a été défini récemment :
Get-LapsADPassword -Identity WS0142 | Select-Object ComputerName, PasswordUpdateTime, ExpirationTimestampAjoutez l'analyse de SYSVOL à une tâche planifiée afin qu'une sauvegarde restaurée ou une ancienne GPO importée soit détectée dans la journée. PingCastle vérifie aussi la présence de mots de passe GPP et signalera donc une régression lors de votre évaluation périodique.
Un leurre délibéré constitue une couche de détection utile : un Groups.xml dans une GPO non liée, avec un cpassword pour un compte honeytoken qui n'est jamais utilisé légitimement. Toute tentative d'authentification pour ce compte (4625, 4771 ou 4776 sur les DC) signifie que quelqu'un collecte le contenu de SYSVOL.
Ce qui casse
- Supprimer un élément Local Users and Groups avant le déploiement de LAPS laisse les machines avec un mot de passe d'administrateur local connu et non géré. Déployez LAPS d'abord.
- Renouveler un compte de service de domaine casse chaque service, tâche et application qui détient encore l'ancien mot de passe. Inventoriez les consommateurs à partir des données d'ouverture de session 4624/4768 avant la réinitialisation.
- Supprimer les identifiants des mappages de lecteurs provoque des refus d'accès pour les utilisateurs dont les propres comptes n'ont pas les autorisations de partage ; corrigez d'abord les ACL des partages.
- Supprimer les anciennes sauvegardes de GPO vous prive de la possibilité de restaurer ces GPO dans leur état d'origine. Conservez une sauvegarde assainie si vous avez besoin de l'historique.
- La GPO leurre sera signalée par vos propres outils d'évaluation ; documentez-la pour qu'un collègue ne la « corrige » pas.
Pour aller plus loin : le thème Stratégie de groupe & SYSVOL, auditer les autorisations des GPO, et une stratégie de mots de passe qui fonctionne pour les contrôles côté compte qui limitent les dégâts de tout identifiant divulgué.
Questions fréquentes
Si je supprime le cpassword de SYSVOL, suis-je protégé ?
Non. Tout utilisateur authentifié a pu lire SYSVOL aussi longtemps que la valeur s'y trouvait, souvent pendant des années : considérez donc que le mot de passe est connu. Supprimer l'élément de préférence met fin à une nouvelle exposition, mais ne change le mot de passe sur aucun des systèmes où il a été appliqué. Renouvelez l'identifiant sur chaque machine ou compte qui l'utilise, et recherchez des copies dans les sauvegardes de GPO, les caches clients et les images.
MS14-025 a-t-il supprimé les valeurs cpassword existantes ?
Non. MS14-025 (KB2962486, mai 2014) a supprimé la possibilité de définir des mots de passe dans les boîtes de dialogue Group Policy Preferences concernées : les administrateurs ne peuvent donc plus en créer de nouveaux via l'éditeur. Il n'a pas touché aux fichiers XML déjà présents dans SYSVOL et n'empêche pas quelqu'un d'importer une ancienne sauvegarde de GPO qui en contient. Les valeurs existantes doivent être trouvées et supprimées manuellement.
Par quoi remplacer les mots de passe d'administrateur local GPP ?
Par Windows LAPS. Il définit un mot de passe unique et aléatoire pour l'administrateur intégré (ou un compte nommé) sur chaque machine, le renouvelle selon un calendrier et le stocke dans AD ou Entra ID avec un accès contrôlé par UO et, en option, chiffré. Il supprime entièrement le problème du mot de passe partagé, qui est précisément ce qui rendait les comptes d'administrateur local GPP si dangereux.
Trouver et supprimer les mots de passe GPP (cpassword)