Nettoyer le SIDHistory après une migration AD
Trouver, évaluer et supprimer sans risque le sIDHistory hérité des migrations : SID dangereux, retraitement des ACL, suppression par étapes, limites du retour arrière.
sIDHistory existe pour une bonne raison : lorsqu'un utilisateur ou un groupe passe d'un domaine à un autre, il conserve ses anciens SID afin que les ressources encore autorisées pour l'ancienne identité continuent de fonctionner. En pratique, les migrations se terminent, les domaines sources sont décommissionnés, et les anciens SID restent sur des milliers d'objets pendant dix ans. Chacune de ces valeurs est une identité supplémentaire portée dans le jeton de l'utilisateur, et un endroit où un attaquant disposant de droits suffisants peut dissimuler des privilèges : une valeur SID history pointant vers Domain Admins accorde les droits Domain Admins sans apparaître dans la liste des membres du groupe.
L'article pilier sur les approbations et les frontières de forêt traite du filtrage de SID history au niveau de l'approbation. Ce guide porte sur les objets eux-mêmes : trouver chaque valeur sIDHistory, distinguer les entrées dangereuses des reliquats de migration, retraiter les autorisations des ressources pour que les anciens SID ne soient plus nécessaires, supprimer les valeurs par étapes, et surveiller pour que de nouvelles valeurs n'apparaissent pas à votre insu.
Avant de toucher à quoi que ce soit, mettez-vous d'accord sur les responsabilités. Le nettoyage de SID history concerne à la fois les équipes identité, serveurs de fichiers, applications et sécurité, et ses échecs sont visibles par les utilisateurs finaux. Désignez un responsable du programme, un contact par application et un plan de communication qui indique aux utilisateurs pilotes quoi signaler et à qui.
Pourquoi un SID history résiduel est un risque
- Privilèges cachés. Les jetons incluent SID history : un utilisateur standard dont le
sIDHistorycontient le SID d'un groupe privilégié en est de fait membre. Les revues d'appartenance aux groupes,adminCountet la plupart des rapports d'administration ne le montrent pas. - Persistance. L'ajout de SID history passe normalement par l'API de migration avec des droits Domain Admin dans le domaine cible, mais un attaquant ayant déjà atteint le Tier 0 peut l'écrire directement avec des outils comme Mimikatz ou DSInternals. La valeur survit aux réinitialisations de mot de passe et passe facilement inaperçue lors d'une réponse à incident.
- Gonflement des jetons. Les utilisateurs cumulant de nombreux anciens SID et de nombreux groupes peuvent dépasser les limites de taille des jetons Kerberos, ce qui provoque des échecs d'authentification intermittents.
- Exposition de l'approbation. Si vous maintenez SID history fonctionnel à travers une approbation, vous devez laisser le filtrage des SID assoupli, ce qui affaiblit l'approbation elle-même. Voir Filtrage des SID et authentification sélective.
Mesurer : inventorier chaque valeur
$forestSids = (Get-ADForest).Domains | ForEach-Object { (Get-ADDomain $_).DomainSID.Value }
Get-ADObject -LDAPFilter "(sIDHistory=*)" -Properties sIDHistory, objectClass, samAccountName, whenChanged |
ForEach-Object {
$obj = $_
foreach ($sid in $obj.sIDHistory) {
$prefix = $sid.AccountDomainSid.Value
[pscustomobject]@{
Object = $obj.samAccountName
Class = $obj.objectClass
HistorySid = $sid.Value
SourceDomain = $prefix
Rid = [int]($sid.Value.Split('-')[-1])
Builtin = $sid.Value.StartsWith('S-1-5-32-')
SameForest = $forestSids -contains $prefix
WhenChanged = $obj.whenChanged
}
}
} | Export-Csv .\sidhistory-inventory.csv -NoTypeInformationExécutez ce script dans chaque domaine de la forêt. Le CSV constitue votre référence et la preuve dont vous aurez besoin plus tard, puisque les valeurs supprimées ne peuvent pas être simplement réécrites.
Regroupez les résultats par SourceDomain. Vous verrez généralement un ou deux anciens SID de domaine, un par migration historique, avec le nombre d'objets concernés. Associez chaque préfixe à un domaine source connu grâce aux archives de migration ; si le domaine source existe encore et qu'une approbation est en place, Translate() sur un SID échantillon le résoudra.
Auditer : trier par niveau de risque
Classez chaque valeur dans l'une des trois catégories suivantes.
Critique : à traiter comme un incident
SameForestvautTrue. Une migration légitime copie des SID du domaine source vers le domaine cible ; une valeur provenant de votre propre forêt, et surtout du même domaine, n'est pas un artefact de migration.Ridest inférieur à 1000, quel que soit le domaine, en particulier 500, 512, 518 et 519, ouBuiltinvautTrue, en particulierS-1-5-32-544(Administrators). Les SID intégrés n'ont pas de préfixe de domaine, doncSourceDomainest vide pour eux. Des RID et SID privilégiés intégrés dans SID history sont une technique de persistance classique.- Des valeurs sur des objets dont le
whenChangedest bien postérieur à la dernière migration connue.
Ne vous contentez pas de les supprimer. Capturez l'objet et ses métadonnées (repadmin /showobjmeta donne le DC d'origine et l'heure de la modification de sIDHistory), et recherchez dans vos journaux d'événements les événements 4765 et 4766 autour de ce moment. Supprimez ensuite la valeur et renouvelez les identifiants du compte.
Héritées avec des dépendances actives
Valeurs provenant d'un domaine source qui a encore des ressources autorisées avec ses SID : serveurs de fichiers migrés avec leurs autorisations intactes, applications avec des ACL sur les anciens SID, connexions SQL. Il faut d'abord retraiter leurs autorisations.
Héritées sans dépendances
Valeurs provenant d'un domaine source décommissionné depuis des années et dont les ressources ont été reconstruites. C'est généralement la majorité, et leur suppression est sûre après un pilote.
Appliquer : retraiter les autorisations avant la suppression
L'objectif est de remplacer chaque ACE qui référence un ancien SID par une ACE référençant le SID actuel du même principal. Outils :
- La traduction de sécurité d'ADMT (assistant Translate Objects) fonctionne si ADMT et sa base de migration existent encore.
icacls /substituteremplace un SID par un autre dans les ACL NTFS :icacls D:\Shares /substitute <OldSID> <NewSID> /t /c. Utilisez d'abord/savepour conserver une copie restaurable des ACL.- Les autorisations applicatives (connexions SQL associées à d'anciens SID, autorisations de boîtes aux lettres Exchange, autorisations de sites SharePoint) nécessitent leurs propres outils.
Identifiez ce qui référence d'anciens SID sur les serveurs de fichiers, avant et après la traduction :
$oldPrefix = "S-1-5-21-1111111111-2222222222-3333333333" # SID de l'ancien domaine source
Get-ChildItem D:\Shares -Directory -Recurse -ErrorAction SilentlyContinue |
ForEach-Object {
$rules = (Get-Acl $_.FullName).GetAccessRules($true, $true, [Security.Principal.SecurityIdentifier])
$hits = $rules | Where-Object { $_.IdentityReference.Value -like "$oldPrefix-*" }
if ($hits) { [pscustomobject]@{ Path = $_.FullName; Count = @($hits).Count } }
}Une ACE pour un principal dont le seul lien avec l'ancien SID est SID history s'affiche dans l'interface graphique sous le nom du compte actuel : c'est pourquoi les analyses d'ACL doivent porter sur les SID bruts et non sur les noms affichés. Incluez aussi les ACL des objets AD : les délégations sur les UO référencent parfois des groupes migrés par leur ancien SID. Le guide d'audit des ACL explique comment les extraire.
Appliquer : suppression par étapes
Procédez par vagues, en commençant par un pilote d'utilisateurs IT, puis les services, et les groupes en dernier (le SID history d'un groupe affecte tous ses membres).
# Supprimer tout le SID history d'un objet, en journalisant ce qui a été supprimé
$user = Get-ADUser "jdoe" -Properties sIDHistory
$user.sIDHistory | ForEach-Object { "{0};{1}" -f $user.SamAccountName, $_.Value } |
Add-Content .\sidhistory-removed.log
foreach ($sid in $user.sIDHistory) {
Set-ADUser $user -Remove @{ sIDHistory = $sid.Value }
}
# Supprimer uniquement les valeurs d'un ancien domaine donné, pour un groupe pilote
$oldPrefix = "S-1-5-21-1111111111-2222222222-3333333333"
Get-ADGroupMember "SIDH-Pilot" | Get-ADUser -Properties sIDHistory |
ForEach-Object {
$u = $_
$u.sIDHistory | Where-Object { $_.AccountDomainSid.Value -eq $oldPrefix } |
ForEach-Object { Set-ADUser $u -Remove @{ sIDHistory = $_.Value } }
}Pour les groupes, utilisez Set-ADGroup avec la même syntaxe -Remove. Les utilisateurs prennent en compte la modification à leur prochaine ouverture de session, lorsqu'un nouveau TGT est émis ; demandez aux utilisateurs pilotes de se déconnecter puis de se reconnecter, ou attendez l'expiration des tickets. Laissez chaque vague en place pendant un cycle métier complet, clôtures mensuelles comprises, avant de passer à la suivante.
Le retour arrière est limité. Vous ne pouvez pas réécrire sIDHistory avec Set-ADUser -Add. Les options sont de relancer une migration avec ADMT (uniquement si le domaine source existe encore) ou d'effectuer une restauration faisant autorité des objets concernés depuis une sauvegarde. C'est pourquoi le retraitement des autorisations et les pilotes passent en premier.
Planifier le programme de façon réaliste
Dans un grand environnement, le nettoyage prend des mois, pas des jours, et l'ordre compte :
- Semaine 1 : les constats critiques. Les SID de la même forêt et les RID privilégiés sont traités immédiatement comme des constats de sécurité, indépendamment du reste.
- Mois 1 : les éléments factuels. Terminez l'inventaire dans chaque domaine, identifiez chaque domaine source et analysez les ACL des serveurs de fichiers et des bases applicatives. Estimez le nombre d'ACE à traduire par domaine source : c'est ce nombre, et non le nombre d'objets, qui détermine l'effort.
- Mois 2-3 : la traduction. Retraitez d'abord les serveurs de fichiers, qui portent la plupart des ACE sur d'anciens SID, puis les applications. Conservez des exports d'ACL avant et après.
- Mois 3-6 : les vagues de suppression. Pilote, services, puis groupes, avec au moins une clôture mensuelle entre chaque vague.
- Enfin : l'approbation. Une fois qu'il ne reste plus aucune valeur provenant d'un domaine source approuvé, réactivez le filtrage des SID sur cette approbation, ou supprimez-la entièrement si elle n'existait que pour la migration.
Suivez l'avancement avec deux indicateurs remontés à la direction : le nombre d'objets possédant encore un sIDHistory et le nombre d'ACE référençant encore d'anciens SID. Les deux doivent tomber à zéro ; une courbe qui stagne signifie généralement qu'une équipe applicative est bloquée et a besoin d'aide plutôt que d'une relance.
Vérifier et surveiller
# Valeurs restantes, par domaine source
Import-Csv .\sidhistory-inventory.csv | Group-Object SourceDomain | Select-Object Name, Count
(Get-ADObject -LDAPFilter "(sIDHistory=*)").Count
# Reste-t-il du SID history du même domaine ? Doit être zéro
$domainSid = (Get-ADDomain).DomainSID.Value
Get-ADObject -LDAPFilter "(sIDHistory=*)" -Properties sIDHistory |
Where-Object { $_.sIDHistory.AccountDomainSid.Value -contains $domainSid } | Select-Object NamePour la détection continue, créez des alertes sur :
- 4765 (SID History was added to an account) et 4766 (an attempt to add SID History failed). En dehors d'une migration planifiée, tout 4765 est un incident.
- 5136 sur l'attribut
sIDHistory, ce qui nécessite l'audit Directory Service Changes et une SACL sur les objets utilisateur et groupe. - 4738 et 4742 lorsque le champ SID History change.
Des outils comme BloodHound et PingCastle signalent également les SID history pointant vers des groupes privilégiés ; intégrez ces contrôles à votre évaluation récurrente.
Ce que cela casse
- L'accès aux ressources encore autorisées avec d'anciens SID : partages de fichiers, imprimantes, rôles applicatifs et connexions SQL renvoient un accès refusé aux utilisateurs dont le SID history a été supprimé avant la traduction.
- La suppression du SID history d'un groupe affecte tous ses membres d'un coup ; une seule ACL oubliée peut bloquer tout un service.
- Les accès à travers une approbation qui reposaient discrètement sur SID history via une approbation assouplie cessent de fonctionner ; c'est d'ailleurs le moment où vous pouvez réactiver le filtrage.
- Relancer ADMT pour un retour arrière nécessite le domaine source, l'approbation et la base de migration, qui ont souvent disparu.
- Les scripts et rapports qui résolvaient les anciens SID en noms via SID history affichent désormais des SID bruts.
Pour aller plus loin : la thématique Approbations & conception de forêt, l'article pilier sur l'audit et la détection pour la stratégie d'audit à l'origine des événements 4765 et 5136, et la gestion des chemins d'attaque pour suivre les privilèges cachés en parallèle des chemins d'ACL.
Questions fréquentes
Peut-on restaurer sIDHistory après l'avoir supprimé ?
Pas en réécrivant simplement l'ancienne valeur. Active Directory permet aux administrateurs de supprimer des valeurs sIDHistory, mais n'autorise leur ajout que via l'API de migration utilisée par ADMT et les outils similaires, ce qui suppose que le domaine source existe toujours, ou via une restauration faisant autorité de l'objet depuis une sauvegarde. Considérez la suppression comme pratiquement irréversible et terminez la traduction des ACL et les tests avant de supprimer quoi que ce soit.
Quelles valeurs sIDHistory sont les plus dangereuses ?
Toute valeur qui correspond à un SID de votre propre domaine ou de votre forêt, en particulier se terminant par un RID privilégié comme 500 (Administrator), 512 (Domain Admins), 518 (Schema Admins), 519 (Enterprise Admins), ou le SID intégré S-1-5-32-544 (Administrators), qui n'a pas de préfixe de domaine. Une migration légitime ajoute des SID du domaine source, jamais du domaine cible lui-même : un SID history du même domaine est donc soit une grave erreur, soit une porte dérobée de persistance, et doit être traité comme un incident.
Comment savoir si quelque chose utilise encore les anciens SID ?
Analysez les emplacements qui stockent des SID dans des listes de contrôle d'accès : autorisations NTFS et de partage sur les serveurs de fichiers, ACL du registre et des services, connexions SQL Server, autorisations Exchange et SharePoint, et ACL des objets AD. Toute ACE qui référence le préfixe de SID de l'ancien domaine dépend encore de SID history. Une fois que les analyses n'en trouvent plus et qu'une suppression pilote ne génère aucune plainte d'accès pendant un cycle métier complet, la suppression est sûre.
Nettoyer le SIDHistory après une migration AD