La console des modèles de certificat vous présente une version propre et organisée par onglets d'un modèle. En dessous, un modèle n'est qu'un objet Active Directory doté d'une trentaine d'attributs, et l'essentiel de la vraie configuration réside dans des entiers à masque de bits que la console traduit discrètement pour vous. Quand vous auditez une infrastructure à clés publiques (PKI), scriptez la création d'un modèle ou cherchez pourquoi un certificat émis est sorti de travers, vous finissez par lire ces attributs bruts directement.

Ceci est une référence sur le sens de chaque attribut, écrite pour les gens qui savent déjà ce qu'est un modèle de certificat et veulent en lire un sans l'interface graphique dans le chemin.

Vous pouvez exporter un modèle de deux façons. certutil -dsTemplate <NomDuModele> donne la vue décodée pour humains utilisée dans tout cet article. Ou vous pouvez lire l'objet directement en LDAP sous CN=Certificate Templates,CN=Public Key Services,CN=Services,CN=Configuration,DC=..., ce que font réellement les outils (et les attaquants qui énumèrent les chemins ESC). La liste complète des attributs et de leurs tables d'indicateurs est documentée par Microsoft dans la spécification MS-CRTD.

La matrice

La colonne Modifiable indique : s'agit-il d'une propriété que vous configurez légitimement pour définir le modèle (true), ou de métadonnées AD/système qu'il ne faut pas éditer à la main (false). Quelques-unes ne sont pas des booléens nets et sont renvoyées en note.

AttributModifiableRôle
objectClassfalseDésigne l'objet comme top + pKICertificateTemplate.
cnfalse¹Nom interne du modèle (sans espaces). L'identité de l'objet.
namefalse¹Reflète cn.
displayNametrueNom convivial affiché dans la console.
distinguishedNamefalseDérivé du cn et de l'emplacement de l'objet.
instanceTypefalseType d'instance de l'objet AD. Système.
whenCreated / whenChangedfalseHorodatages de création et de dernière modification. Système.
uSNCreated / uSNChangedfalseNuméros de séquence de réplication. Système.
showInAdvancedViewOnlytrueMasque l'objet des vues ADUC par défaut.
nTSecurityDescriptortrueLa liste de contrôle d'accès : qui peut Lire, S'inscrire, S'inscrire automatiquement et Écrire.
objectGUIDfalseIdentifiant d'objet immuable.
objectCategoryfalsePointeur vers la classe de schéma.
revisionfalse²Version majeure. Incrémentée automatiquement à la modification.
msPKI-Template-Minor-Revisionfalse²Version mineure. Incrémentée automatiquement à la modification.
msPKI-Template-Schema-Versiontrue³Génération du modèle, de 1 à 4.
flagstrueIndicateurs d'inscription généraux (hérités).
pKIDefaultKeySpectrueSpécification de clé CAPI héritée : 1 = échange de clés, 2 = signature.
pKIKeyUsagetrueBits de l'extension Utilisation de la clé inscrits dans les certificats émis.
pKIMaxIssuingDepthtrueContrainte de longueur de chemin, pour les modèles d'AC.
pKICriticalExtensionstrueOID marqués comme critiques dans les certificats émis.
pKIExpirationPeriodtruePériode de validité des certificats émis.
pKIOverlapPeriodtrueFenêtre de renouvellement avant l'expiration.
pKIExtendedKeyUsagetrueOID d'utilisation avancée de la clé (EKU).
pKIDefaultCSPstrueListe ordonnée des fournisseurs cryptographiques.
dSCorePropagationDatafalseMétadonnées de réplication. Système.
msPKI-RA-SignaturetrueNombre de signatures d'autorité d'inscription requises.
msPKI-Enrollment-FlagtrueMasque de bits du comportement d'inscription.
msPKI-Private-Key-FlagtrueGestion de la clé privée et seuils de version OS (AC / client).
msPKI-Certificate-Name-FlagtrueProvenance du sujet et du SAN.
msPKI-Minimal-Key-SizetrueTaille de clé minimale.
msPKI-Cert-Template-OIDfalseOID immuable identifiant ce modèle.
msPKI-Certificate-Application-PolicytrueOID de stratégie d'application (équivalent EKU à partir de la V2).
  1. cn et name sont définis une seule fois à la création et sont de fait immuables. Renommer un modèle revient à créer un nouvel objet.
  2. revision et la révision mineure sont gérées par le système et s'incrémentent quand vous modifiez un modèle. Vous pouvez les écrire via ADSI, et les administrateurs les incrémentent parfois volontairement pour forcer une réémission par inscription automatique, mais ce ne sont pas des paramètres de configuration ordinaires.
  3. msPKI-Template-Schema-Version est modifiable, mais pas librement. Elle est liée aux paramètres de compatibilité, lesquels résident aussi dans msPKI-Private-Key-Flag. Détails plus bas.

