The Kerberos authentication protocol works with tickets in order to grant access. An ST (Service Ticket) can be obtained by presenting a TGT (Ticket Granting Ticket). That prior TGT can only be obtained by validating a first step named "pre-authentication" (except if that requirement is explicitly removed for some accounts, making them vulnerable to ASREProast). The pre-authentication can be validated symmetrically (with a DES, RC4, AES128 or AES256 key) or asymmetrically (with certificates). The asymmetrical way of pre-authenticating is called PKINIT.
The client has a public-private key pair, and encrypts the pre-authentication data with their private key, and the KDC decrypts it with the client’s public key. The KDC also has a public-private key pair, allowing for the exchange of a session key. (specterops.io)
Active Directory user and computer objects have an attribute called
msDS-KeyCredentialLinkwhere raw public keys can be set. When trying to pre-authenticate with PKINIT, the KDC will check that the authenticating user has knowledge of the matching private key, and a TGT will be sent if there is a match.
There are multiple scenarios where an attacker can have control over an account that has the ability to edit the
msDS-KeyCredentialLink(a.k.a. "kcl") attribute of other objects (e.g. member of a special group, has powerful ACEs, etc.). This allows attackers to create a key pair, append to raw public key in the attribute, and obtain persistent and stealthy access to the target object (can be a user or a computer).
In order to exploit that technique, the attacker needs to:
- 1.be in a domain that supports PKINIT and containing at least one Domain Controller running Windows Server 2016 or above.
- 2.be in a domain where the Domain Controller(s) has its own key pair (for the session key exchange) (e.g. happens when AD CS is enabled or when a certificate authority (CA) is in place).
- 3.have control over an account that can edit the target object's
If those per-requisites are met, an attacker can
- 1.create an RSA key pair
- 2.create an X509 certificate configured with the public key
- 4.authenticate using PKINIT and the certificate and private key
pywhisker.py -d "FQDN_DOMAIN" -u "user1" -p "CERTIFICATE_PASSWORD" --target "TARGET_SAMNAME" --action "list"
Whisker.exe add /target:"TARGET_SAMNAME" /domain:"FQDN_DOMAIN" /dc:"DOMAIN_CONTROLLER" /path:"cert.pfx" /password:"pfx-password"