MaxTokenSize et erreurs HTTP 400
MaxTokenSize?
Au fur et à mesure de la vie d’un Active Directory, les comptes utilisateurs deviennent membres de groupes de sécurité de plus en plus nombreux. Cela peut provoquer dans certains cas des problèmes généralement difficiles à reconnaître. Ils apparaissent souvent comme des défaillances d’application aléatoires ou des pannes: Echecs de l’application de stratégie de groupe, lancement d’un site Web finissant en erreur HTTP 400, ouverture se session impossible, etc…
Les informations d’appartenance à un groupe utilisées pour créer un jeton d’accès sont envoyées chiffrées dans un ticket Kerberos. La partie du ticket Kerberos utilisée pour stocker ces informations d’appartenance au groupe est appelée le Privilege Attribute Certificate (PAC). Pour en savoir plus sur le PAC, vous pouvez consulter cet article ou [MS-PAC] pour connaitre la structure complète du PAC.
Si la taille de jeton maximale est définie sur une valeur trop petite pour contenir toutes les informations d’appartenance à un groupe pour un utilisateur, le jeton ne contiendra pas l’appartenance à un groupe complet. Un utilisateur ne pourra pas s’authentifier car le jeton Kerberos généré lors des tentatives d’authentification a une taille maximale fixe. Les protocoles de transports tels que RPC (Remote Procedure Call) et HTTP s’appuient sur la valeur MaxTokenSize lorsqu’ils s’allouent un espace mémoire pour traiter l’authentification. Cette valeur a évoluée depuis Windows 2000. Nous sommes à présent dans les versions de Windows les plus récentes sur une valeur à 48Ko.
Attention, cet article ne traite que du phénomène rencontré à l’utilisation du protocole Kerberos. Dans la plupart des cas quand NTLM est utilisé, aucun problème n’apparaîtra dans la phase d’authentification. En effet NTLM fournit le PAC après cette phase par le message NETLOGON_VALIDATION_SAM_INFO4.
Ouverture de session Windows
Lorsqu’un utilisateur ouvre une session et que l’authentification réussit, le processus d’ouverture de session renvoie un SID pour l’utilisateur et une liste de SID pour les groupes de sécurité de l’utilisateur. Ces informations sont ensuite forgées dans le TGT et utilisée aussi dans les TGS. Le PAC peut contenir le SID des groupes ci dessous:
- Le SID principal de l’utilisateur, y compris les SID history,
- Le SID de chaque groupe local de domaine,
- Le SID de chaque groupe global y compris si existant des SID history de groupes,
- Le SID de chaque groupe universel y compris si existant des SID history de groupes,
- Globalement l’ensemble des SID de groupes y compris les groupes imbriqués.
Attention: Le champ qui contient les SID des appartenances au groupe dans le jeton d’accès peut contenir théoriquement un maximum de 1 024 SID. En réalité ça n’est pas vraiment 1024 mais 1024 – 9 soit 1015 SID! Si l’utilisateur fait donc partit de plus de 1015 groupes, l’autorité de sécurité locale (LSA) ne peut pas créer de jeton d’accès lors de la tentative d’ouverture de session. Si cela se produit, le message d’erreur ci dessous s’affiche à l’ouverture de session de l’utilisateur:
Calcul du de la taille d’un Token pour un compte
Au delà de cette limite en nombre de groupe, certains groupes prennent une place plus importante que d’autres et peuvent contribuer s’ils sont trop importants à générer des problèmes bien avant d’avoir 1015 groupes. Il existe une formule mathématique permettant de calculer la valeur du token pour un utilisateur: Microsoft la documente dans cet article et nous pouvons la rependre ici:
TokenSize = 1200 octets + (40 octets X d)+ (8 octets X s)
d: Représente le nombre de groupes locaux auquel appartient un utilisateur + le nombre de groupes universels situés en dehors du domaine de compte de l’utilisateur + le nombre de groupes représentés dans l’SID history.
s: Représente le nombre de groupes globaux auquel appartient un utilisateur + le nombre de groupes universels dans le domaine de compte d’un utilisateur.
1200: Représente la valeur estimée pour la le reste du ticket. Cette valeur peut varier en fonction de facteurs tels que la longueur du nom de domaine DNS, le nom du client et d’autres facteurs… (D’expérience, nous sommes plus autour de 1340 octets)
Nous pouvons utiliser ce script powershell pour calculer la valeur d’un Ticket pour un utilisateur. Il reprend la formule ci dessus. Il existe cependant une méthode moins connue qui permet de lister les groupes auxquels un utilisateur appartient à travers la commande NTDSUTIL / Group Membership Evaluation puis run NOMDEDOMAIN nomducompte.
IIS, HTTP 400 – Bad Request
Par le passé Microsoft avait indiqué qu’il était possible d’augmenter la taille du MaxTokenSize à 65 535 o. C’est quelque chose qui n’est pas à recommander car certaines applications se calquent sur cette valeur. Prenons l’exemple de IIS. Comme nous l’avons vu dans cet article, le client utilise l’entête « Autorization » pour fournir au serveur IIS des éléments d’authentification (Ticket Kerberos). La taille de l’en-tête augmente donc avec le nombre de groupes d’utilisateurs. Si l’en-tête HTTP augmente au-delà des limites qui sont configurés sur le serveur, le serveur IIS peut rejeter la demande et envoyer un message d’erreur comme réponse (HTTP 400 – Bad Request).
2 valeurs dans la base de registre du serveurs pour HTTP.sys permettent de contrôler la taille maximale de chaque en-tête de demande HTTP. Par défaut ces valeurs ne sont pas présentes mais peuvent au besoin être créées sous HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\HTTP\Parameters . L’entrée de Registre MaxFieldLength spécifie la limite supérieure de la taille totale de la ligne Request et des en-têtes. En général, cette entrée de Registre est configurée avec l’entrée de Registre MaxRequestBytes . Si la valeur de MaxRequestBytes est inférieure à la valeur de MaxFieldLength, la valeur MaxFieldLength est ajustée.
Même si absente dans le registre, MaxFieldLength est fixé par défaut à partir de Windows 2012 à 65 534 o. En raison du codage HTTP en base64 de l’entête HTTP, la valeur du MaxTokenSize ne doit donc pas dépasser 48 000 octets (48 o X 1.333 = env 64 o). Les 1.333 représentent l’encodage en base 64 qui augmente mécaniquement la taille de l’entête. Vous pouvez consulter cet article pour aller plus loin en décodant l’entête Autorization.
Solutions
Nous l’avons vu, il n’est pas recommandé d’augmenter les valeurs MaxTokenSize pour éviter les sur-problèmes notamment liés au applications diverses composant l’écosystème Microsoft.
Une autre idées serait d’activer la compression du SID à partir de Windows 2012 mais encore une fois certaines applications ne supportant pas ce fonctionnement risquent de ne plus fonctionner.
Le seul conseil qui pourrait être donné serait de réduire la taille du ticket Kerberos en effectuant un ménage sur le nombre de groupe. Malheureusement cette tache n’est pas aisé surtout pour les environnements importants. Il faut donc se focaliser sur les groupes les plus « gourmands », les d dans le calcul plus haut. Au delà de l’aspect sécurité, le nettoyage de l’historique SID peut être aussi une bonne solution ainsi que la limitation du nombre d’utilisateurs configurés pour utiliser « approuvé pour la délégation.