Atributo userAccountControl de Active Directory explicado

Si administras Active Directory, antes o después te encontrarás con un valor numérico que parece sacado de la nada: userAccountControl = 66048, 514 o 544. Es el atributo userAccountControl (UAC), un único número que resume casi todo el estado de una cuenta de usuario o de equipo: si está habilitada, si su contraseña caduca, si puede iniciar sesión sin contraseña, si usa tarjeta inteligente o si es de confianza para delegar. En esta guía aprenderás a leerlo, a decodificarlo con PowerShell, a buscar cuentas por una característica concreta y a usarlo para detectar configuraciones peligrosas.
Qué es userAccountControl y cómo funciona
El atributo guarda un número entero que es la suma de varios indicadores (flags), donde cada uno ocupa un bit distinto. Cada opción de la pestaña Cuenta de un usuario en Usuarios y equipos de Active Directory (la casilla «La contraseña nunca caduca», «La cuenta está deshabilitada»…) activa uno de esos bits. Como los valores son potencias de dos, cualquier combinación se puede representar con un único número y descomponerse después sin ambigüedad.
Por ejemplo, una cuenta de usuario normal vale 512 (NORMAL_ACCOUNT). Si la deshabilitas se le suma el indicador ACCOUNTDISABLE (2), y queda en 514. Si además marcas «La contraseña nunca caduca» (65536), pasa a ser 66050. Los indicadores son acumulativos, por eso un valor tan grande como 66048 es solo 512 + 65536: una cuenta normal, habilitada, cuya contraseña no caduca.
Tabla de indicadores
Esta es la lista de indicadores que documenta Microsoft, con su valor en hexadecimal y en decimal. Ldp.exe muestra los valores en hexadecimal, y ADSI Edit, en decimal:
| Indicador | Hex | Decimal | Significado |
|---|---|---|---|
| SCRIPT | 0x0001 | 1 | Se ejecutará el script de inicio de sesión. |
| ACCOUNTDISABLE | 0x0002 | 2 | La cuenta está deshabilitada. |
| HOMEDIR_REQUIRED | 0x0008 | 8 | Se requiere carpeta principal. |
| LOCKOUT | 0x0010 | 16 | Cuenta bloqueada (ver nota más abajo). |
| PASSWD_NOTREQD | 0x0020 | 32 | No se requiere contraseña. |
| PASSWD_CANT_CHANGE | 0x0040 | 64 | El usuario no puede cambiar la contraseña (se gestiona como permiso). |
| ENCRYPTED_TEXT_PWD_ALLOWED | 0x0080 | 128 | Permite almacenar la contraseña con cifrado reversible. |
| NORMAL_ACCOUNT | 0x0200 | 512 | Cuenta de usuario típica. |
| INTERDOMAIN_TRUST_ACCOUNT | 0x0800 | 2048 | Cuenta de confianza entre dominios. |
| WORKSTATION_TRUST_ACCOUNT | 0x1000 | 4096 | Cuenta de equipo (estación o servidor miembro). |
| SERVER_TRUST_ACCOUNT | 0x2000 | 8192 | Cuenta de equipo de un controlador de dominio. |
| DONT_EXPIRE_PASSWORD | 0x10000 | 65536 | La contraseña no caduca nunca. |
| SMARTCARD_REQUIRED | 0x40000 | 262144 | Obliga a iniciar sesión con tarjeta inteligente. |
| TRUSTED_FOR_DELEGATION | 0x80000 | 524288 | Confiable para delegación Kerberos. |
| NOT_DELEGATED | 0x100000 | 1048576 | La cuenta no se delega aunque el servicio sea de confianza. |
| USE_DES_KEY_ONLY | 0x200000 | 2097152 | Solo cifrado DES para las claves de Kerberos. |
| DONT_REQ_PREAUTH | 0x400000 | 4194304 | No requiere preautenticación Kerberos. |
| PASSWORD_EXPIRED | 0x800000 | 8388608 | La contraseña ha caducado. |
| TRUSTED_TO_AUTH_FOR_DELEGATION | 0x1000000 | 16777216 | Habilitada para delegación (sensible a la seguridad). |
| PARTIAL_SECRETS_ACCOUNT | 0x04000000 | 67108864 | Cuenta de un controlador de solo lectura (RODC). |
Una nota importante de la documentación: en dominios con nivel funcional de Windows Server 2003 o superior, los indicadores LOCKOUT y PASSWORD_EXPIRED se sustituyeron por un atributo calculado distinto, msDS-User-Account-Control-Computed. Por eso no debes confiar en el bit 16 de userAccountControl para saber si una cuenta está bloqueada; usa en su lugar la propiedad LockedOut de PowerShell (lo vemos más abajo).
Valores comunes y qué significan
- 512: usuario normal, habilitado.
- 514: usuario normal, deshabilitado (512 + 2).
- 544: usuario habilitado que no requiere contraseña (512 + 32). Es una configuración que conviene revisar.
- 546: usuario deshabilitado sin contraseña requerida (512 + 2 + 32).
- 66048: usuario habilitado con la contraseña sin caducidad (512 + 65536).
- 66050: usuario deshabilitado con contraseña sin caducidad (512 + 2 + 65536).
- 262656: usuario habilitado que requiere tarjeta inteligente (512 + 262144).
- 4096: cuenta de equipo (estación de trabajo o servidor miembro).
- 532480: cuenta de equipo de un controlador de dominio (8192 + 524288).
Cómo leer el atributo con PowerShell
Con el módulo de Active Directory instalado puedes leerlo directamente:
Get-ADUser -Identity l.gomez -Properties userAccountControl | Select-Object Name, userAccountControl
# Y las propiedades ya calculadas, más fáciles de interpretar
Get-ADUser -Identity l.gomez -Properties Enabled, LockedOut, PasswordExpired, PasswordNeverExpires, PasswordNotRequired |
Select-Object Name, Enabled, LockedOut, PasswordExpired, PasswordNeverExpires, PasswordNotRequired
Para ver qué indicadores activos tiene un valor, puedes usar una pequeña función que descomponga el número con el operador -band (AND bit a bit):
function Get-UacFlags {
param([int]$Valor)
$banderas = [ordered]@{
SCRIPT = 1; ACCOUNTDISABLE = 2; HOMEDIR_REQUIRED = 8; PASSWD_NOTREQD = 32
PASSWD_CANT_CHANGE = 64; ENCRYPTED_TEXT_PWD_ALLOWED = 128; NORMAL_ACCOUNT = 512
INTERDOMAIN_TRUST_ACCOUNT = 2048; WORKSTATION_TRUST_ACCOUNT = 4096; SERVER_TRUST_ACCOUNT = 8192
DONT_EXPIRE_PASSWORD = 65536; SMARTCARD_REQUIRED = 262144; TRUSTED_FOR_DELEGATION = 524288
NOT_DELEGATED = 1048576; USE_DES_KEY_ONLY = 2097152; DONT_REQ_PREAUTH = 4194304
TRUSTED_TO_AUTH_FOR_DELEGATION = 16777216; PARTIAL_SECRETS_ACCOUNT = 67108864
}
$banderas.GetEnumerator() | Where-Object { $Valor -band $_.Value } | ForEach-Object Key
}
Get-UacFlags 66050 # NORMAL_ACCOUNT, ACCOUNTDISABLE, DONT_EXPIRE_PASSWORD
Cómo buscar cuentas por un indicador
Aquí está el uso más práctico del atributo: encontrar todas las cuentas que tienen un indicador concreto. Para ello se usa una regla de coincidencia bit a bit de LDAP, cuyo identificador es 1.2.840.113556.1.4.803 (AND) y 1.2.840.113556.1.4.804 (OR):
# Cuentas deshabilitadas (bit 2)
Get-ADUser -LDAPFilter '(userAccountControl:1.2.840.113556.1.4.803:=2)' | Select-Object Name, SamAccountName
# Cuentas cuya contraseña no caduca (bit 65536)
Get-ADUser -LDAPFilter '(userAccountControl:1.2.840.113556.1.4.803:=65536)' | Select-Object Name, SamAccountName
# Con la sintaxis de filtro de PowerShell
Get-ADUser -Filter 'userAccountControl -band 65536' | Select-Object Name
Las cuentas deshabilitadas que no deberían seguir ahí, las que tienen la contraseña sin caducidad y las que no requieren contraseña son, en conjunto, una de las primeras revisiones de higiene del directorio. Si quieres aprender a gestionar las bajas y el ciclo de vida de las cuentas, consulta la guía de usuarios y grupos de Active Directory.
Cómo modificar el atributo (con cuidado)
Siempre que puedas, usa los cmdlets específicos en lugar de editar el número a mano: son más legibles y evitan errores.
Disable-ADAccount -Identity l.gomez
Enable-ADAccount -Identity l.gomez
Set-ADUser -Identity l.gomez -PasswordNeverExpires $false
Set-ADAccountControl -Identity l.gomez -DoesNotRequirePreAuth $false
Si necesitas cambiar un bit concreto de forma directa, hazlo con operaciones de bits para no pisar los demás: leer, modificar solo ese bit y volver a escribir.
$u = Get-ADUser -Identity l.gomez -Properties userAccountControl
# Activar "la contraseña nunca caduca" (OR bit a bit)
Set-ADUser -Identity $u -Replace @{ userAccountControl = ($u.userAccountControl -bor 65536) }
# Desactivarlo (AND con el complemento)
Set-ADUser -Identity $u -Replace @{ userAccountControl = ($u.userAccountControl -band (-bnot 65536)) }
Haz siempre una prueba con una cuenta de laboratorio, y recuerda que algunos valores solo los puede establecer el propio servicio de directorio.
Indicadores que debes vigilar por seguridad
- DONT_REQ_PREAUTH (4194304): permite solicitar un ticket sin demostrar la contraseña, y es la base del ataque conocido como AS-REP roasting, que permite intentar romper la contraseña sin conexión. Solo debería estar activo en casos muy justificados.
- TRUSTED_FOR_DELEGATION (524288): la delegación sin restricciones permite a un servicio suplantar a los usuarios que se conectan a él. Fuera de los controladores de dominio, conviene revisarla y sustituirla por delegación restringida.
- PASSWD_NOTREQD (32): cuentas que pueden tener contraseña vacía. Debe revisarse cada una.
- DONT_EXPIRE_PASSWORD (65536): aceptable en cuentas de servicio justificadas (idealmente cuentas administradas de grupo), no en usuarios normales.
- ENCRYPTED_TEXT_PWD_ALLOWED (128): almacena la contraseña con cifrado reversible; solo se debería usar si una aplicación antigua lo exige.
- USE_DES_KEY_ONLY (2097152): restringe a un cifrado obsoleto y débil.
# Cuentas que no requieren preautenticación Kerberos
Get-ADUser -LDAPFilter '(userAccountControl:1.2.840.113556.1.4.803:=4194304)' | Select-Object Name, SamAccountName
# Cuentas con delegación sin restricciones (excluyendo controladores de dominio)
Get-ADObject -LDAPFilter '(userAccountControl:1.2.840.113556.1.4.803:=524288)' |
Where-Object { $_.DistinguishedName -notlike '*OU=Domain Controllers*' } | Select-Object Name, ObjectClass
Estos informes conviene generarlos de forma periódica, por ejemplo con una tarea programada; en la guía de tareas programadas con PowerShell verás cómo hacerlo. Y si necesitas repasar el uso de Get-ADUser y los filtros, consulta los 10 comandos de PowerShell imprescindibles.
Cuentas de equipo y controladores de dominio
El atributo también existe en los objetos de equipo. Los valores por defecto que documenta Microsoft son 4096 para una estación de trabajo o servidor miembro, y 532480 (0x82000) para un controlador de dominio, que es la suma de SERVER_TRUST_ACCOUNT (8192) y TRUSTED_FOR_DELEGATION (524288). Un controlador de solo lectura (RODC) añade además el indicador PARTIAL_SECRETS_ACCOUNT.
Preguntas frecuentes
¿Por qué el valor de una cuenta bloqueada no cambia en userAccountControl?
Porque el bloqueo de cuenta se almacena en otro atributo (lockoutTime) y se expone mediante msDS-User-Account-Control-Computed. Para consultarlo, usa Get-ADUser -Properties LockedOut o Search-ADAccount -LockedOut.
¿Qué diferencia hay entre 512 y 544?
544 es 512 más 32: la cuenta es normal pero tiene el indicador PASSWD_NOTREQD, lo que significa que puede existir sin contraseña. Es una diferencia importante desde el punto de vista de la seguridad.
¿Cómo sé qué indicadores tiene un valor cualquiera?
Descomponlo en potencias de dos o usa la función Get-UacFlags de esta guía: va comprobando cada bit con -band.
Conclusión
El atributo userAccountControl es la suma de indicadores independientes, por lo que cada valor se puede descomponer siempre de una única manera. Aprende los más comunes (512, 514, 544, 66048), usa la regla de bits de LDAP para buscar cuentas por un indicador y revisa con regularidad las configuraciones sensibles, como la falta de preautenticación o la delegación sin restricciones. Y para cambiarlo, prefiere los cmdlets específicos antes que editar el número a mano.