Les métadonnées auxquelles vous ne touchez pas

La première douzaine de lignes relève de la plomberie Active Directory. objectClass, objectCategory, instanceType, objectGUID, les horodatages et les compteurs USN sont tous posés et maintenus par AD. distinguishedName découle de l'endroit où vit l'objet. cn et name sont l'identité interne du modèle et ne changent pas sur place.

displayName et showInAdvancedViewOnly sont les deux attributs proches des métadonnées que vous éditez réellement : l'un est le nom convivial dans la console, l'autre détermine si l'objet apparaît dans la vue ADUC par défaut.

msPKI-Cert-Template-OID mérite une note. C'est l'OID unique qui identifie le modèle, attribué à la création et jamais changé. Si vous dupliquez un modèle, la copie reçoit son propre OID. Les certificats émis transportent cet OID dans l'extension Certificate Template Information, ce qui permet à une AC et à une partie de confiance de savoir quel modèle a produit un certificat donné.

Les deux jeux d'indicateurs qui se ressemblent

C'est la source de confusion la plus fréquente à la lecture d'un modèle, donc autant être explicite.

Il existe deux attributs à masque de bits sans rapport entre eux qui utilisent tous deux des noms de constantes CT_FLAG_, et certains de ces noms apparaissent dans les deux avec la même valeur. Ce sont des attributs différents qui régissent des choses différentes.

L'attribut hérité flags est l'attribut des indicateurs d'inscription généraux. Il porte des caractéristiques larges du modèle, dont plusieurs que le système pose pour vous selon le type de modèle et les EKU. Les bits que vous verrez réellement ici incluent CT_FLAG_MACHINE_TYPE (0x40, c'est un modèle d'ordinateur), CT_FLAG_IS_CA (0x80, c'est un modèle d'AC), CT_FLAG_PUBLISH_TO_DS (0x8), CT_FLAG_EXPORTABLE_KEY (0x10), CT_FLAG_ADD_TEMPLATE_NAME (0x200) et CT_FLAG_AUTO_ENROLLMENT (0x20).

L'attribut msPKI-Enrollment-Flag regroupe les indicateurs d'inscription de la V2 et au-delà. C'est lui qui porte les contrôles d'inscription modernes. Les bits à connaître :

  • CT_FLAG_PEND_ALL_REQUESTS (0x2) active l'approbation par le gestionnaire de certificats de l'AC. Chaque demande tombe dans la file d'attente.
  • CT_FLAG_PUBLISH_TO_DS (0x8) écrit le certificat émis dans l'attribut userCertificate de l'objet utilisateur.
  • CT_FLAG_AUTO_ENROLLMENT (0x20) active l'inscription automatique pour le modèle.
  • CT_FLAG_ADD_OCSP_NOCHECK (0x400) appose l'extension ocsp-nocheck, utilisée sur les certificats de signature des répondeurs OCSP.
  • CT_FLAG_NO_SECURITY_EXTENSION (0x20000) supprime l'extension de sécurité SID. Celui-là mord, voir plus bas.

Donc flags = "131642" et msPKI-Enrollment-Flag = "33" sont deux entiers distincts décodés selon deux tables distinctes. Voir CT_FLAG_AUTO_ENROLLMENT dans les deux n'est pas un doublon, ce sont deux attributs différents qui partagent un nom.

L'indicateur d'extension SID est celui à auditer

CT_FLAG_NO_SECURITY_EXTENSION (0x20000 dans msPKI-Enrollment-Flag) dit à l'AC de ne pas ajouter l'extension szOID_NTDS_CA_SECURITY_EXT (OID 1.3.6.1.4.1.311.25.2) aux certificats émis. Cette extension porte le SID du compte demandeur et c'est elle qui rend un certificat fortement mappé.

