Votre détection a fonctionné. Je veux commencer par là, parce que ça n'arrive pas aussi souvent que ça devrait.

Suzie Q a cliqué sur la chose un jeudi matin. À 11 h 40, quelqu'un dans votre SOC avait une alerte qui ne lui plaisait pas, pis à 11 h 52 son mot de passe était réinitialisé, ses sessions coupées, ses jetons d'actualisation révoqués, et le balayage EDR roulait sur son portable. Ça, c'est une bonne heure de travail. La plupart des places prennent une semaine pour se rendre là, pis bien des places ne s'y rendent jamais.

Ensuite quelqu'un a fermé le billet, le billet était correct, pis j'étais encore dedans.

Voici le bout pour lequel votre plan de réponse n'a pas de ligne. Suzie Q a un certificat. Elle en a un depuis le jour où son compte a été créé, parce que l'inscription automatique lui en a donné un sur le modèle User, pis il se renouvelle tout seul chaque année depuis. Personne ne l'a demandé. Personne ne se souvient qu'il existe. C'est un certificat d'authentification client pour une vraie employée, émis par votre propre AC, et il n'y a rien de croche avec.

J'en ai pris une copie, avec la clé privée, pendant que j'avais sa session. Je n'écrirai pas comment, parce que ça transformerait ce billet en tutoriel, mais je vais vous dire le bout qui compte : le modèle marque cette clé comme non exportable, pis ça ne m'a pas arrêté, parce que « non exportable » dans un fournisseur logiciel, c'est une règle que l'API respecte, pas une propriété de la clé. Avec son profil et sa clé maîtresse, la matière sort.

Regardez maintenant ce que je tiens.

Il porte son SID dans l'extension, l'OID 1.3.6.1.4.1.311.25.2, parce que votre AC est à jour et fait ça correctement. Sous application intégrale, la correspondance est forte, implicitement, exactement comme prévu. Votre KDC n'a aucune raison d'hésiter et aucune raison de journaliser quoi que ce soit d'inhabituel. J'ai déjà écrit sur ce qui arrive quand la confiance déménage dans un attribut d'annuaire. Ici c'est le problème inverse. La confiance est dans le certificat, le certificat est vrai, pis le certificat est à moi maintenant.

Alors je m'authentifie. PKINIT, ma copie de sa clé, pis j'obtiens un TGT Kerberos pour Suzie Q. Événement 4768, ouverture de session par certificat, jeudi après-midi, à partir d'un poste qu'elle utilise. Rien là-dedans ne ressemble à quoi que ce soit.

Ensuite je pose une question de suivi à votre contrôleur de domaine. Le PAC revenu avec ce ticket contient son hash NT, chiffré avec la clé de session, et c'est une fonctionnalité : c'est là pour que les ouvertures de session par certificat puissent encore faire du NTLM vers le serveur de fichiers qui n'a jamais entendu parler de Kerberos. Un échange user-to-user me le remet en clair.

Vous avez changé son mot de passe à 11 h 52. J'ai demandé le nouveau à 12 h 20, pis votre contrôleur de domaine me l'a donné.

Prenez une seconde là-dessus. La réinitialisation n'était pas juste insuffisante. La réinitialisation, c'était une affaire dont je pouvais interroger le résultat.

Je n'en ai plus besoin. C'est le point que je veux vous laisser. Le certificat est bon pour un an à partir du jour de son émission, et avant qu'il expire je peux le renouveler avec la même clé, pis une requête de renouvellement s'authentifie avec le certificat, pas avec son mot de passe. Son mot de passe est maintenant un détail à son sujet, pas un contrôle sur moi. Elle peut le changer aux quatre-vingt-dix jours pendant les onze prochains mois et je vais les regarder passer un par un.

J'ai quand même vérifié si vous pouviez me l'enlever. Vous pouvez. Révoquez le certificat et vos DC vont le refuser. Mais votre CRL de base se publie aux sept jours, pis un contrôleur de domaine honore la copie qu'il a déjà jusqu'à ce qu'elle expire. Donc la réponse honnête, c'est que si quelqu'un avait pensé aux certificats ce jeudi-là, j'aurais eu entre une journée et une semaine, pis je l'aurais dépensée.

Personne n'a pensé aux certificats ce jeudi-là. Il n'y a pas de case sur le formulaire.

Avant de partir, je l'ai renouvelé d'avance. Ouvrez la console de votre AC, allez dans Certificats émis, ajoutez la colonne Attributs de requête, pis triez par date de soumission. Vous cherchez un certificat User émis à Suzie Q à 3 h 14 un dimanche matin. Même clé publique, nouveau numéro de série, pis un attribut sur la requête que j'ai tapé moi-même.

Ça dit Hiro.

Hiro out.


Si vous êtes du côté défense, voici ce qui vient de se passer, sans détour.

Il n'y a pas de numéro ESC sur celle-là. Aucune mauvaise configuration de modèle, aucun droit d'inscription vulnérable, pas de relais, pas d'AC compromise. Chaque composant s'est comporté comme prévu. Le certificat était légitime, l'inscription était légitime, l'authentification était légitime, pis le contrôleur de domaine avait raison de l'accepter. La seule défaillance était dans la réponse, et c'était une omission.

