Active Directory Management Blog

On our blog you will find of some of our most requested white paper articles on common Active Directory management tasks. SysOp Tools provides active directory management software to assist enterprises with common tasks related to expiring password domain users and domain password policies.

Password Reminder PRO sends email notifications to password expiring users and notifies IT admins of upcoming password related issues.

Password Reset PRO is a secure web based self service solution that allows users to reset an expired password or unlock a locked out account.

For more information visit our website at http://www.sysoptools.com/

Thursday, April 8, 2010

Changing the UserAccountControl Active Directory Attribute with a VB Script – Fix User Accounts marked as System Accounts in AD



Problem: User Accounts in Active Directory are flagged as System Accounts and do not Require a Password (UAC = 544)

An issue we see regularly with domains that contain user accounts which were migrated from NT4 or Novell using 3rd-party migrations tools is, when the accounts are migrated the userAccountControl attribute is not properly set to 512 (an active normal user account object that requires a password) or 514 (a disabled normal user account object) for the accounts. We also see this happen frequently with home-grown user account creation scripts or software that does not set the user account attribute correctly on creation.


If this attribute is not specified for the object at time of creation, Active Directory assigns the account an attribute value of 544 and classifies it as a 'System' object. Not good. With this incorrect attribute, many enterprise software tools for AD will not identify these user accounts properly and you may be left scratching your head wondering why.

For example, our password expiration reminder software Password Reminder PRO will not send expiring password reminders to System accounts, because system accounts are not supposed to belong to a human user. Or perhaps your other user account management software is not categorizing the accounts properly as well.

What is userAccountControl and why is it important?


The actual attribute field for AD user accounts we're discussing here is called userAccountControl.
This field identifies whether the user object should be treated by AD as a non-user "system" account or treated as a normal user account. A "system" account tells AD that a password is not required by the account (even though it may have a password set), and the password is probably managed by the system process which created that account. These system accounts are typically created, managed and used by an integrated root service or inter-domain process (IIS, for example). .

The userAccountControl field value for a normal domain user account is 512 (password is required), but the accounts in question may be set to 544 which is 512 plus 32 (a password is not required).
This presents a potential security risk by allowing a user to maintain a domain logon account with a blank password.

To fix the issue of normal user accounts having an incorrect attribute set, you will have to go through the schema with ADSIEDIT and change these user objects' userAccountControl value to 512, and the problem will be resolved. Changing this field value will not affect anything that your users will notice. However, using ADSIEDIT is dangerous and should be used with care as you are basically editing the 'registry' of your domain! Additionally, doing this one-by-one can take a long time if you have many incorrectly flagged accounts.

Below you will find two VB Script examples that you can easily modify, point to an OU of user objects, and force-set the correct attribute of 512. This is much easier! But do be careful- you DO NOT want to run this script on your entire domain, or you will break the real 'system' accounts that need to be there. ONLY run it on an OU that you know contains problem user objects.



Prerequisites for editing the userAccountControl attribute via scripting
Logon to a DC or member server as a domain administrator and run the below script.


1.       Copy and paste the example script below into notepad.
2.       Change the value for "OU=MyUsers,OU=BadAccounts, " to point to the OU of your problem user objects. You must leave a comma and space after the OU name and before the end quote. Always start OU= with the downlevel OU first (backwards from how it is laid out in your AD Users and Computers).
3.       "intAccValue" is set to 512, which means normal active user account
4.       Save the file with a .vbs extension, for example: ChangeUser .vbs.
5.       Double click ChangeUser .vbs to run the script on the users in the specified OU and set the user account attributes to 512, making them normal user objects. You can also drag/drop the script into an open CMD prompt window then hit enter.

 
Method #1 - Sample Script to Set userAccountControl (copy area in blue and paste in notepad)
 
' ChangeUser .vbs
' Sample VBScript to change user account attributes
' SysOp Tools, Inc – Offered 'as-is' – use with care
' Version 1.0 – March 2007
' --------------------------------------------------------------'
Option Explicit
Dim objOU, objUser, objRootDSE
Dim strContainer, strLastUser, strDNSDomain, intAccValue

' Bind to Active Directory Domain
Set objRootDSE = GetObject("LDAP://RootDSE")
strDNSDomain = objRootDSE.Get("DefaultNamingContext")