Depuis KB5014754, les contrôleurs de domaine passés en mode d'application complète rejettent les ouvertures de session par certificat dépourvues d'un mappage fort. Si cet indicateur est posé sur un modèle d'authentification alors que vos KDC sont en application, ces certificats échouent à l'authentification. L'indicateur existe pour des raisons légitimes (certaines parties de confiance hors AD s'étouffent sur l'extension inconnue), mais sur un modèle d'authentification de domaine c'est un constat. Vérifiez-le avant une échéance d'application, pas après.

La gestion de la clé privée, et où se joue vraiment la question 2012 contre 2016

msPKI-Private-Key-Flag fait deux travaux dans un seul entier. Les bits de poids faible contrôlent la gestion de la clé privée. Les bits de poids fort encodent les systèmes d'exploitation minimaux de l'AC et du client, ce que l'onglet Compatibilité de la console lit et écrit en réalité. Microsoft documente la table des indicateurs dans MS-CRTD et l'entrée du schéma AD dans Win32.

Les bits de poids faible que vous verrez :

  • CT_FLAG_REQUIRE_PRIVATE_KEY_ARCHIVAL (0x1) envoie la clé privée à l'AC en vue d'une récupération de clé.
  • CT_FLAG_EXPORTABLE_KEY (0x10) permet d'exporter la clé en PFX par la suite. Sur un modèle d'authentification, cela affaiblit l'hypothèse que la clé reste sur l'appareil, donc à regarder de près.
  • CT_FLAG_STRONG_KEY_PROTECTION_REQUIRED (0x20) demande ou impose une protection de la clé par l'utilisateur.
  • CT_FLAG_USE_LEGACY_PROVIDER (0x100) force le traitement CAPI/CSP au lieu de CNG/KSP. On le pose délibérément quand un chemin KSP pose problème, par exemple certains scénarios HSM ou NDES.
  • Les bits d'attestation (CT_FLAG_ATTEST_NONE, _PREFERRED, _REQUIRED) régissent l'attestation de clé par TPM.

Les bits de poids fort sont la partie que les gens manquent. Selon MS-WCCE, la valeur ET 0x000F0000 donne la version minimale de l'AC, et la valeur ET 0x0F000000 donne la version minimale du client. Ces deux quartets sont l'onglet Compatibilité.

Voici la conséquence pratique. La version de schéma 4 est le plafond. Microsoft n'a jamais livré de schéma 5, donc Server 2012, 2012 R2, 2016, 2019 et 2022 rapportent tous msPKI-Template-Schema-Version = 4. Le numéro de schéma seul ne distingue pas 2012 de 2016. La distinction tient entièrement à ces quartets de version :

  • 0x40000 / 0x4000000 = Windows 8 / Server 2012
  • 0x50000 / 0x5000000 = Windows 8.1 / Server 2012 R2
  • 0x60000 / 0x6000000 = Windows 10 / Server 2016

Donc si vous créez un modèle par script, fixez le schéma 4 et laissez les quartets à la valeur par défaut 2012, la console rapportera correctement « Server 2012 » et ne passera jamais à 2016. Pour l'élever, vous devez réécrire ces quartets dans msPKI-Private-Key-Flag. Ce sont des champs multi-bits, alors vous effacez le quartet d'abord, puis posez la nouvelle valeur. Ne faites pas un simple OR des nouveaux bits, vous corrompriez le champ :

# élever la version de l'AC à Server 2016 (Threshold)
$pkf = $pkf -band (-bnot 0x000F0000)
$pkf = $pkf -bor   0x00060000
# élever la version du client à Windows 10 / Server 2016
$pkf = $pkf -band (-bnot 0x0F000000)
$pkf = $pkf -bor   0x06000000

Une mise en garde : élever le plancher client retire silencieusement du modèle tout système plus ancien. Faites-le parce que vous le voulez, pas par réflexe.

La provenance du sujet et du SAN

msPKI-Certificate-Name-Flag décide d'où viennent le sujet et l'autre nom du sujet (SAN), et c'est l'attribut qui décide si un modèle est dangereux. La table complète des indicateurs est dans MS-CRTD.