Les pièces sont documentées. Sortir un certificat utilisateur et sa clé d'un profil compromis, c'est THEFT2 dans Certified Pre-Owned, de Will Schroeder et Lee Christensen chez SpecterOps, juin 2021. Retransformer le ticket PKINIT en hash NT, c'est THEFT5 dans le même document, communément appelé UnPAC the hash. Le détail qui rend la réinitialisation sans effet, c'est le moment : le KDC construit la structure PAC_CREDENTIAL_INFO à partir des identifiants du compte tels qu'ils sont au moment où il émet le ticket, donc ce qui revient, c'est le hash actuel, pas celui qui existait quand le certificat a été émis. Renouveler avant l'expiration pour conserver l'accès, c'est PERSIST3. Rien de neuf là-dedans. Ça a cinq ans pis c'est encore la façon la plus discrète de survivre à une réponse à incident.

Deux nuances honnêtes.

Premièrement, c'est de la persistance, pas de l'accès initial ni de l'élévation de privilèges. Hiro est déjà sur le poste avant que ça commence, pis Suzie Q n'est personne en particulier. Ce que le certificat achète, c'est un identifiant qui survit à votre réponse sur un compte que vous avez déjà marqué comme nettoyé, ce qui vaut plus que ça en a l'air, parce que ce compte-là ne sera jamais regardé une deuxième fois.

Deuxièmement, que la clé sorte ou non dépend du fournisseur. Si le modèle exige un KSP adossé au TPM ou une carte à puce, ça devient nettement plus difficile, et dans la plupart des cas ça arrête. Si c'est un fournisseur logiciel, le drapeau « non exportable » est appliqué par l'API et pas par le matériel, pis il n'arrête personne qui a le contexte de l'utilisateur. Je ne peux pas vous donner de chiffre sur la proportion de modèles d'authentification utilisateur en KSP logiciel dans le vrai monde. Le modèle User par défaut en est un, pis la plupart des organisations ne l'ont jamais remplacé. C'est une impression de praticien, pas une statistique que je peux citer.

Trois choses à vérifier cette semaine

Un : ajoutez les certificats au plan de réponse aux incidents. Quand un compte est compromis, énumérez ce que vos AC lui ont émis, pis révoquez-le. Sur chaque AC émettrice, c'est une vue des certificats émis filtrée par demandeur, ou certutil -view -restrict sur le UPN, ensuite révocation avec le motif KeyCompromise et publication immédiate d'une nouvelle CRL au lieu d'attendre la prochaine planifiée. Deux affaires à savoir avant d'en avoir besoin. Désactiver le compte coupe l'ouverture de session par certificat tout de suite, donc un confinement complet vous couvre déjà, mais une simple réinitialisation de mot de passe, non, pis « réinitialiser et surveiller », c'est ce que la plupart des billets d'utilisateur compromis reçoivent réellement. Et la révocation n'est jamais plus rapide que votre CRL, alors trouvez aujourd'hui quel est votre intervalle de publication et votre chevauchement, parce que ce chiffre-là, c'est votre vrai délai de confinement.

Deux : calculez combien de temps un certificat survit à un incident. Regardez la période de validité de chaque modèle qui émet de l'authentification client aux utilisateurs et aux postes. Le modèle User par défaut émet pour un an, donc un certificat volé au premier mois est un identifiant fonctionnel pour les onze suivants. Regardez ensuite le renouvellement, parce qu'un renouvellement avec la clé existante repart cette horloge-là et s'authentifie avec le certificat plutôt qu'avec le mot de passe : rien de ce qui est rattaché aux identifiants du compte ne va s'en apercevoir. Une validité plus courte sur les modèles d'authentification utilisateur ne vous coûte rien sauf de la taille de CRL, pis vous achète une fenêtre plus petite sur chaque incident que vous n'avez pas encore détecté.

Trois : vérifiez si les clés privées sont protégées ou juste étiquetées. Regardez les drapeaux de clé privée sur vos modèles d'authentification client. Une clé « non exportable » dans un KSP logiciel est non exportable pour CAPI et pas plus loin. Un KSP TPM ou une carte à puce, c'est la différence entre un drapeau et un contrôle, pis c'est le seul changement qui rend cette histoire-là pas mal plus courte. Pendant que vous y êtes, activez l'audit de l'AC pour que l'émission et le renouvellement soient enregistrés tout court. C'est l'AuditFilter sur l'AC plus la stratégie d'audit Accès aux objets sur le serveur, pis ça vous donne les 4886 et 4887 pour les requêtes et l'émission. Un renouvellement sur un compte utilisateur à trois heures du matin, ça ne s'enquête pas après coup si rien ne l'a écrit.

Un mot de passe est un secret, pis un secret, ça se change. Un certificat est une déclaration que votre AC a signée, pis elle reste vraie jusqu'à ce que vous disiez le contraire, à voix haute, sur une CRL qu'un contrôleur de domaine lit vraiment.

Votre plan de réponse a une étape pour le secret. Vérifiez s'il en a une pour la déclaration.

Et pendant que vous établissez ce que vos AC ont signé, ça vaut la peine de demander aussi à quelles AC vos contrôleurs de domaine acceptent encore une authentification — y compris celle que vous avez décommissionnée il y a des années, qui n'a pas besoin d'exister pour continuer à signer.