Encontrar y eliminar contraseñas de GPP (cpassword)
Localice cada cpassword de GPP en SYSVOL, copias de seguridad y cachés de cliente, identifique la cuenta expuesta, cambie su contraseña y evite que reaparezca.
Group Policy Preferences permitía antiguamente a los administradores establecer mediante una GPO contraseñas de cuentas locales, credenciales de servicios, cuentas de ejecución de tareas programadas, credenciales de unidades asignadas y contraseñas de orígenes de datos. La contraseña se almacenaba en SYSVOL como atributo cpassword, cifrada con AES-256 mediante una clave que Microsoft publicó en su documentación del protocolo. SYSVOL es legible por todos los usuarios autenticados, y herramientas como Get-GPPPassword y los módulos equivalentes de los frameworks de ataque habituales descifran el valor en un segundo. El botín habitual es una contraseña de administrador local compartida por todas las estaciones de trabajo y servidores, lo que convierte a un solo usuario víctima de phishing en movimiento lateral por todo el parque.
MS14-025 cerró el editor en mayo de 2014, pero dejó los valores existentes donde estaban, y todavía hoy aparecen en las evaluaciones. El pilar de directiva de grupo y SYSVOL muestra la búsqueda básica en SYSVOL. Esta guía cubre el trabajo completo: todos los lugares donde puede esconderse un cpassword, averiguar qué cuenta expone cada uno, cambiar su contraseña correctamente y asegurarse de que no vuelva.
Dónde residen los valores cpassword
Los elementos de preferencia que podían llevar una contraseña la escriben en estos archivos dentro de las carpetas Machine\Preferences o User\Preferences de una GPO:
| Archivo | Tipo de preferencia | Atributo de cuenta que leer |
|---|---|---|
Groups\Groups.xml | Local Users and Groups | userName, newName |
Services\Services.xml | Services | accountName |
ScheduledTasks\ScheduledTasks.xml | Scheduled Tasks | runAs |
Drives\Drives.xml | Drive Maps | userName |
DataSources\DataSources.xml | Data Sources | username |
Printers\Printers.xml | Printers | username |
Los mismos archivos XML también existen fuera de la carpeta Policies activa:
- Copias de seguridad de GPO hechas con la GPMC o
Backup-GPO, a menudo en recursos compartidos de administración o en repositorios de control de cambios. - Cachés del lado cliente: cada cliente guarda una copia del XML de preferencias aplicado en
%ProgramData%\Microsoft\Group Policy\History\{GUID}\(configuración de equipo) y%LocalAppData%\Microsoft\Group Policy\History\(configuración de usuario), que también acaba en plantillas de máquinas virtuales e imágenes de disco. - Copias obsoletas de SYSVOL que quedaron tras una migración de FRS a DFSR o copias manuales en los controladores de dominio (
SYSVOL.bak,SYSVOL_old). - Scripts en
NETLOGONy en las carpetas de scripts de las GPO, que no son cpassword pero a menudo contienen credenciales en texto claro de las mismas cuentas.
Medir: encontrar todas las instancias
Analice el XML en lugar de usar grep, para poder extraer a qué cuenta pertenece cada valor. El script informa de la presencia del valor, nunca del valor en sí.
function Find-GppCpassword {
param([Parameter(Mandatory)] [string[]] $Path)
Get-ChildItem -Path $Path -Recurse -Include Groups.xml, Services.xml, ScheduledTasks.xml,
Drives.xml, DataSources.xml, Printers.xml -ErrorAction SilentlyContinue |
ForEach-Object {
$file = $_.FullName
Select-Xml -Path $file -XPath '//*[@cpassword]' | ForEach-Object {
$n = $_.Node
if ($n.cpassword) {
[pscustomobject]@{
File = $file
GpoGuid = if ($file -match '\{([0-9A-Fa-f-]{36})\}') { $Matches[1] }
Item = $n.ParentNode.name
Account = @($n.userName, $n.accountName, $n.runAs, $n.username, $n.newName) |
Where-Object { $_ } | Select-Object -First 1
Changed = $n.ParentNode.changed
}
}
}
}
}
$dns = (Get-ADDomain).DNSRoot
$hits = Find-GppCpassword -Path "\\$dns\SYSVOL\$dns\Policies", 'D:\GPOBackups'
$hits | ForEach-Object {
$gpo = if ($_.GpoGuid) { Get-GPO -Guid $_.GpoGuid -ErrorAction SilentlyContinue }
$_ | Add-Member -NotePropertyName GpoName -NotePropertyValue $gpo.DisplayName -PassThru
} | Format-Table GpoName, Item, Account, Changed, File -AutoSizeLos atributos cpassword="" vacíos se ignoran porque no contienen ningún secreto. Una coincidencia sin GpoName resoluble suele apuntar a una copia de seguridad o a una carpeta GPT huérfana cuyo GPC se eliminó; las carpetas huérfanas siguen siendo legibles por todos y también deben eliminarse.
Busque copias sobrantes de SYSVOL en cada controlador de dominio, y copias en caché en una muestra de clientes y en sus imágenes maestras:
# En cada DC
Get-ChildItem C:\Windows -Directory -Filter 'SYSVOL*' | Select-Object FullName
# En un cliente o en una imagen montada
Find-GppCpassword -Path "$env:ProgramData\Microsoft\Group Policy\History"Auditar: averiguar qué expone cada valor
Para cada coincidencia, responda a tres preguntas antes de tocar la GPO:
- ¿Qué cuenta? Un elemento de
Groups.xmlconuserName="Administrator"(o una cuenta integrada renombrada mediantenewName) expone al administrador local de todos los equipos del ámbito de la GPO. Un elemento deServices.xmloScheduledTasks.xmlsuele exponer una cuenta de servicio del dominio. - ¿Dónde se aplicó? Compruebe los vínculos y el filtrado de seguridad de la GPO con
Get-GPOReport -Guid <id> -ReportType Html. Una contraseña de administrador local aplicada tanto a servidores como a estaciones de trabajo significa que la misma credencial funciona en ambos tiers. - ¿Sigue siendo válida? Para las cuentas de dominio, compare
pwdLastSetcon la marca de tiempochangeddel elemento. Si la contraseña se estableció por última vez antes de esa fecha o en esa misma fecha, el valor de SYSVOL es casi con seguridad el actual.
Get-ADUser svc-backup -Properties pwdLastSet, lastLogonTimestamp, memberOf |
Select-Object Name, @{n='PwdLastSet';e={[datetime]::FromFileTime($_.pwdLastSet)}},
@{n='LastLogon';e={[datetime]::FromFileTime($_.lastLogonTimestamp)}}, memberOfPara dimensionar el alcance de una entrada de administrador local, cuente los equipos del ámbito de la GPO. La consulta siguiente recorre todas las OU donde está vinculada la GPO; ajústela si la GPO también está filtrada por seguridad a un grupo.
$guid = '<GpoGuid from the scan>' # p. ej. 6AC1786C-016F-11D2-945F-00C04FB984F9
Get-ADObject -LDAPFilter "(gPLink=*$guid*)" -SearchBase (Get-ADDomain).DistinguishedName |
ForEach-Object {
[pscustomobject]@{
LinkedTo = $_.DistinguishedName
Computers = (Get-ADComputer -SearchBase $_.DistinguishedName -Filter * | Measure-Object).Count
}
}Un recuento que incluye a la vez servidores y estaciones de trabajo le indica que la contraseña conectaba tiers: cualquiera que la obtuviera en una estación de trabajo podía iniciar sesión en los servidores con la misma cuenta. Anote este hecho en el hallazgo, porque determina qué parte del parque debe considerar potencialmente accedida.
Si la cuenta expuesta es privilegiada (miembro de algún grupo de administradores, o una cuenta de servicio con derechos sobre sistemas de Tier 0), trátelo como un posible incidente: revise su historial de inicios de sesión en los controladores de dominio (eventos 4624 y 4768) antes de que el cambio de contraseña destruya las pruebas de reutilización.
Aplicar: sustituir, eliminar, cambiar la contraseña
El orden importa. Sustituya primero el mecanismo; de lo contrario, eliminar la preferencia rompe lo que estuviera haciendo. Planifique el trabajo como un cambio por cuenta expuesta y no como un cambio por GPO: la misma cuenta de servicio suele aparecer en varias GPO, y cambiar su contraseña mientras una de ellas sigue distribuyendo la antigua significa que la siguiente actualización de la directiva de grupo rompe el servicio o, en el caso de las cuentas locales, restablece la contraseña al valor expuesto.
- Contraseñas de administrador local → implemente Windows LAPS en las mismas OU, confirme que las contraseñas se están respaldando y después elimine el elemento Local Users and Groups. LAPS cambia inmediatamente la contraseña local en cada equipo, lo que también es su paso de cambio de contraseña.
- Cuentas de servicio y de tareas programadas → migre a una gMSA donde la aplicación lo admita. Las tareas programadas pueden ejecutarse como una gMSA (
New-ScheduledTaskPrincipal -UserId 'CORP\svc-task$' -LogonType Password) o como SYSTEM si la tarea solo necesita derechos locales. - Asignaciones de unidades e impresoras con credenciales → elimine la credencial; el acceso debe usar la propia identidad del usuario, con permisos de recurso compartido que le concedan lo que necesita.
- Orígenes de datos → use autenticación integrada o un almacén de secretos gestionado por la aplicación.
Después, elimine el elemento. Use el Editor de administración de directivas de grupo (Computer o User Configuration > Preferences > el nodo correspondiente > eliminar el elemento) en lugar de editar el XML a mano, para que el número de versión de la GPO se incremente y los clientes procesen el cambio. Si la GPO no contiene nada más, desvincúlela y elimínela tras guardar una copia de seguridad en un lugar con acceso controlado.
Por último, cambie la contraseña. Para las cuentas de dominio, restablezca la contraseña a un nuevo valor aleatorio y actualice todos sus consumidores; si sospecha que un atacante usó la cuenta, revise también a qué tenía acceso en lugar de dar el asunto por cerrado con el restablecimiento. Para las cuentas locales no cubiertas por LAPS, cambie la contraseña en todos los equipos del ámbito. Eliminar una preferencia nunca revierte ni cambia la contraseña que ya estableció.
Elimine o sanee las copias de seguridad de GPO que contengan los valores, elimine las copias sobrantes de SYSVOL y reconstruya o limpie las imágenes maestras que capturaron el historial del lado cliente.
Verificar
Vuelva a ejecutar Find-GppCpassword contra SYSVOL, las ubicaciones de copia de seguridad y una muestra de clientes tras su siguiente actualización de la directiva de grupo; ninguno debe devolver nada. Para las cuentas de dominio, confirme que pwdLastSet es posterior a la fecha del cambio. En los equipos cubiertos por LAPS, confirme que existe una contraseña de LAPS y que se estableció recientemente:
Get-LapsADPassword -Identity WS0142 | Select-Object ComputerName, PasswordUpdateTime, ExpirationTimestampAñada el análisis de SYSVOL a un trabajo programado para que una copia de seguridad restaurada o una GPO heredada importada se detecte en menos de un día. PingCastle también comprueba las contraseñas de GPP, así que señalará una regresión en su evaluación periódica.
Una capa de detección útil es un señuelo deliberado: un Groups.xml en una GPO no vinculada con un cpassword para una cuenta honeytoken que nunca se usa de forma legítima. Cualquier intento de autenticación con esa cuenta (4625, 4771 o 4776 en los controladores de dominio) significa que alguien está recolectando SYSVOL.
Qué se rompe
- Eliminar un elemento Local Users and Groups antes de implementar LAPS deja los equipos con una contraseña de administrador local conocida y no gestionada. Implemente LAPS primero.
- Cambiar la contraseña de una cuenta de servicio del dominio rompe todos los servicios, tareas y aplicaciones que aún tengan la contraseña antigua. Inventaríe los consumidores con los datos de inicio de sesión 4624/4768 antes de restablecerla.
- Eliminar las credenciales de asignación de unidades provoca accesos denegados a los usuarios cuyas propias cuentas carecen de permisos sobre el recurso compartido; corrija antes las ACL del recurso.
- Eliminar las copias de seguridad antiguas de GPO le impide restaurar esas GPO tal como estaban. Conserve una copia saneada si necesita el historial.
- La GPO señuelo será señalada por sus propias herramientas de evaluación; documéntela para que ningún compañero la «corrija».
Lecturas relacionadas: el tema Directiva de grupo y SYSVOL, auditar los permisos de GPO y una directiva de contraseñas que funcione para los controles del lado de las cuentas que limitan el daño de cualquier credencial filtrada.
Preguntas frecuentes
Si elimino el cpassword de SYSVOL, ¿estoy a salvo?
No. Cualquier usuario autenticado pudo leer SYSVOL durante todo el tiempo que el valor estuvo ahí, a menudo años, así que dé por hecho que la contraseña es conocida. Eliminar el elemento de preferencia detiene la exposición nueva, pero no cambia la contraseña en ninguno de los sistemas donde se aplicó. Cambie la credencial en todos los equipos o cuentas que la usan, y busque copias en las copias de seguridad de GPO, las cachés de cliente y las imágenes.
¿Eliminó MS14-025 los valores cpassword existentes?
No. MS14-025 (KB2962486, mayo de 2014) eliminó la posibilidad de establecer contraseñas en los cuadros de diálogo afectados de Group Policy Preferences, de modo que los administradores no pueden crear nuevas mediante el editor. No tocó los archivos XML que ya estaban en SYSVOL, y no impide que alguien importe una copia de seguridad antigua de una GPO que los contenga. Los valores existentes deben localizarse y eliminarse manualmente.
¿Qué debería sustituir a las contraseñas de administrador local de GPP?
Windows LAPS. Establece una contraseña única y aleatoria para el administrador integrado (o una cuenta con nombre) en cada equipo, la cambia periódicamente y la almacena en AD o en Entra ID con acceso controlado por OU y, opcionalmente, cifrada. Elimina por completo el problema de la contraseña compartida, que es lo que hacía tan dañinas las cuentas de administrador local de GPP.
Encontrar y eliminar contraseñas de GPP (cpassword)