The UserAccountControl attribute can be used to configure several account settings in Active Directory. This applies, for example, to the expiration date of passwords or to Kerberos delegation. An AD audit should check this attribute regularly. This can be done using PowerShell, and there is a cmdlet for changing flags.

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.

FlagValueDescription
SCRIPT1The logon script will be run.
ACCOUNTDISABLE2The user account is disabled.
Undeclared4This flag is undeclared.
HOMEDIR_REQUIRED8The home folder is required.
LOCKOUT16
PASSWD_NOTREQD32No password is required.
PASSWD_CANT_CHANGE64The user cannot change the password. This is a permission on the user's object.
ENCRYPTED_TEXT_PWD_ALLOWED128This indicates whether Active Directory will store the password in the reversible encryption format.
TEMP_DUPLICATE_ACCOUNT256This 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_ACCOUNT512This is a default account type that represents a typical user.
INTERDOMAIN_TRUST_ACCOUNT2048This is a permit to trust an account for a system domain that trusts other domains.
WORKSTATION_TRUST_ACCOUNT4096This 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_ACCOUNT8192This is a computer account for a domain controller that is a member of this domain.
DONT_EXPIRE_PASSWORD65536This represents the password, which should never expire on the account.
MNS_LOGON_ACCOUNT131072This is an MNS logon account.
SMARTCARD_REQUIRED262144When this flag is set, it forces the user to log on by using a smart card.
TRUSTED_FOR_DELEGATION524288When 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_DELEGATED1048576When 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_ONLY2097152This restricts this principal to use only Data Encryption Standard (DES) encryption types for keys.
DONT_REQ_PREAUTH4194304This account does not require Kerberos pre-authentication for logging on.
PASSWORD_EXPIRED8388608The user's password has expired.
TRUSTED_TO_AUTH_FOR_DELEGATION16777216The 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_ACCOUNT67108864The 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.

Get the value of the userAccountControl attribute from AD Users and Computers

Get the value of the userAccountControl attribute from AD Users and Computers

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

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.

Changing account settings in AD Users and Computers

Changing account settings in AD 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.

avataravatar
0 Comments

Leave a reply

Your email address will not be published.

*

© 4sysops 2006 - 2022

CONTACT US

Please ask IT administration questions in the forums. Any other messages are welcome.

Sending

Log in with your credentials

or    

Forgot your details?

Create Account