UserAccountControl is one of the most important attributes of the user and computer objects in Active Directory. This attribute determines the state of the account in the AD domain: whether the account is active or locked out, whether the option of password change at the next logon is enabled, whether users can change their passwords, etc. However, not all administrators are fully aware of how the UserAccountControl attribute works and what it is used for in AD
Contents:
- UserAccountControl Attribute/Flag in Active Directory
- Decoding UserAccountControl Values with PowerShell Script
- How to Set UserAccoutControl Attribute in AD with PowerShell?
UserAccountControl Attribute/Flag in Active Directory
Open the properties of any AD account in the Active Directory Users and Computers (ADUC, dsa.msc
) console and go to the Account tab. Please, pay attention to the group of user attributes in the Account Options section. Here you can see the following options:
- User must change password at next logon;
- User cannot change password;
- Password never expires;
By default, the domain password policy in AD requires the user to change their password periodically.
- Store password using reversible encryption (not safe);
- Account is disabled;
- Smart card is required for interactive logon;
- Account is sensitive and cannot be delegated;
- Use Kerberos DES encryption types for this account;
- This account supports Kerberos AES 128/256-bit encryption;
- Do not require Kerberos Pre-authentication.
Each of these user account attributes is essentially a bit value (flag) that can be either 1 (True
) or 0 (False
). However, these values are not stored as separate AD attributes, instead the UserAccountControl attribute is used.
The total value of all options specified above is stored in the value of UserAccountControl attribute. Instead of storing all these options in different user attributes, a single Active Directory attribute is used. The UserAccountControl is a bitmask, each bit of which is a separate flag and has a value On (True) or Off (False). Depending on the enabled account options a user will have different UserAccountControl attribute values. You can see the current value of the attribute in the corresponding Attribute Editor tab or using the Get-ADUser cmdlet in PowerShell:
get-aduser jkelly -properties *|select name,UserAccountControl | ft
In this example, the value of the attribute is 0x10202 (decimal value is 66050). What do these numbers mean?
The table of available flags of AD accounts is given below. Each flag corresponds to a certain UserAccountControl bit, and UserAccountControl value equals the sum of all flags.
UserAccountControl Flag | HEX Value | Decimal Value |
SCRIPT (Running the logon script) | 0x0001 | 1 |
ACCOUNTDISABLE (The account is disabled) | 0x0002 | 2 |
HOMEDIR_REQUIRED (The home folder is required) | 0x0008 | 8 |
LOCKOUT (The account is locked) | 0x0010 | 16 |
PASSWD_NOTREQD (No password is required) | 0x0020 | 32 |
PASSWD_CANT_CHANGE (Prevent user from changing password) | 0x0040 | 64 |
ENCRYPTED_TEXT_PWD_ALLOWED (Store password using reversible encryption) | 0x0080 | 128 |
TEMP_DUPLICATE_ACCOUNT (An account of a user, whose primary account is in another domain) | 0x0100 | 256 |
NORMAL_ACCOUNT (A default account, a typical active account) | 0x0200 | 512 |
INTERDOMAIN_TRUST_ACCOUNT | 0x0800 | 2048 |
WORKSTATION_TRUST_ACCOUNT | 0x1000 | 4096 |
SERVER_TRUST_ACCOUNT | 0x2000 | 8192 |
DONT_EXPIRE_PASSWORD (user accounts with passwords that don’t expire) | 0x10000 | 65536 |
MNS_LOGON_ACCOUNT | 0x20000 | 131072 |
SMARTCARD_REQUIRED (To log on to the network, the user needs a smart card) | 0x40000 | 262144 |
TRUSTED_FOR_DELEGATION | 0x80000 | 524288 |
NOT_DELEGATED | 0x100000 | 1048576 |
USE_DES_KEY_ONLY | 0x200000 | 2097152 |
DONT_REQ_PREAUTH (Kerberos pre-authentication is not required) | 0x400000 | 4194304 |
PASSWORD_EXPIRED (The user password has expired) | 0x800000 | 8388608 |
TRUSTED_TO_AUTH_FOR_DELEGATION | 0x1000000 | 16777216 |
PARTIAL_SECRETS_ACCOUNT | 0x04000000 | 67108864 |
For example, there is a regular account for which the requirement to change the password is disabled. The userAccountControl value is calculated as follows:
NORMAL_ACCOUNT (512) + DONT_EXPIRE_PASSWORD (65536) = 66048
Accordingly, the value of userAccountControl from my example (66050) was obtained as follows:
NORMAL_ACCOUNT (512) + DONT_EXPIRE_PASSWORD (65536) + ACCOUNTDISABLE (2) = 66050
A disabled user account has 514 as a userAccountControl value:
(NORMAL_ACCOUNT (512)+ ACCOUNTDISABLE (2) = 514
Default UserAccountControl values for typical domain objects:
- A regular AD user: 0x200 (512);
- A domain controller: 0x82000 (532480);
- A workstation/server: 0x1000 (4096).
You can use LDAP filters to select objects from AD objects with a certain useraccountcontrol value. For example, to display all active (normal) accounts:
Get-ADUser -Properties * -ldapFilter "(useraccountcontrol=512)"
Display the list of all disabled user accounts:
Get-ADUser -Properties * -ldapFilter "(useraccountcontrol=514)"
The list of accounts with a non-expiring password option:
Get-ADUser -Properties * -ldapFilter "(useraccountcontrol=66048)"
You can sum the required bits from the table and select AD objects using the command:
$UserAccountControl_hex= 0x10000 + 0x0080 + 0x200000
Get-ADUser -Filter {UserAccountControl -band$UserAccountControl_hex}
Decoding UserAccountControl Values with PowerShell Script
To make it more convenient, I want to have a tool to automatically convert the value of UserAccountControl bitmask into a human-transparent form. Let’s try to write a simple PowerShell function that takes the decimal value of UserAccountControl attribute and returns the list of enabled account options. Since UserAccountControl is a bitmask, you can assign a text description to each bit.
I wrote this PowerShell function DecodeUserAccountControl to convert UserAccountControl value into a readable form:
Function DecodeUserAccountControl ([int]$UAC)
{
$UACPropertyFlags = @(
"SCRIPT",
"ACCOUNTDISABLE",
"RESERVED",
"HOMEDIR_REQUIRED",
"LOCKOUT",
"PASSWD_NOTREQD",
"PASSWD_CANT_CHANGE",
"ENCRYPTED_TEXT_PWD_ALLOWED",
"TEMP_DUPLICATE_ACCOUNT",
"NORMAL_ACCOUNT",
"RESERVED",
"INTERDOMAIN_TRUST_ACCOUNT",
"WORKSTATION_TRUST_ACCOUNT",
"SERVER_TRUST_ACCOUNT",
"RESERVED",
"RESERVED",
"DONT_EXPIRE_PASSWORD",
"MNS_LOGON_ACCOUNT",
"SMARTCARD_REQUIRED",
"TRUSTED_FOR_DELEGATION",
"NOT_DELEGATED",
"USE_DES_KEY_ONLY",
"DONT_REQ_PREAUTH",
"PASSWORD_EXPIRED",
"TRUSTED_TO_AUTH_FOR_DELEGATION",
"RESERVED",
"PARTIAL_SECRETS_ACCOUNT"
"RESERVED"
"RESERVED"
"RESERVED"
"RESERVED"
"RESERVED"
)
return (0..($UACPropertyFlags.Length) | ?{$UAC -bAnd [math]::Pow(2,$_)} | %{$UACPropertyFlags[$_]}) -join ” | ”
}
Let’s check what value 66050 of UserAccountControl means:
DecodeUserAccountControl 66050
As you can see, the script has returned that the following flags are enabled for this user:
ACCOUNTDISABLE | NORMAL_ACCOUNT | DONT_EXPIRE_PASSWORD
The same script can be used to decode the UserAccountControl values on the fly when getting the information about AD accounts in a convenient form using the Get-ADUser or Get-ADComputer cmdlets, for example:
get-aduser ms-pam -properties *|select @{n='UsrAcCtrl';e={DecodeUserAccountControl($_.userAccountControl)}}
ACCOUNTDISABLE | NORMAL_ACCOUNT | DONT_EXPIRE_PASSWORD
get-adcomputer rome-dc01 -properties *|select @{n='UsrAcCtrl';e={DecodeUserAccountControl($_.userAccountControl)}}
SERVER_TRUST_ACCOUNT | TRUSTED_FOR_DELEGATION
How to Set UserAccoutControl Attribute in AD with PowerShell?
You can change individual options of the UserAccountControl attribute in Active Directory using the Set-ADUser and Set-ADComputer PowerShell cmdlets. Both of these cmdlets have separate options, for example:
- AccountNotDelegated
- AllowReversiblePasswordEncryption
- CannotChangePassword
- ChangePasswordAtLogon
- KerberosEncryptionType
- PasswordNeverExpires
- PasswordNotRequired
- PrincipalsAllowedToDelegateToAccount
The computer account password in AD provides a trust relationship between the computer and the domain.
So, to change some user options, you need to use the following command:
Set-ADUser jkelly –CannotChangePassword:$true -PasswordNeverExpires:$true
Or you can use the generic Set-UserAccountControl cmdlet:
Set-ADAccountControl -Identity jkelly -CannotChangePassword $True -PasswordNeverExpires $True
You can also enable both of these user account options directly by setting the exact value via the UserAccountControl attribute:
Set-ADUser jkelly -Replace @{UserAccountControl= 66048}