Shadow Credentials Attack
The Shadow Credentials attack (Elad Shamir's
"Shadow Credentials")
abuses write access on a target user / computer object's
msDS-KeyCredentialLink attribute to plant a forged WHfB-style key
credential, then uses PKINIT to obtain a TGT for the target — and finally
UnPAC the Hash
to recover the target's NT hash.
In a single OctoPwn run, this:
- Generates a fresh self-signed certificate + RSA key.
- Embeds the public key in a
KeyCredentialblob and appends it to (not replaces) the target object'smsDS-KeyCredentialLink— capturing the original value first. - Uses the PFX (cert + private key) to do PKINIT as the target.
- Calls
nton the resulting Kerberos session to UnPAC the target's NT hash out of the TGT'sPAC_CREDENTIAL_INFO. - Restores the original
msDS-KeyCredentialLinkvalue, no matter what.
The recovered NT hash is stored in the Credentials Hub and is immediately usable for pass-the-hash, Kerberoast, etc. — and the target's normal authentication keeps working because their existing keys / WHfB devices were preserved.
How it works
- LDAP session is opened against
dctargetusingcredential(NTLM, hidden) and logged in. shadowcred(targetuser)is called on the LDAP session, which under the hood:- Generates a fresh RSA key + self-signed X.509 cert in OctoPwn.
- Builds a
KeyCredential(Microsoft KEYCREDENTIALLINK_BLOB) wrapping that public key, with a freshDeviceIDGUID. - Reads the target user's current
msDS-KeyCredentialLinkvalue and stashes it inoriginal_certs. - Writes back the original list plus the new entry.
- Stores the matching PFX (cert + private key) as a project credential
and returns its
cidalong withoriginal_certsand thetarget_dn. The new PFX cred shows up in the Credentials Hub immediately.
- Open Kerberos session as the target user, using the new PFX. Because the credential is a PFX, the Kerberos session does PKINIT to get a TGT — the KDC validates the certificate against the published key credential we just planted and hands over a TGT for the target.
nton the Kerberos session (do_nt). This issues an additional AS-REQ / TGS-REQ flow that requests theKERB-PA-PAC-OPTIONScontainingPAC_CREDENTIAL_INFO— the recovered NT hash is decrypted out of the response and stored as a project credential. This is the UnPAC the Hash primitive.- Cleanup runs in
finally:setkeycredentiallinkis called ontarget_dnwithoriginal_certs— restoring the attribute to its pre-attack value (preserving any legitimate WHfB devices the target had).
End result: a new NT-hash credential in the Hub, no permanent change on the target object.
Prerequisites
- A valid domain credential with write access on the target object's
msDS-KeyCredentialLinkattribute. Standard ways to have this:- The credential is
Domain Admins(trivial). - The credential / one of its groups has
WritePropertyon the target object via a misconfigured ACL — typical scenario after a successfulRELAYLDAPinto the target's ACL. - The credential is the target's owner (
WriteOwneris enough to grant yourself the write).
- The credential is
- The forest functional level must be ≥ 2016 for
msDS-KeyCredentialLinkto exist as an attribute. On forests stuck at 2012-R2 / older, the attribute is absent and the LDAP write fails withNO_SUCH_ATTRIBUTE. There is no workaround in that case. - At least one DC must support PKINIT (every DC since 2008 does, by default, unless the operator explicitly disabled it).
- The target must not be in
Protected Usersfor the PKINIT TGT to be usable for UnPAC (Protected Users disables PAC_CREDENTIAL_INFO). If you see the TGT come back fine butntfails with "no PAC_CREDENTIAL_INFO" — that's the cause. - Outbound
389/636/TCPtodctarget(LDAP) and88/UDP+TCPfor PKINIT.
Parameters
Normal parameters
dctarget
Target ID of the Domain Controller (LDAP). Required.
credential
Credential ID for the LDAP bind. Must hold write rights on the target's
msDS-KeyCredentialLink.
targetuser
The sAMAccountName of the user (or computer) to take over. Required.
You can target either user or computer accounts — the attack works the same
way; computer takeovers are useful for getting a machine's NT hash without
touching the local SAM.
Advanced parameters
The standard ScannerBaseParameters set: maxruntime, resultsfile,
showerrors, timeout, workercount, wsnetreuse, plus proxy from
CredentialedScanParameters. Defaults are fine.
Output
Where cids is the list of newly-stored credential IDs:
- One PFX credential (the cert + key OctoPwn generated for PKINIT).
- One NT-hash credential for the target user (the actual loot — used for everything you'd normally do with NT-hash material: pass-the-hash, Kerberoast, RBCD, etc.).
Why prefer ShadowCreds over RBCD or DCSync?
| Attack | Required write target | Output | Cleanup automatic? | Detection profile |
|---|---|---|---|---|
| ShadowCreds | msDS-KeyCredentialLink on target user |
NT hash of target | Yes (restore) | LDAP write event + PKINIT login event |
RBCD |
msDS-AllowedToActOnBehalfOfOtherIdentity on target machine |
TGS for target user against target machine | Yes (restore + delete machine) | Computer creation/deletion + LDAP write |
DCSYNC |
DCSync rights on the domain | NT / AES / DPAPI keys for every account | N/A (read-only) | Distinctive 4662 + replication RPC pattern |
ShadowCreds is the cleanest "I have a write on this specific user/computer object" primitive — no machine creation, no SD juggling, just one attribute write that's restored at the end.
Limitations and caveats
- The 1-minute LDAP-replication race. If the LDAP write hits DC-A but
the PKINIT exchange hits DC-B that hasn't replicated yet, PKINIT fails
with
KDC_ERR_CLIENT_NAME_MISMATCHorKDC_ERR_PADATA_TYPE_NOSUPP. Pin both to the same DC, or wait a minute and retry. - Restore can fail silently. Same caveat as
ESC4: if the LDAP session dies between the modify and the finally, the restore won't run and you'll leave a plantedmsDS-KeyCredentialLinkentry on the target. Always check the session log forOriginal certificates restored successfully. If absent, manually callsetkeycredentiallinkto restore. - Some forests reject PKINIT for service accounts with
userAccountControlflagDONT_REQUIRE_PREAUTHset. Edge case, easy to spot from the error message. - Audit signature. A
5136event on the target object will record themsDS-KeyCredentialLinkchange, then a second5136records the restore — within seconds of each other. Mature SOCs treat this as a ShadowCreds signature. - Cannot defeat Protected Users. If the target is in
Protected Users, thent(UnPAC) step fails — but the PKINIT login itself still works (the PFX credential is left in the Hub for downstream use).
See also
- LDAP client →
shadowcred— the attribute-write primitive, callable directly for manual workflows. - LDAP client →
setkeycredentiallink— manual restore / fully custom KeyCredentialLink management. - Kerberos client →
nt— the UnPAC-the-Hash primitive used internally. RBCD— alternative takeover when you have write rights on a machine object.RELAYLDAP— the most common way to acquire the necessary write rights on a target object.- SpecterOps: Shadow Credentials — original technique writeup.
- The Hacker Recipes: UnPAC the Hash — the recovery primitive.