Menu

english flag

Délégation Kerberos - Fonctionnement

Délégation Kerberos - Fonctionnement

Au sein d’un Active Directory, des services peuvent être utilisés par des utilisateurs. Il arrive parfois que ces services doivent en contacter d’autres, au nom de l’utilisateur, comme un service web pourrait avoir besoin de contacter un serveur de fichiers. Afin d’autoriser un service à accéder à un autre service au nom de l’utilisateur, une solution a été mise en place (introduite à partir de Windows Server 2000) pour répondre à ce besoin : La délégation Kerberos.

Principe de la délégation

Pour comprendre le principe de la délégation Kerberos, prenons un exemple concret. Une machine héberge un service Web qui, via une jolie interface, permet à un utilisateur d’accéder à son dossier personnel, hébergé sur un serveur de fichiers. Nous sommes donc dans la situation suivante :

Etat actuel

Le serveur Web est en frontal, et c’est lui qui va chercher les informations à la place de l’utilisateur sur le serveur de fichiers afin d’afficher le contenu d’un dossier, par exemple.

Cependant, le serveur web ne sait pas ce qui appartient à l’utilisateur sur le serveur de fichiers. Ce n’est pas son rôle à lui de décortiquer le PAC de l’utilisateur pour faire une demande spécifique au serveur de fichiers. C’est là qu’entre en jeu la délégation. Ce mécanisme permet au serveur web de prendre la place de l’utilisateur, et de s’authentifier au nom de celui-ci auprès du serveur de fichiers. Ainsi, du point de vue du serveur de fichiers, c’est l’utilisateur qui fait la demande, et le serveur de fichiers va pouvoir vérifier les droits de cet utilisateur, puis renvoyer les informations auxquelles ce compte a accès. C’est de cette manière que le serveur web peut ensuite afficher ces informations dans une jolie interface.

Impersonation

Constrained & Unconstrained Delegation

La possibilité de relayer des identifiants peut être donnée à une machine ou un utilisateur de service, c’est à dire qui possède au moins un attibut SPN.

Il existe aujourd’hui trois manières d’autoriser une machine ou un compte de service de prendre la place d’un utilisateur pour communiquer avec un ou plusieurs autre(s) service(s) : La Unconstrained Delegation, la Constrained Delegation et la Resource Based Constrained Delegation.

Kerberos Unconstrained Delegation

Dans le cas d’une Unconstrained Delegation, le serveur ou le compte de service qui se voit attribuer ce droit est en mesure de se faire passer pour l’utilisateur pour communiquer avec n’importe quel service sur n’importe quelle machine.

C’est historiquement le seul choix qu’il y avait lors de l’instauration du principe de délégation, mais il a été complété par le principe de la Constrained Delegation.

Unconstrained Delegation

Voici un exemple, dans mon lab, d’une machine qui est en Unconstrained Delegation :

Unconstrained Delegation

Kerberos Constrained Delegation

Si une machine ou un compte de service possède le flag Constrained Delegation, alors une liste de services autorisés sera associée à ce droit. Par exemple, dans le cas du serveur web de l’introduction, la machine hébergeant le serveur web aura le drapeau Constrained Delegation avec comme précision que ce serveur ne peut relayer les informations de l’utilisateur qu’au service CIFS du serveur SERVEUR01.

Constrained Delegation

C’est donc le serveur relayant les informations de l’utilisateur qui possède l’information des services (SPN) autorisés.

En d’autres termes, le serveur en frontal va dire “je suis autorisé à m’authentifier en tant que l’utilisateur auprès de cette liste de SPN : […]”.

Dans mon lab, le serveur web est WEB-SERVER-01 et celui qui possède le partage de fichiers est WEB-SERVER-02. Voici donc à quoi ressemble la liste des services pour lesquels WEB-SERVER-01 peut se faire passer pour l’utilisateur :

Delegation CIFS

Resource Based Kerberos Constrained Delegation - RBCD

