Aller au contenu
03 · DélégationPartie 2 sur 4Intermédiaire

Supprimer la délégation non contrainte des serveurs AD

Trouvez chaque compte hors DC approuvé pour la délégation non contrainte, identifiez ses dépendances et migrez vers la délégation contrainte ou RBCD sans interruption.

Florian Amette8 min de lecture

Un serveur approuvé pour la délégation non contrainte conserve une copie du TGT Kerberos de chaque utilisateur qui s'y authentifie. Quiconque obtient les droits d'administrateur local sur ce serveur peut extraire ces tickets et les réutiliser n'importe où dans le domaine, et grâce aux techniques de coercition d'authentification (PrinterBug, PetitPotam et consorts), un attaquant n'a même pas besoin d'attendre qu'un administrateur se connecte : il peut forcer un contrôleur de domaine à s'authentifier auprès de l'hôte et capturer le propre TGT du DC. À partir de là, DCSync n'est plus qu'à une commande.

Le guide de référence sur la délégation présente les trois modèles de délégation et la manière de les inventorier. Ce guide va plus loin sur la partie qui fait caler la plupart des projets : découvrir pourquoi un serveur porte l'indicateur, prouver si quelque chose l'utilise réellement et le remplacer par une alternative délimitée sans casser l'application qui l'a justifié il y a dix ans.

Mesurer : construire l'inventaire exact

L'indicateur correspond au bit 0x80000 (TRUSTED_FOR_DELEGATION, 524288 en décimal) de userAccountControl. Interrogez-le avec un filtre LDAP bit à bit pour capturer ordinateurs, utilisateurs et comptes de service administrés en une seule passe, puis excluez les DC accessibles en écriture par leur groupe principal (516).

PowerShell
Import-Module ActiveDirectory

$filter = '(userAccountControl:1.2.840.113556.1.4.803:=524288)'
Get-ADObject -LDAPFilter $filter -Properties samAccountName, objectClass, primaryGroupID,
        servicePrincipalName, operatingSystem, whenChanged, lastLogonTimestamp |
    Where-Object { $_.primaryGroupID -ne 516 } |
    Select-Object samAccountName, objectClass, operatingSystem, whenChanged,
        @{n='LastLogon';e={[datetime]::FromFileTime($_.lastLogonTimestamp)}},
        @{n='SPNs';e={$_.servicePrincipalName -join '; '}} |
    Sort-Object objectClass, samAccountName |
    Export-Csv .\unconstrained-delegation.csv -NoTypeInformation

