Double Hop et Internet Information Service (IIS)

Fonctionnement de Kerberos

Synthétiquement, Kerberos fonctionne de la façon suivante

  • Le compte demande un TGT (l’équivalent d’un passeport), en présentant son identité (nom, mot de passe, domaine).
  • Le contrôleur de domaine retourne un TGT. Ce ticket est crypté par une information partagée par tous les contrôleurs de domaine, et uniquement par eux, le mot de passe du compte krbtgt.
  • Le compte demande un TGS (l’équivalent d’un visa) pour accéder à une ressource, en présentant son TGT.
  • Le contrôleur de domaine retourne le TGS. Ce ticket est encrypté par une information partagée par le contrôleur de domaine et la ressource, le mot de passe du compte utilisé par la ressource.
  • Le compte se connecte à la ressource en présentant le TGS.
  • La ressource valide l’authentification et autorise l’accès.

La ressource est identifiée par un SPN (Service Principal Name) prenant généralement la forme <SERVICE>/<nom de la machine>. Le nom peut être netbios ou DNS. On peut également trouver comme suffixe au SPN, un numéro de port (pour SQL par exemple), ou le nom du domaine.

Exemples de SPN :

  • HOST/MyComputer.child.domain.com
  • TERMSRV/MYCOMPUTER
  • ldap/MyDC.child.domain.com/child.domain.com
  • MSSQLSvc/MySQL.domain.com:1433

Le compte dont le mot de passe est utilisé pour crypter le TGS est celui qui publie le SPN demandé. D’où la nécessité de vérifier avec attention les SPNs et l’objet sur lequel ils sont publiés. En particulier dans le cas de service s’exécutant avec un compte utilisateur. Il faut publier <service>/<nom de l’ordinateur> sur le compte de service. Attention également aux comptes homonymes dans plusieurs domaine de votre environnement, cela peut mener à l’échec de l’authentification Kerberos, causé par l’usage d’un compte différent de celui utilisé par la ressource pour encrypté le TGS.

Prenons un exemple. Mon serveur web se nomme IIS, dans le domaine child.domain.com. Le site web utilise un nom différent : intranet.child.domain.com. et l’application pool utilise le compte srv_IIS du domaine child.domain.com. Il faut donc publier HTTP/intranet.child.domain.com sur le compte srv_IIS.
Cette opération peut être réalisée avec l’outil setspn.exe et la commande suivante

setspn.exe -A HTTP/intranet.child.domain.com srv_IIS

Qu’est-ce que le double hop

Le double hop consiste à permettre à un compte de demander un TGS pour un autre compte.

C’est par exemple le cas lorsqu’on le souhaite qu’un serveur web se connecte à une base de donnée en utilisant l’identité de l’utilisateur, et non son identité propre. Dans ce cas, il faut respecter les pré-requis suivant :

  • Le compte de l’utilisateur ne doit pas avoir le flag “This account is sensible and cannot be delegated” Mots clés Technorati : Kerberos
  • Le compte de service doit avoir un SPN publié, pour que la première authentification (client – IIS ici) utilise Kerberos.
  • Ce compte de service doit avoir la délégation activée (flag “Trusted for delegation”)
  • Le compte de la seconde ressource (SQL dans l’exemple) doit également avoir un SPN publié.
  • Il faut que les pré-requis pour l’authentification Kerberos soit réunis (poste client pas en workgroup, résolution DNS pour les enregistrements SRV, accès possible à un contrôleur de domaine par le poste client, …)

Si la première authentification n’est pas faite en Kerberos mais en NTLM (du client vers le serveur web dans mon exemple), la seconde connexion (du serveur web vers la base SQL) sera réalisée en anonyme, et donc l’accès refusé. NTLM ne permet pas de délégation.

En pratique, le poste client demande un TGT, puis un TGS pour le premier service selon la mécanique classique. Ensuite, ce service demande un TGS pour le second service en présentant non pas son propre TGT, mais le TGS de l’utilisateur. Il obtient ainsi un ticket pour l’utilisateur, sans connaitre son mot de passe.

Informations complémentaires

Si vous utilisez un enregistrement DNS de type alias (CNAME) pour résoudre le nom de la ressource sur le nom de la machine, il faut publier le SPN en utilisant le nom physique de la machine.
Dans mon exemple plus haut, le nom du serveur est IIS.child.domain.com, et la zone child.domain.com contient un alias nommé intranet qui pointe sur ce nom. C’est donc le SPN HTTP/IIS.child.domain.com qu’il faut publier. Si part contre l’enregistrement intranet est de type hote (A), il faut alors publier HTTP/intranet.child.domain.com.
Ce comportement a été modifié par le patch de sécurité MS09-054 qui active la fonctionnalité décrite dans l’article technique 911149 - Error message in Internet Explorer when you try to access a Web site that requires Kerberos authentication on a Windows XP-based computer: "HTTP Error 401 - Unauthorized: Access is denied due to invalid credentials"

Sous Windows 2000 la délégation n’était pas granulaire. Le premier service pouvait demander n’importe quel ticket au nom de l’utilisateur. Avec Windows 2003, on dispose d’une granularité plus fine. Il est désormais possible d’indiquer explicitement quel ticket le service peut demander au nom de l’utilisateur. Cela s’appelle la délégation contrainte (constrained delegation). De plus, il est désormais possible de faire de la transition de protocole (protocol transitionnong), résolvant ainsi le problème de la première authentification. Le service est capable de demander un ticket Kerberos pour l’utilisateur, même si celui-ci s’est connecté en utilisant NTLM.

La dernière version de l’outil setspn.exe permet la recherche de doublon de SPN (SPN publié plusieurs fois, sur ces comptes différents). Cette situation est une cause courante de l’echec de l’authentification Kerberos (le TGS est encrypté avec le mot de passe d’un compte, et la ressource utilise un autre compte). Elle vérifie, au moment de la publication d’un SPN, s’il n’est pas déjà publié sur une autre ressource, et peut rechercher les doublons. Cette mise à jour est téléchargeable depuis l’article technique 970536 - Setspn.exe support tool update for Windows Server 2003

IIS 7 offre une nouvelle fonctionnalité nommée Kernel Mode Authentication. Elle permet d’éviter le passge du mode kernel au mode user pour l’authentification Kerberos. Cette technique permet de gagner en performance quand l’applicaiton pool utilise un contexte de sécurité système (local service, network service ou système). Par contre si l’application pool utilise un compte utilisateur (compte de service), Kerberos ne fonctionnera pas. IIS tentera de décrypter les TGS encrypté avec le mot de passe du compte de service en utilisant le mot de passe du compte machine. Dans ce cas (utilisation d’un compte de service) il est donc nécessaire de désactiver l’option “Kernel Mode Authentication” dans IIS.
Cela se fait en modifiant l’élément windowsAuthentication pour le site web utilisé. Pour plus de détail sur l’élément windowsAuthentication, voir “IIS 7.0: windowsAuthentication Element (IIS Settings Schema)” in the Internet Information Services documentation.

Cyrille de Pardieu