Enfin, nous avons le cas de la Resource Based Constrained Delegation (RBCD). Apparue avec Windows Server 2012, cette solution permet de palier à quelques problèmes liés à la délégation contrainte classique (Responsabilité, délégation inter-domaines, …). Sans trop aller dans les détails, la responsabilité de la délégation est déplacée. Alors que dans délégation contrainte, c’est au niveau du serveur qui délègue qu’on indique la liste des SPN autorisés, dans le cas du RBCD, c’est au niveau des services finaux qu’on indique la liste des services qui peuvent communiquer avec eux via délégation. Ainsi, le schéma est le suivant :

Resource Based Constrained Delegation

La responsabilité est déplacée, c’est au niveau de la ressource qui reçoit les connexions avec délégation que se trouve l’information de si oui ou non cette délégation est acceptée.

En d’autres termes, c’est la ressource finale qui dit “j’autorise cette liste de comptes […] à s’authentifier chez moi au nom d’un utilisateur”.

Détails techniques

Maintenant que le principe est compris (du moins je l’espère), nous allons détailler un peu ce process. Concrètement, comment est-ce qu’une machine ou un compte peut se faire passer pour un utilisateur auprès d’une ressource ? C’est ce que nous allons voir maintenant. Les détails entre les différentes techniques sont relativement différents, c’est pourquoi chacune d’entre elle sera expliquée séparemment. Accrochez vous, it’s gonna get dirty.

Kerberos Unconstrained Delegation

Comme nous l’avons vu, dans ce cas, le serveur ou le compte de service peut s’authentifier au nom de l’utilisateur auprès de n’importe quel autre service. Pour que cela soit possible, il faut deux prérequis :

  • Le premier est que le compte qui veut déléguer une authentification possède le drapeau TRUSTED_FOR_DELEGATION dans la liste des drapeaux UAC - User Account Control. Pour pouvoir changer cette information sur un compte de service, il faut avoir le droit SeEnableDelegationPrivilege qui est la plupart du temps seulement existant pour les administrateurs de domaine. Voici comment ce drapeau est placé sur le compte (machine ou compte de service):

Unconstrained Delegation

Une fois placé, nous pouvons voir les drapeaux UAC et constater que TRUSTED_FOR_DELEGATION est bien présent.

Unconstrained Delegation UAC

  • Le deuxième est que le compte utilisateur qui va être relayé soit effectivement “relayable”. Pour cela, il ne faut pas faut que le drapeau NOT_DELEGATED soit positionné. Par défaut, aucun compte de l’AD n’a ce drapeau de positionné, ils sont donc tous “relayables”.

Not delegated flag unset

Concrètement, lors des échanges avec le contrôleur de domaine tels que décrits dans l’article Kerberos en Active Directory, lorsque l’utilisateur fait une demande de ticket de service (KRB_TGS_REQ), il précisera le SPN du service qu’il souhaite utiliser. C’est à ce moment que le contrôleur de domaine va chercher les deux prérequis :

  • Est-ce que le drapeau TRUSTED_FOR_DELEGATION est positionné dans les attributs du compte associé au SPN
  • Est-ce que le drapeau NOT_DELEGATED n’est pas positionné pour l’utilisateur qui fait la demande

Si les deux prérequis sont vérifiés, alors le contrôleur de domaine va répondre à l’utilisateur avec un KRB_TGS_REP contenant les informations classiques, mais il va également intégrer dans sa réponse une copie du TGT de l’utilisateur, ainsi qu’une nouvelle clé de session associée.

TGT Copy

Une fois en possession de ces éléments, l’utilisateur va continuer le processus classique en envoyant une requête auprès du service (KRB_AP_REQ) en lui envoyant le ticket de service et un authentifiant. Le service va être en mesure de déchiffrer le contenu du ticket de service, vérifier l’identité de l’utilisateur en déchiffrant l’authentifiant, mais surtout il va pouvoir récupérer la copie du TGT ainsi que la clé de session associée pour, ensuite, se faire passer pour l’utilisateur auprès du contrôleur de domaine.

TGT Memory