Exécutez-la dans chaque domaine de la forêt : l'indicateur est défini par compte, et un domaine enfant hébergeant un serveur de fichiers oublié est tout aussi utile à un attaquant que la racine. Pour chaque résultat, consignez le responsable, les applications hébergées et la date de définition de l'indicateur. whenChanged n'est qu'un indice ; si vous auditez les événements 5136 sur les objets ordinateurs (voir l'audit et la détection AD), recherchez les modifications de userAccountControl sur cet objet pour trouver la date réelle et le compte à l'origine du changement.

Repérez aussi les comptes obsolètes. Un objet ordinateur désactivé ou disparu depuis longtemps qui porte l'indicateur est le gain le plus facile : rien ne peut en dépendre, donc effacez l'indicateur, puis désactivez ou supprimez l'objet via votre processus habituel de gestion du cycle de vie.

Auditer : prouver ce qui délègue réellement

Le fait que l'indicateur soit défini ne signifie pas que quelque chose en dépend. De nombreux serveurs l'ont reçu comme correctif générique lors d'une vieille séance de dépannage. Il vous faut des éléments des deux côtés.

Sur le serveur : les ouvertures de session avec emprunt d'identité de niveau délégation

Sous Windows Server 2016 et ultérieur, l'événement 4624 comporte un champ ImpersonationLevel. Lorsqu'un client transfère son TGT au serveur, l'ouverture de session est enregistrée avec le niveau d'emprunt d'identité Delegation (%%1840). Collectez ces événements pendant une à deux semaines, en incluant une fin de mois ou un cycle de traitements batch si l'application en a un.

PowerShell
# À exécuter sur le serveur candidat (ou à distance avec -ComputerName)
$xpath = "*[System[EventID=4624] and EventData[Data[@Name='ImpersonationLevel']='%%1840']]"
Get-WinEvent -LogName Security -FilterXPath $xpath -MaxEvents 5000 |
    ForEach-Object {
        $x = [xml]$_.ToXml()
        $d = @{}; $x.Event.EventData.Data | ForEach-Object { $d[$_.Name] = $_.'#text' }
        [PSCustomObject]@{
            Time        = $_.TimeCreated
            User        = "$($d.TargetDomainName)\$($d.TargetUserName)"
            LogonType   = $d.LogonType
            Process     = $d.ProcessName
            SourceIP    = $d.IpAddress
        }
    } | Group-Object User, Process | Sort-Object Count -Descending |
    Select-Object Count, Name

Les ouvertures de session de niveau délégation provenant d'administrateurs interactifs (RDP, console) ne prouvent pas un besoin applicatif ; ce sont simplement des administrateurs qui exposent leurs TGT. Ce sont les ouvertures de session réseau (type 3) traitées par w3wp.exe, sqlservr.exe ou un service métier qu'il faut approfondir.

Côté application : où va le second saut ?

Pour chaque processus qui reçoit des ouvertures de session déléguées, identifiez le service dorsal qu'il sollicite sous l'identité de l'utilisateur : un partage de fichiers, une instance SQL, une API HTTP, un autre annuaire LDAP. Interrogez le responsable de l'application, lisez la configuration (web.config avec <identity impersonate="true" />, sources de données SSRS réglées sur « Windows integrated security », serveurs liés SQL utilisant « Be made using the login's current security context ») et confirmez au besoin par une capture réseau. Cette étape produit une courte liste de SPN cibles, tels que cifs/fs01.corp.example.com ou MSSQLSvc/sql01.corp.example.com:1433.

Si le serveur ne présente aucune ouverture de session réseau de niveau délégation provenant de processus de service sur toute la période, il n'a très probablement aucun besoin de délégation.

Imposer : effacer ou remplacer l'indicateur

Serveurs sans dépendance

Effacez l'indicateur et passez à la suite. Configurer la délégation (définir l'indicateur ou modifier msDS-AllowedToDelegateTo) nécessite le privilège SeEnableDelegationPrivilege sur les contrôleurs de domaine, détenu par défaut uniquement par les Administrators des DC : effectuez donc ces modifications depuis une session d'administration Tier 0.

PowerShell
Set-ADComputer -Identity FS-LEGACY01 -TrustedForDelegation $false
# Pour un compte de service de type utilisateur
Set-ADAccountControl -Identity svc-legacyapp -TrustedForDelegation $false

Les tickets Kerberos existants sur le serveur conservent leurs TGT transférés jusqu'à leur expiration : prévoyez donc un redémarrage du serveur dans la même fenêtre de changement. Cela purge les tickets en cache de LSASS et garantit que rien ne continue discrètement à fonctionner sur d'anciens identifiants, ce qui masquerait une dépendance réelle jusqu'au lendemain.

Serveurs avec un vrai double saut

Remplacez la délégation non contrainte par un modèle délimité. Deux options s'offrent à vous, détaillées dans délégation contrainte et RBCD en toute sécurité :

  • La délégation Kerberos contrainte (KCD), configurée sur le compte frontal via msDS-AllowedToDelegateTo. Utilisez la variante « Kerberos only » dès lors que les utilisateurs atteignent le frontal en Kerberos ; la transition de protocole n'est nécessaire que s'ils s'authentifient par formulaire, par certificat ou en NTLM.
  • La délégation contrainte basée sur les ressources, configurée sur le service dorsal via msDS-AllowedToActOnBehalfOfOtherIdentity. Utile lorsque le service dorsal se trouve dans un autre domaine, ou lorsque son responsable doit contrôler qui peut lui déléguer.
PowerShell
# Option 1 : KCD, Kerberos uniquement, de WEB01 vers le partage de fichiers et l'instance SQL dont il a besoin
Set-ADComputer -Identity WEB01 -TrustedForDelegation $false
Set-ADComputer -Identity WEB01 -Add @{
    'msDS-AllowedToDelegateTo' = @(
        'cifs/fs01.corp.example.com', 'cifs/fs01',
        'MSSQLSvc/sql01.corp.example.com:1433'
    )
}

# Option 2 : RBCD, le service dorsal fait confiance au frontal
Set-ADComputer -Identity SQL01 -PrincipalsAllowedToDelegateToAccount (Get-ADComputer WEB01)

Si l'application s'exécute sous un compte de service de domaine plutôt que sous le compte d'ordinateur, placez la délégation sur ce compte, et profitez-en pour le migrer vers un gMSA (voir le durcissement des comptes de service). Une délégation configurée sur un compte utilisateur à mot de passe statique est un contrôle plus faible que le même paramètre sur un compte administré.

Appliquez la modification serveur par serveur, redémarrez, puis testez le double saut en tant qu'utilisateur ordinaire. Conservez l'ancienne valeur de userAccountControl dans la demande de changement, afin que le retour arrière tienne en une seule commande.

Dépendances inter-forêts

Depuis les mises à jour Windows de juillet 2019, la délégation de TGT à travers les approbations de forêt est désactivée par défaut (attribut d'approbation contrôlé par netdom trust <trust> /domain:<forest> /EnableTGTDelegation:No). Si une ancienne application reposait sur la délégation non contrainte pour des utilisateurs venant d'une forêt approuvée, elle a déjà été cassée ou repensée. Ne réactivez pas la délégation de TGT sur l'approbation pour la sauver ; utilisez plutôt la RBCD, qui fonctionne à travers les frontières d'approbation. Le guide sur le durcissement des approbations et des forêts traite du côté approbation.

Contrôles compensatoires pendant la migration

Certains serveurs prendront des mois à corriger. D'ici là, réduisez ce qu'ils peuvent récolter :

  • Ajoutez chaque compte d'administration Tier 0 et Tier 1 à Protected Users ou activez « Account is sensitive and cannot be delegated ». Leurs TGT ne sont alors jamais transférés au serveur.
  • Arrêtez le spouleur d'impression sur les contrôleurs de domaine et appliquez les mesures anti-coercition décrites dans bloquer la coercition d'authentification, ce qui supprime l'étape « forcer le DC à se connecter à moi ».
  • Traitez les serveurs restants comme du Tier 0 dans votre modèle d'administration : restreignez les administrateurs locaux et n'autorisez pas les comptes Tier 1 ou du support à y ouvrir une session.

Vérifier

Relancez la requête d'inventaire dans chaque domaine. Les seuls résultats doivent être les DC accessibles en écriture (déjà filtrés) et une liste d'exceptions explicitement documentée qui diminue chaque trimestre.

PowerShell
Get-ADObject -LDAPFilter '(userAccountControl:1.2.840.113556.1.4.803:=524288)' `
    -Properties primaryGroupID |
    Where-Object { $_.primaryGroupID -ne 516 } |
    Measure-Object | Select-Object Count

Confirmez ensuite que rien ne réintroduit l'indicateur. Activez l'audit des modifications de userAccountControl sur les objets ordinateurs et utilisateurs, et déclenchez une alerte sur tout événement 4742 (ordinateur modifié) ou 4738 (utilisateur modifié) dont le champ User Account Control affiche « 'Trusted For Delegation' - Enabled » sur un serveur qui n'est pas un DC. Les nouvelles constructions de serveurs doivent être contrôlées par la même requête dans votre chaîne de provisionnement ; c'est également l'un des contrôles d'une évaluation PingCastle, si bien que l'analyse régulière détecte les dérives.

Enfin, testez de bout en bout les applications migrées en tant qu'utilisateur standard, depuis un client sans tickets en cache, y compris les rapports planifiés ou les traitements batch qui s'exécutent la nuit.

Ce que cela casse

  • Les applications IIS avec authentification Windows et emprunt d'identité qui lisent un chemin UNC, interrogent SQL ou appellent une autre API protégée par Kerberos sous l'identité de l'utilisateur échouent au second saut, avec des erreurs d'« accès refusé » ou d'ouverture de session anonyme, tant que la KCD ou la RBCD n'est pas configurée avec les bons SPN.
  • Les sources de données SSRS et SharePoint réglées sur la sécurité intégrée Windows cessent de produire les rapports des utilisateurs lorsque le chemin de délégation est supprimé sans remplacement.
  • Les serveurs liés SQL Server utilisant le contexte de sécurité actuel de la connexion échouent avec « Login failed for user 'NT AUTHORITY\ANONYMOUS LOGON' ».
  • Les anciens serveurs d'impression, de télécopie et de gestion documentaire s'appuyaient parfois sur des TGT transférés pour écrire leurs sorties dans les partages personnels des utilisateurs ; cela se manifeste par des travaux en échec plutôt que par une erreur explicite.
  • Les applications qui enregistrent des SPN par adresse IP ou par alias : si les utilisateurs se connectent via un CNAME ou le nom d'un répartiteur de charge sans SPN correspondant, la KCD n'aidera pas tant que le SPN n'est pas corrigé, car le client se replie sur NTLM, et un chemin KCD « Kerberos only » ne peut pas déléguer une ouverture de session NTLM.

Pour aller plus loin : la thématique Délégation pour la série complète, régler ms-DS-MachineAccountQuota sur 0 pour fermer la voie de création de comptes d'ordinateurs qu'utilisent les attaquants pour abuser de la RBCD une fois la délégation non contrainte supprimée, et l'entrée du glossaire délégation non contrainte pour une définition courte à partager avec les responsables d'applications.

Questions fréquentes

Puis-je simplement décocher « Trust this computer for delegation to any service » et passer à autre chose ?

Techniquement oui, et sur la plupart des serveurs il ne se passe rien, car l'indicateur n'a jamais été nécessaire. Mais là où une application effectue réellement un double saut Kerberos, comme un site IIS qui lit un partage de fichiers ou interroge SQL Server sous l'identité de l'utilisateur, le second saut échoue immédiatement. Consacrez d'abord une semaine à collecter des éléments sur les ouvertures de session et les tickets pour savoir si le serveur délègue réellement, et préparez le remplacement par une délégation contrainte avant d'effacer l'indicateur.

La délégation non contrainte sur un compte de service utilisateur est-elle aussi dangereuse que sur un ordinateur ?

Oui. L'indicateur TRUSTED_FOR_DELEGATION fonctionne de la même manière sur les objets utilisateurs : tout service exécuté sous ce compte reçoit les TGT transférés par les utilisateurs qui s'y connectent. C'est souvent pire, car le mot de passe du compte de service est généralement statique, connu de plusieurs personnes et valide sur plusieurs hôtes. Quiconque récupère ce mot de passe ou compromet un hôte exécutant le service peut récolter les TGT transférés : traitez donc aussi ces comptes comme une non-conformité critique.

Les contrôleurs de domaine ont-ils besoin de la délégation non contrainte, et faut-il la leur retirer ?

Les contrôleurs de domaine accessibles en écriture sont approuvés pour la délégation non contrainte par conception, et il faut laisser ce réglage tel quel. De ce fait, un DC contraint de s'authentifier auprès d'un hôte non contraint compromis livre son propre TGT. Retirer l'indicateur de tous les autres serveurs, laisser le spouleur d'impression désactivé sur les DC et bloquer les chemins de coercition ferment ensemble cette voie. Les contrôleurs de domaine en lecture seule ne portent pas l'indicateur.

Supprimer la délégation non contrainte des serveurs AD

Guides associés

Tier 0 & accès à privilèges

Stratégies et silos d'authentification pour le Tier 0

Limitez où les administrateurs Tier 0 s'authentifient avec les stratégies et silos d'authentification AD : prérequis, revendications, durée du TGT, audit et application.

Avancé