' Here is where we set the value to enable the account
' 512 = Enable as normal user account, 514 = Disable as normal user account.
intAccValue = 512

' -------------------------------------------------------------'
' Important - change
"OU=MyUsers,OU=BadAccounts, " to the proper OU path for your user accounts
' -------------------------------------------------------------'
strContainer = "
OU=MyUsers,OU=BadAccounts, "
strContainer = strContainer & strDNSDomain

set objOU =GetObject("LDAP://" & strContainer )

For each objUser in objOU
   If objUser.class="user" then
      objUser.Put "userAccountControl", intAccValue
      objUser.SetInfo
Wscript.Echo strUname
End if
next
Wscript.Echo "User Accounts Have Been Changed"

' End of Free Sample UserAccountControl VBScript


Method #2 - Script to Change userAccountControl, Reset Password and Force User to Change Password at Next Logon
This script builds on Method #1, we recommend you check over the previous script before tackling this more advanced example below.  As you reset the account password, there are two other factors that you may wish to include in the script.  If the account is disabled or is marked with "password never expires" or is flagged as a "System Account", you may wish to enable it and set to a normal, password expiring user with userAccountControl = 512.  In addition to resetting the password and changing the UAC of the account, perhaps you want to force the users to change their password at next logon. You can do all of this with the below script.
Change the OU and "default" password by editing the value for strContainer = "OU=Your Users, " and  strPassword = "!P@ssw0rd".  The OU in strContainer must match the name of your target OU in AD and is case sensitive! Of course you also need to have some users in the OU referenced by strContainer, and if you are using complex passwords your default password must meet the complexity requirements of the domain password policy.

' ResetPasswordAndUAC.vbs
' Sample VBScript to change UAC and force user to change password at next logon
' --------------------------------------------------------------'
Option Explicit
Dim objOU, objUser, objRootDSE
Dim strContainer, strDNSDomain, strPassword
Dim intCounter, intAccValue, intPwdValue

' Bind to Active Directory Domain
Set objRootDSE = GetObject("LDAP://RootDSE")
strDNSDomain = objRootDSE.Get("DefaultNamingContext")

' -------------------------------------------------------------'
' Important change OU= to reflect your target OU
' -------------------------------------------------------------'
strContainer = "OU=Your Users, "
strPassword = "!P@ssw0rd"
strContainer = strContainer & strDNSDomain

' Here is where we set the value to enable or change the UAC on user accounts
' 512 = Enable, 514 = Disable, 544 = System Account.
intAccValue = 512

' Here we force a change of password at next logon
' Change this to -1 if you do not want to enforce change on next login, or delete the command
intPwdValue = 0

' Loop through OU=, setting passwords for all users
set objOU =GetObject("LDAP://" & strContainer )
For each objUser in objOU
   If objUser.class="user" then
      objUser.SetPassword strPassword
      objUser.Put "userAccountControl", intAccValue
      objUser.Put "PwdLastSet", intPwdValue
      objUser.SetInfo
Wscript.Echo strUname
End If
Next

WScript.Echo "Password is " & strPassword & vbCr & _
"UserAccountControl = " & intAccValue & vbCr & "Check " & strContainer

WScript.Quit



Making Changes With The Above Scripts:

1.       UserAccountControl needs a numeric value in order to set the account.  The two common values for user accounts are: 512 = enable and 514 = disable account.  If you are scripting computer accounts substitute a value of 4096. Read the MS article on all possible userAccountControl values
2.       Purely for testing, I suggest setting userAccountControl = 514 and setting the script to point to a new OU called TEST with one test user account in it.  Then open up Active Directory Users and Computers at the OU that corresponds to strContainer "OU=TEST".  What you are looking for is a red X over the account because 514 sets the account to disabled.   Naturally, you could enable the account by setting the intAccValue= back to 512 and running the script again.   Incidentally, Active Directory Users and Computers does not always refresh with F5, so right click and select Refresh from the shortcut menu if you want to refresh the user account view after re-running the script.
3.   Remember, our task is to change all accounts in the OU from an incorrect attribute of 544 to a normal user attribute of 512.
4.   If you are having a tough time finding all of your incorrectly-attributed user accounts in AD, and would like an easy method to globally-view and validate successful changes made by the script, please feel free to use our Password Reminder PRO software as it contains a user account audit console that will display (1) all user accounts with the incorrect attribute and (2) show them as fixed if the script was successful. Our software is FREE to use for 60 days, more than enough time for you to plan and execute domain-wide fixes, no catch or purchase involved.