En effet, maintenant en possession d’une copie du TGT de l’utilisateur ainsi que d’une clé de session valide, le service peut s’authentifier auprès de n’importe quel autre service au nom de l’utilisateur en faisant une demande de ticket de service au contrôleur de domaine, en lui fournissant ce TGT et en chiffrant un authentifiant avec la clé de session. C’est le principe de la délégation sans contrainte, ou Unconstrained Delegation.

Voici un schéma récapitulatif :

Unconstrained Delegation Detailed

Kerberos Constrained Delegation

Pour la délégation contrainte, ou Constrained Delegation, une liste de SPN est fournie pour indiquer les ressources acceptées pour la délégation. De ce fait, le processus n’est pas le même. Le service concerné ne sera pas en possession du TGT de l’utilisateur, sinon il n’y a aucun moyen de contrôler ses authentifications. Un mécanisme différent est utilisé.

Mettons nous dans le cas où l’utilisateur s’authentifie auprès du Service A puis que ce Service A doit s’authentifier auprès de la ressource Ressource B en tant que l’utilisateur.

L’utilisateur fait une requête de ticket de service, puis l’envoie au Service A. Ce service devant s’authentifier en tant que l’utilisateur auprès de Ressource B, il va demander un ticket de service au contrôleur de domaine au nom de l’utilisateur. Cette demande est régie par l’extension S4U2Proxy. Pour indiquer au contrôleur de domaine qu’il veut s’authentifier au nom de quelqu’un d’autre, deux attributs seront définis dans la demande de ticket KRB_TGS_REQ :

  • le champ additional-tickets, d’habitude vide, doit cette fois contenir le ticket de service de l’utilisateur en question (sous condition que le drapeau NOT_DELEGATED ne soit pas positionné pour l’utilisateur qui fait la demande. Si c’était le cas, le ticket de service de l’utilisateur ne serait pas forwardable, et le contrôleur de domaine ne l’accepterait pas dans la suite du processus)
  • Le drapeau cname-in-addl-tkt, qui doit être positionné pour indiquer au contrôleur de domaine qu’il ne doit pas utiliser les informations du serveur, mais celles du ticket présent dans additional-tickets, c’est à dire les informations de l’utilisateur pour lequel le service veut se faire passer.

C’est lors de cette demande que le contrôleur de domaine, en voyant ces informations, va vérifier que Service A a le droit de s’authentifier auprès de Ressource B au nom de l’utilisateur.

Constrained Delegation - Classique

Dans le cas classique de Constrained Delegation (donc quand l’information est située au niveau de Service A), cette information est présente dans l’attribut msDS-AllowedToDelegateTo de l’objet (compte) demandeur, donc de Service A, attribut qui spécifie la liste des SPN autorisés pour la délégation.

Delegation CIFS

Par exemple ici l’attribut msDS-AllowedToDelegateTo contiendra cifs/WEB-SERVER-02.

allowedToDelegateTo

Si le SPN cible est bien présent, alors le contrôleur de domaine renvoie un ticket de service valide, avec le nom de l’utilisateur, pour le service demandé. Voici un schéma récapitulatif :

Constrained Delegation Detailed

Constrained Delegation - Resource Based

Le contrôleur de domaine va cette fois aller voir les attributs de Ressource B (et non plus de Service A). Il va vérifier que le compte associé à Service A est bien présent dans l’attribut msDS-AllowedToActOnBehalfOfOtherIdentity du compte lié à Ressource B.

Pour mettre en place de la délégation sans contrainte basée sur une ressource, il faut le faire via Powershell.

Set RBCD

Nous ajoutons WEB-SERVER-01 à la liste de confiance de WEB-SERVER-02. Le contenu de l’attribut msDS-AllowedToActOnBehalfOfOtherIdentity est alors mis à jour.

Voici le schéma récapitulant le fonctionnement de RBCD.

Resource Based Constrained Delegation Detailed

Comme le montre le schéma, le fonctionnement technique est similaire, cependant les responsabilités de chaques entités sont radicalement différentes.

Extension S4U2Self