Les deux modes :

  • CT_FLAG_ENROLLEE_SUPPLIES_SUBJECT (0x1) laisse le demandeur se nommer lui-même. L'AC prend le sujet et le SAN dans la demande.
  • Les bits SUBJECT_REQUIRE_* et SUBJECT_ALT_REQUIRE_* construisent plutôt le sujet et le SAN à partir de l'objet AD du demandeur. Par exemple CT_FLAG_SUBJECT_ALT_REQUIRE_UPN (0x2000000) ajoute l'UPN, CT_FLAG_SUBJECT_REQUIRE_COMMON_NAME (0x40000000) fixe le CN d'après AD.

Un modèle où le demandeur fournit le sujet, qui émet en plus un EKU d'authentification et autorise une inscription large, c'est la configuration classique d'ESC1 : un demandeur peu privilégié se nomme sous l'identité d'un autre et obtient un certificat d'authentification pour cette identité. Quand vous lisez cet attribut, la question est toujours de savoir si le sujet est construit depuis AD ou fourni par le demandeur.

Propriétés de cryptographie et d'émission

Les attributs restants sont les plus directs.

pKIDefaultKeySpec est la spécification de clé CAPI héritée : 1 c'est échange de clés (signer et chiffrer), 2 c'est signature seulement. Pertinent pour les modèles fondés sur CSP, inerte sous CNG.

pKIKeyUsage contient les bits de l'extension Utilisation de la clé sous forme de chaîne d'octets. a0 00 c'est Signature numérique plus Chiffrement de la clé. pKICriticalExtensions liste les OID marqués critiques, généralement Utilisation de la clé (2.5.29.15).

pKIExtendedKeyUsage et msPKI-Certificate-Application-Policy portent tous deux des OID d'objectif. EKU est la liste de style V1, la stratégie d'application est l'équivalent de la V2 et au-delà. Sur les modèles modernes, ils concordent en général. Authentification du client c'est 1.3.6.1.5.5.7.3.2, Authentification du serveur c'est .3.1.

pKIDefaultCSPs est la liste ordonnée des fournisseurs cryptographiques offerts à l'inscription, CSP ou KSP. msPKI-Minimal-Key-Size est le plancher, couramment 2048 pour RSA.

pKIExpirationPeriod et pKIOverlapPeriod sont la période de validité et la fenêtre de renouvellement, stockées comme des écarts de temps binaires que certutil décode pour vous en valeurs comme « 1 Years » et « 6 Weeks ».

pKIMaxIssuingDepth est la contrainte de longueur de chemin, et elle ne compte que sur les modèles d'AC. Elle fixe combien de niveaux d'AC supplémentaires peuvent se trouver sous une AC issue de ce modèle. Sur un modèle d'entité finale, elle est inerte.

msPKI-RA-Signature est le nombre de signatures d'autorité d'inscription (agent d'inscription) qu'une demande doit porter avant que l'AC n'émette. Zéro signifie aucune requise.

Qui peut utiliser le modèle

nTSecurityDescriptor est la liste de contrôle d'accès, et c'est l'autre moitié d'un constat de type ESC1. S'inscrire et S'inscrire automatiquement sont des droits étendus accordés aux entités de sécurité listées ici. La combinaison qui compte, c'est des droits d'inscription larges plus un indicateur de nom permissif plus un EKU d'authentification. Un modèle propre accorde Lire aux Utilisateurs authentifiés et S'inscrire seulement à un groupe précis, jamais S'inscrire aux Utilisateurs authentifiés sur un modèle sensible.

Quand vous lisez un modèle, lisez le descripteur de sécurité avec. Les indicateurs vous disent ce que sera le certificat. La liste de contrôle d'accès vous dit qui peut en demander un.

Comment en lire un vous-même

certutil -dsTemplate VotreNomDeModele > template.txt

La sortie liste chaque valeur d'indicateur en entier, les bits posés affichés nus et les bits non posés affichés entre parenthèses. Cette convention est facile à manquer la première fois : une longue liste de noms CT_FLAG_* ne veut pas dire qu'ils sont tous actifs. Lisez ceux qui sont nus.

Tout ce qui précède est régi par la spécification MS-CRTD publique, la référence faisant autorité quand une valeur décodée ne correspond pas à ce que la console affiche.