Before running the script, run Password Reminder PRO's User Reports Console and notice that all of the incorrectly attributed user objects show under the 'Misc Accounts' tab view, with the box on far right under the column of 'SystemAccount' checked. These accounts will be the focus of your fix as the check mark indicates the account has an attribute of 544 (system account).  
 5.  After you run the above script on these accounts and set the attribute to 512, you will see them disappear from the Misc Accounts view and appear under 'Licensed Users' view. Success!
NOTE:
If you get a script error such as "server is unwilling to process request" it may be due to one or more user account having a blank password. AD cannot change the user account to a password expiring user object if no password exists. You may need to use Method #2 to first reset all user passwords plus change the attribute.

Provided by:
SysOp Tools, Inc
       http://www.sysoptools.com/



Instructions for setting userAccountControl

Bulk Reset and Change User Account Passwords in Active Directory via Scripting – VB Script




There may be times when you need to bulk reset user passwords in a domain or OU. We have outlined three VB script methods below. These Active Directory VB scripts are very easy to use and only minor modifications are required.
  • The first method does a password reset to a new permanent password.
  • The second method does a password reset with "must change on next login" set.

  • The third method allows you to change the userAccountControl value and reset passwords, with option to force change on next login. This is handy if you need to change user accounts to password expiring, fix "system account" user objects, or enable / disable user accounts.


  • We STRONGLY recommend testing all scripts first on a test OU with test user objects!


Prerequisites for Running the Reset Password Scripts
Log on as an administrator of the domain, preferably at a domain controller.  Alternatively, connect to the server with Remote Desktop.
Instructions for using the Reset User Password Script Examples
  1. Copy and paste the example script below into notepad or a VBScript editor.

  2. Decide whether to change the OU and "default" password by editing the value for strContainer = "OU=Your Users, " and  strPassword = "!P@ssw0rd".  Of course you need to have some users in the OU referenced by strContainer, and if you are using complex passwords your default password must meet the complexity requirements.


  3. Save the file with a .vbs extension, for example: SetPassword .vbs.
  4. Double click SetPassword .vbs and check the Users container for strUser.
  5. This script DOES NOT set the "must change on next logon" flag. It does a password reset to a permanent new password.


Method #1 Sample Script to Reset User Passwords to a new Permanent Password
This method resets user passwords in the target OU to a new permanent password. It does not set the "must change on next login" flag.
Change the OU and "default" password by editing the value for strContainer = "OU=Your Users, " and  strPassword = "!P@ssw0rd".  The OU in strContainer must match the name of your target OU in AD and is case sensitive! Of course you also need to have some users in the OU referenced by strContainer, and if you are using complex passwords your default password must meet the complexity requirements of the domain password policy.

 
 
' ResetPassword .vbs
' Sample VBScript to set user password in a named OU.
' --------------------------------------------------------------'
Option Explicit
Dim objOU, objUser, objRootDSE
Dim strContainer, strDNSDomain, strPassword

' Bind to Active Directory Domain
Set objRootDSE = GetObject("LDAP://RootDSE")
strDNSDomain = objRootDSE.Get("DefaultNamingContext")

' -------------------------------------------------------------'
' Important change OU= to reflect your target OU
' -------------------------------------------------------------'
strContainer = "OU=Your Users, "
strPassword = "!P@ssw0rd"
strContainer = strContainer & strDNSDomain

' Loop through OU=, setting passwords for all users
set objOU =GetObject("LDAP://" & strContainer )
For each objUser in objOU
If objUser.class="user" then
objUser.SetPassword strPassword
objUser.SetInfo
End If
Next

WScript.Quit

' End of Example VBScript: ResetPassword



Method #2 Sample Script to Reset User Passwords and set "Must Change on Next Login"
This script builds on Method #1, we recommend you check over the previous script before tackling this more advanced example.  As you reset the account password, perhaps you want to force the users to change their password at next logon. The below script will accomplish this nicely.
Change the OU and "default" password by editing the value for strContainer = "OU=Your Users, " and  strPassword = "!P@ssw0rd".  The OU in strContainer must match the name of your target OU in AD and is case sensitive! Of course you also need to have some users in the OU referenced by strContainer, and if you are using complex passwords your default password must meet the complexity requirements of the domain password policy.