Si vous êtes encore là et que vous avez bien suivi, vous aurez remarqué que nous n’avons pas abordé dans cet article la notion de transition de protocole. En effet, dans ce qui a été expliqué concernant la délégation contrainte, nous partions du principe que le Service A était en possession d’un ticket de service provenant de USER, ticket qui était ajouté dans le champ additional-tickets de la demande de ticket de service (S4U2Proxy). Mais il arrive que l’utilisateur s’authentifie auprès du serveur d’une autre manière que via le protocole Kerberos (par exemple via NTLM, ou même un formulaire web). Dans ce cas, le serveur n’est pas en possession d’un ticket de service envoyé par l’utilisateur. Ainsi, Service A ne peut pas, en l’état, remplir le champ additional-tickets comme il le faisait dans les cas précédemment décrits.

C’est pourquoi il y a une étape supplémentaire, possible grâce à l’extension S4U2Self, que Service A doit effectuer. Cette étape lui permet d’obtenir un ticket de service pour un utilisateur choisi arbitrairement. Pour cela, il effectue une demande de ticket de service classique (KRB_TGS_REQ) sauf qu’au lieu de mettre son nom à lui dans le bloc PA-FOR-USER (présent dans la partie préauthentification), il met le nom d’un utilisateur qu’il choisit.

Cette capacité à gérer une transition de protocole n’est acceptée par le contrôleur de domaine que si elle a explicitement été accordée au compte de service voulant gérer cette délégation. C’est ici, dans la gestion des délégation, qu’un administrateur peut choisir une délégation contrainte en utilisant uniquement Kerberos, donc sans transition de protocole, ou pouvant utiliser n’importe quel protocole, autorisant ainsi la transition de protocole.

Protocol transition

Dans le premier cas, le drapeau TRUSTED_FOR_DELEGATION qui est positionné sur le compte, et le service ne peut que relayer les authentification kerberos. Il ne peut pas utiliser l’extension S4U2Self pour créer un ticket factice.

Dans le deuxième cas, c’est le drapeau TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION qui est positionné. Si c’est le cas, alors le service ayant cette capacité peut se faire passer pour n’importe qui auprès des services présents dans sa liste via l’extension S4U2Self.

Attention, le schéma de la délégation contrainte se complique un peu, mais j’espère qu’il reste relativement clair.

S4U2Self

Si un compte de ce type est compromis, alors tous les services auxquels ce compte est en droit de s’authentifier via délégation seront également compromis, puisque l’attaquant peut créer des tickets de service au nom d’utilisateurs arbitraires, notamment des utilisateurs administrateurs des services ciblés.

Conclusion

Je pensais faire un article qui allait décrire le principe de la délégation kerberos ainsi que les attaques associées, cependant les explications sont beaucoup plus denses que prévues, ainsi cet article reste consacré à l’explication. Les attaques associées seront présentées dans d’autres articles.

Pour résumer, il existe trois types de délégation :

  1. Délégation sans contrainte : Dans ce cas de figure, le client envoie une copie de son TGT à un service, et ce service pour l’utiliser pour se faire passer pour le client auprès de qui il souhaite. Seul un administrateur peut appliquer cette option
  2. Délégation contrainte : Une liste de ressources est imposée au service qui souhaitera déléguer une authentification. Si par ailleurs la transition de protocole est autorisée, alors le service peut se faire passer pour n’importe qui auprès des ressources présentes dans sa liste. Quoiqu’il en soit, seul un administrateur peut appliquer cette option.
  3. Délégation contrainte basée sur les ressources : C’est au niveau de la ressource finale qu’il y a une liste de confiance. Tous les comptes présents dans cette liste peuvent déléguer une authentification et accéder à la ressource. Les ressources sont maitres de leur liste, elles peuvent les modifier comme bon leur semble.

Si vous avez des questions ou remarques, n’hésitez pas, je suis tout ouïe.

Ressources

Grands mercis à eux pour leurs explications claires.


hackndo logo
Auteur : Pixis
Créateur du blog, suivez-moi sur twitter ou discord