← back to theory
AD

Shadow Credentials, PKINIT & UnPAC-the-Hash

Passwords are only one of the keys that unlock a Kerberos account. Since Windows introduced certificate logon and Windows Hello for Business, an account can also authenticate with a public/private key pair. That alternative authenticator is the whole story of this page: if you can add a key you control to a target account, you can log in as that account without ever knowing its password — and then pull its NT hash back out of the ticket for good measure. This is the mechanism behind the "shadow credentials" edges you see in BloodHound and on the Attack-Path map.

The theme: own the key material, not the secret. A password reset is loud and disruptive; adding a key credential is quiet, reversible, and grants exactly the same logon capability.

PKINIT in one section

Normal Kerberos (recap on the Kerberos page) proves your identity to the KDC with a key derived from your password. PKINIT (Public Key Cryptography for Initial Authentication) replaces that step: in the AS-REQ you present a certificate and sign the request with the matching private key. The KDC validates the certificate (its issuer must be trusted for authentication — the NTAuth store, for AD CS certs) and, satisfied, issues a TGT. From that point you have a normal Kerberos session. This is exactly how smart-card logon and AD CS certificate abuse (ESC1 and friends) end up producing a TGT.

Key Trust vs Cert Trust — why no CA is needed

There are two ways an account can be bound to a key:

ModelHow the key is trusted
Cert TrustA certificate issued by a CA in the NTAuth store (this is AD CS / ESC territory)
Key TrustA raw public key stored on the account object in the msDS-KeyCredentialLink attribute — no CA involved

Key Trust is what Windows Hello for Business uses: the device generates a key pair and publishes the public key to msDS-KeyCredentialLink; the KDC will then accept a PKINIT logon signed by the matching private key. Crucially, populating that attribute needs no certificate authority at all — just write access to the attribute. That is the opening.

The Shadow Credentials attack

If you can write msDS-KeyCredentialLink on a target user or computer — because you hold GenericWrite, GenericAll, WriteProperty on that specific attribute, or the AddKeyCredentialLink right (all common ACL findings) — you simply add your own key credential to the account. You now hold a private key the KDC will accept for that identity, so you PKINIT as them:

pywhisker -d <domain> -u <user> -p '<pass>' --target <victim> --action add
# pywhisker writes the KeyCredential and hands you a PFX + its password, then:
gettgtpkinit.py -cert-pfx victim.pfx -pfx-pass <pfx_pass> <domain>/<victim> victim.ccache
# or the one-shot with Certipy:
certipy shadow auto -u <user>@<domain> -p '<pass>' -account <victim>

certipy shadow auto is the fast path: it adds the key, authenticates, retrieves the TGT, and (see below) prints the NT hash, then cleans up the attribute. Because the change is a single attribute write and is trivially removed, it is far stealthier than resetting a password — the victim never notices a login problem.

Requirements & constraints

RequirementWhy
A KDC that supports PKINITThe DC needs a domain-controller / KDC certificate; most modern domains have one (often via an installed AD CS)
Write access to msDS-KeyCredentialLink on the targetThe core requirement — usually from an ACL edge
2016+ functional level in practiceKey Trust / composite identity support

If there is no PKINIT-capable KDC, the raw key logon will not work — but the same attribute-write can still be paired with AD CS certificate mapping abuses. Shadow Credentials is also the natural payload when you relay to LDAP: relay a machine account, write its msDS-KeyCredentialLink, and you own the computer.

UnPAC-the-Hash — getting the NT hash back

Certificate logon gives you Kerberos, but a lot of the environment still speaks NTLM, and you may want the account's NT hash for pass-the-hash. PKINIT provides it. When the KDC issues a TGT to a PKINIT client, it can include a PAC_CREDENTIAL_INFO structure containing the account's NTLM secret, precisely so that Kerberos-authenticated users can still perform NTLM authentication to downstream services. Ask for those credentials and the ticket hands you the NT hash:

Rubeus.exe asktgt /user:<victim> /certificate:<pfx> /password:<pfx_pass> /getcredentials /nowrap
# or with certipy, which prints the hash after authenticating:
certipy auth -pfx victim.pfx -dc-ip <dc_ip>

This is the "UnPAC-the-hash" trick: it converts certificate access into a reusable NT hash, unifying the certificate and hash worlds. It is why an AD CS ESC1, a shadow credential, or a relayed machine account all ultimately land you at the same place — a hash and a ticket for the victim.

Where it sits in the bigger picture

  • ACL abuse gives you the attribute write → Shadow Credentials.
  • AD CS ESC1/ESC3/etc. give you a cert → the same PKINIT logon, minus the attribute write.
  • Relay to LDAP gives you the write over a coerced machine → Shadow Credentials on a computer, then RBCD or Silver-ticket its services.
  • UnPAC-the-hash then converts any of the above into an NT hash for pass-the-hash and ticket attacks.

Detection & defence

ControlEffect
Audit writes to msDS-KeyCredentialLink (directory change event 5136)A key-credential added to a user/computer by an unexpected principal is the primary signal
Tighten who can write that attribute; review GenericWrite/GenericAll edges in BloodHoundRemoves the precondition entirely
Enforce strong certificate mapping (KB5014754) and the SID security extensionBlunts weak-mapping abuses that pair with PKINIT
Monitor PKINIT AS-REQ (4768 with certificate info) from unusual hostsCatches the logon step
Protect the KDC/AD CS trust and the NTAuth storeControls which certificates the KDC will ever accept

The takeaway

Shadow Credentials weaponises a legitimate feature — key-based logon — by adding a key you control to an account you can write. It is quiet, reversible, and grants full logon as the target; UnPAC-the-hash then extracts the NT hash from the resulting ticket so the access works everywhere, NTLM included. Watch msDS-KeyCredentialLink like a hawk, prune the ACL edges that let low-privileged principals write it, and remember that certificates, key credentials and hashes are three doors into the same room. Tools (pywhisker, Certipy, Rubeus, gettgtpkinit) are in the Toolkit.

Related reading