Sample Script to Reset Passwords and Force Users to Change Password at Next Logon

 
' ResetTemporaryPassword.vbs
' Sample VBScript to reset password and force user to change password at next logon
' --------------------------------------------------------------'
Option Explicit
Dim objOU, objUser, objRootDSE
Dim strContainer, strDNSDomain, strPassword
Dim intCounter, intAccValue, intPwdValue

' Bind to Active Directory Domain
Set objRootDSE = GetObject("LDAP://RootDSE")
strDNSDomain = objRootDSE.Get("DefaultNamingContext")

' -------------------------------------------------------------'
' Important change OU= to reflect your target OU
' -------------------------------------------------------------'
strContainer = "OU=Your Users, "
strPassword = "!P@ssw0rd"
strContainer = strContainer & strDNSDomain

' Here we force a change of password at next logon
intPwdValue = 0 ' Default is -1

' Loop through OU=, setting passwords for all users
set objOU =GetObject("LDAP://" & strContainer )
For each objUser in objOU
   If objUser.class="user" then
      objUser.SetPassword strPassword
      objUser.Put "userAccountControl", intAccValue
      objUser.Put "PwdLastSet", intPwdValue
      objUser.SetInfo
   End If
Next

WScript.Echo "Password is " & strPassword & vbCr & _
"UserAccountControl = " & intAccValue & vbCr & "Check " & strContainer

WScript.Quit

' End of Free Sample ResetTemporaryPassword Script



Method #3 Sample Script to Enable User or Change User to Password Expiring, Reset Password and Force User to Change Password at Next Logon
This script builds on Method #2, we recommend you check over the previous script before tackling this more advanced example below.  As you reset the account password, there are two other factors that you may wish to include in the script.  If the account is disabled or is marked with "password never expires" or is flagged as a "System Account", you may wish to enable it and set to a normal, password expiring user with userAccountControl = 512.  In addition to resetting the password and changing the UAC of the account, perhaps you want to force the users to change their password at next logon. You can do all of this with the below script.
Change the OU and "default" password by editing the value for strContainer = "OU=Your Users, " and  strPassword = "!P@ssw0rd".  The OU in strContainer must match the name of your target OU in AD and is case sensitive! Of course you also need to have some users in the OU referenced by strContainer, and if you are using complex passwords your default password must meet the complexity requirements of the domain password policy.


 
' ResetPasswordAndUAC.vbs
' Sample VBScript to change UAC and force user to change password at next logon
' --------------------------------------------------------------'
Option Explicit
Dim objOU, objUser, objRootDSE
Dim strContainer, strDNSDomain, strPassword
Dim intCounter, intAccValue, intPwdValue

' Bind to Active Directory Domain
Set objRootDSE = GetObject("LDAP://RootDSE")
strDNSDomain = objRootDSE.Get("DefaultNamingContext")

' -------------------------------------------------------------'
' Important change OU= to reflect your target OU
' -------------------------------------------------------------'
strContainer = "OU=Your Users, "
strPassword = "!P@ssw0rd"
strContainer = strContainer & strDNSDomain

' Here is where we set the value to enable or change the UAC on user accounts
' 512 = Enable, 514 = Disable, 544 = System Account.
intAccValue = 512

' Here we force a change of password at next logon
' Change this to -1 if you do not want to enforce change on next login, or delete the command
intPwdValue = 0

' Loop through OU=, setting passwords for all users
set objOU =GetObject("LDAP://" & strContainer )
For each objUser in objOU
   If objUser.class="user" then
      objUser.SetPassword strPassword
      objUser.Put "userAccountControl", intAccValue
      objUser.Put "PwdLastSet", intPwdValue
      objUser.SetInfo
   End If
Next

WScript.Echo "Password is " & strPassword & vbCr & _
"UserAccountControl = " & intAccValue & vbCr & "Check " & strContainer

WScript.Quit

' End of Free Sample ResetPasswordAndUAC Script


For more guides, visit our website at http://www.sysoptools.com/