- Windows 11 taskbar: remove chat icon, customize search field with Group Policy - Tue, Oct 3 2023
- Allow non-admins to access Remote Desktop - Thu, Sep 28 2023
- Which WSUS products to select for Windows 11? - Tue, Sep 26 2023
UserAccountControl is an integer, and each of its bits serves as a flag for one of the settings. For example, the value 2 means the account is disabled, and 32 means it doesn't require a password. For a complete overview, see the following table from Microsoft's Documentation.
Flag | Value | Description |
---|---|---|
SCRIPT | 1 | The logon script will be run. |
ACCOUNTDISABLE | 2 | The user account is disabled. |
Undeclared | 4 | This flag is undeclared. |
HOMEDIR_REQUIRED | 8 | The home folder is required. |
LOCKOUT | 16 | |
PASSWD_NOTREQD | 32 | No password is required. |
PASSWD_CANT_CHANGE | 64 | The user cannot change the password. This is a permission on the user's object. |
ENCRYPTED_TEXT_PWD_ALLOWED | 128 | This indicates whether Active Directory will store the password in the reversible encryption format. |
TEMP_DUPLICATE_ACCOUNT | 256 | This is an account for users whose primary account is in another domain. This account provides user access to this domain, but not to any domain that trusts this domain. |
NORMAL_ACCOUNT | 512 | This is a default account type that represents a typical user. |
INTERDOMAIN_TRUST_ACCOUNT | 2048 | This is a permit to trust an account for a system domain that trusts other domains. |
WORKSTATION_TRUST_ACCOUNT | 4096 | This is a computer account for a computer that is running Microsoft Windows NT 4.0 Workstation, Microsoft Windows NT 4.0 Server, Microsoft Windows 2000 Professional, or Windows 2000 Server and is a member of this domain. |
SERVER_TRUST_ACCOUNT | 8192 | This is a computer account for a domain controller that is a member of this domain. |
DONT_EXPIRE_PASSWORD | 65536 | This represents the password, which should never expire on the account. |
MNS_LOGON_ACCOUNT | 131072 | This is an MNS logon account. |
SMARTCARD_REQUIRED | 262144 | When this flag is set, it forces the user to log on by using a smart card. |
TRUSTED_FOR_DELEGATION | 524288 | When this flag is set, the service account (the user or computer account) under which a service runs is trusted for Kerberos delegation. Any such service can impersonate a client requesting the service. |
NOT_DELEGATED | 1048576 | When this flag is set, the security context of the user is not delegated to a service even if the service account is set as trusted for Kerberos delegation. It can be set using the "Account is sensitive and cannot be delegated" checkbox. |
USE_DES_KEY_ONLY | 2097152 | This restricts this principal to use only Data Encryption Standard (DES) encryption types for keys. |
DONT_REQ_PREAUTH | 4194304 | This account does not require Kerberos pre-authentication for logging on. |
PASSWORD_EXPIRED | 8388608 | The user's password has expired. |
TRUSTED_TO_AUTH_FOR_DELEGATION | 16777216 | The account is enabled for delegation. This is a security-sensitive setting. Accounts that have this option enabled should be tightly controlled. This setting lets a service that runs under the account assume a client's identity and authenticate as that user to other remote servers on the network. |
PARTIAL_SECRETS_ACCOUNT | 67108864 | The account is a read-only domain controller (RODC). This is a security-sensitive setting. Removing this setting from an RODC compromises security on that server. |
If you go through the list, it is apparent that some settings are relevant for security. This applies, for example, to the option that an account does not need a password or allows reversible encryption, whether Kerberos delegation may be used, or whether it has to log on with a smartcard.
With Set-ADAccountControl, PowerShell offers a cmdlet to change these flags, but no counterpart to read and parse the attribute. You can get its value from AD Users and Computers or run Get-ADUser for this purpose.
If you prefer to use PowerShell for this task, the corresponding command looks like this:
Get-ADUser <user> -properties UserAccountControl | select UserAccountControl
Breaking down the attribute value
As a result, you get the decimal value of the attribute, which you then have to interpret yourself. One way to do this is to convert it to a binary number, and then rattle through each of its digits to see if it is set to 1. If it is, then print the corresponding flag.
$UACFlags = @("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" ) #read the attribute value of UserAccountControl $UAC = Get-ADUser <username> -properties UserAccountControl | select UserAccountControl #convert it to a binary representation and reverse the array $a = ([Convert]::ToString($UAC.UserAccountControl,2)).ToCharArray() [array]::Reverse($a) #iterate though the array to see which flag is set 0 .. $a.Length | foreach { if( $a[$_] -eq "1" ) { $UACFlags[$_] } }
The above script converts the binary representation of the attribute value into a character array and reverses its order because the check must start with the lowest digit, i.e., from the back.
Find accounts with a certain flag
With this script, it is quite easy to output all active flags for single accounts. However, in practice, you often want to find all accounts that have a certain flag set.
In some cases, you don't need to drill down into the value of UserAccountControl, because PowerShell provides simpler methods for querying certain flags. For example, this is true for:
- Password never expires: Get-ADUser -Filter 'PasswordNeverExpires -eq $TRUE'
- Password not required: Get-ADUser -Filter 'PasswordNotRequired -eq $TRUE'
- Find disabled accounts in Active Directory: Search-ADAccount -AccountDisabled
- Show locked accounts with PowerShell: Search-ADAccount -LockedOut
But if you want to find out which accounts allow passwords to be stored in a decryptable format, you could use the following query:
Get-ADUser -Filter * -Properties UserAccountControl | Where { $_.UserAccountControl -band 128} | Select name
This call uses a bitwise and to determine if the ENCRYPTED_TEXT_PWD_ALLOWED flag is set.
As you can see from the table above, it represents the eighth digit of the binary number (2 ^ 7 = 128; counting starts at bit 0). If you apply to it a -band- operation with the value 128 and the result is $true, then you know that the flag is set.
Following the same pattern, you can use the values for the other flags in this query:
Get-ADComputer -Filter * -Properties UserAccountControl | Where { $_.UserAccountControl -band 524288 } | Select name
This example would identify computer accounts that are trusted with Kerberos delegation.
Change flags
Once you have identified accounts that are configured inappropriately, you can change the UserAccountControl attribute relatively easily using the Set-ADAccountControl cmdlet mentioned earlier.

The PowerShell cmdlet can set the value for the flags of UserAccountControl using its own parameters
It provides a separate parameter for each flag, which can be set to $true or $false, as needed.
For individual accounts, you can configure some settings of UserAccountControl interactively using Active Directory Users and Computers.
Summary
The UserAccountControl attribute contains several security-related settings for AD accounts. These are implemented as bits of an integer value. Unfortunately, PowerShell does not provide a cmdlet that can be used to drill down into the attribute.
Therefore, you should get UserAccountControl via Get-ADUser or Get-ADComputer and then query for the individual flags using a bit operation.
Subscribe to 4sysops newsletter!
However, if you find undesirable settings, you can change them very easily with Set-ADAccountControl.