Generic accounts security
The title of this post seems a bit contradictory, the use of generic accounts in your domain should be limited to the minimum. Access to your domain ressources should be done with nominative accounts when possible, that’s why you want to avoid generic accouns use. However for political or historical reasons a department of your company might use this type of accounts to access some applications or log on some computers. This account is used by several persons, accordingly the password does not remain secret and across many departments, non-authorized persons might know it and use it for other purposes. If you set up a classic change password policy for this account, then when the password expires, a single person will change it and will probably not notify other users that are entitled to use the account of the new password. That’s why generic accounts are generally flagged “the password never expires”, which is an obvious lack of security. We will demonstrate in this post how to set up an automatic system that will change the password and notify users entitled to use the account.
We will implement a scheduled task, launched with a service account that is granted the sufficient permissions to change our generic account password, that will proceed to change the password and notify the users that are entitled to use the account. This task will run monthly if you want to change the password every month.
First we have to make some modifications on the generic account:
- Leave the flag “passsword never expires”: The password will be changed when our task runs and not when our Default Domain Password Policy (under Windows 2003) or our “Fine Grained Password Policies” (under Windows 2008) requires it.
- Enable the flag “User cannot change password”: Password will only be changed by our service account running the scheduled task or by AD administrators.
- Allow the service account to change the generic account’s password.
Have a look at the following screenshots, s-pwd-supervision is the service account that will run the scheduled task and g-generic is the generic account.
We need to create the scheduled task: The script changepass.vbs will be launched every 1st of the month at 5 am by our service account s-pwd-supervision:
We will now show what is in the script changepass.vbs, first we need to generate a random password and then attribute it to the generic account g-generic. The password generator function was copied from this page,the author is Mark D. MacLachlan, You can find some other functions on the Web. You have to change the DNg-generic value that is the generic account Distinguished Name. “GeneratePassword” function is set up to generate an 8 character long password, you can change this value, as long as you meet your password length policy requirements.
DNg-generic = "CN=g-generic,OU=users,DC=ldap389,DC=info" pwd = generatePassword(8) Set objUser = GetObject("LDAP://"&DNg-generic) objUser.SetPassword pwd Function generatePassword(PASSWORD_LENGTH) Dim NUMLOWER, NUMUPPER, LOWERBOUND, UPPERBOUND, LOWERBOUND1, UPPERBOUND1, SYMLOWER, SYMUPPER Dim newPassword, count, pwd Dim pCheckComplex, pCheckComplexUp, pCheckComplexLow, pCheckComplexNum, pCheckComplexSym, pCheckAnswer NUMLOWER = 48 ' 48 = 0 NUMUPPER = 57 ' 57 = 9 LOWERBOUND = 65 ' 65 = A UPPERBOUND = 90 ' 90 = Z LOWERBOUND1 = 97 ' 97 = a UPPERBOUND1 = 122 ' 122 = z SYMLOWER = 33 ' 33 = !a SYMUPPER = 46 ' 46 = . pCheckComplexUp = 0 ' used later to check number of character types in password pCheckComplexLow = 0 ' used later to check number of character types in password pCheckComplexNum = 0 ' used later to check number of character types in password pCheckComplexSym = 0 ' used later to check number of character types in password ' initialize the random number generator Randomize() newPassword = "" count = 0 DO UNTIL count = PASSWORD_LENGTH ' generate a num between 2 and 10 ' if num <= 2 create a symbol If Int( ( 10 - 2 + 1 ) * Rnd + 2 ) <= 2 Then pwd = Int( ( SYMUPPER - SYMLOWER + 1 ) * Rnd + SYMLOWER ) ' if num is between 3 and 5 create a lowercase Elseif Int( ( 10 - 2 + 1 ) * Rnd + 2 ) > 2 And Int( ( 10 - 2 + 1 ) * Rnd + 2 ) <= 5 Then pwd = Int( ( UPPERBOUND1 - LOWERBOUND1 + 1 ) * Rnd + LOWERBOUND1 ) ' if num is 6 or 7 generate an uppercase Elseif Int( ( 10 - 2 + 1 ) * Rnd + 2 ) > 5 And Int( ( 10 - 2 + 1 ) * Rnd + 2 ) <= 7 Then pwd = Int( ( UPPERBOUND - LOWERBOUND + 1 ) * Rnd + LOWERBOUND ) Else pwd = Int( ( NUMUPPER - NUMLOWER + 1 ) * Rnd + NUMLOWER ) End If newPassword = newPassword + Chr( pwd ) count = count + 1 'Check to make sure that a proper mix of characters has been created. If not discard the password. If count = (PASSWORD_LENGTH) Then For pCheckComplex = 1 To PASSWORD_LENGTH 'Check for uppercase If Asc(Mid(newPassword,pCheckComplex,1)) >64 And Asc(Mid(newPassword,pCheckComplex,1))< 90 Then pCheckComplexUp = 1 'Check for lowercase ElseIf Asc(Mid(newPassword,pCheckComplex,1)) >96 And Asc(Mid(newPassword,pCheckComplex,1))< 123 Then pCheckComplexLow = 1 'Check for numbers ElseIf Asc(Mid(newPassword,pCheckComplex,1)) >47 And Asc(Mid(newPassword,pCheckComplex,1))< 58 Then pCheckComplexNum = 1 'Check for symbols ElseIf Asc(Mid(newPassword,pCheckComplex,1)) >32 And Asc(Mid(newPassword,pCheckComplex,1))< 47 Then pCheckComplexSym = 1 End If Next 'Add up the number of character sets. We require 3 or 4 for a complex password. pCheckAnswer = pCheckComplexUp+pCheckComplexLow+pCheckComplexNum+pCheckComplexSym If pCheckAnswer < 3 Then newPassword = "" count = 0 End If End If Loop 'The password is good so return it generatePassword = newPassword End Function |
We are not done yet, we need to notify the users that are entitled to use the account. For this you can use two methods:
The first is to notify users via Email, for that you can use Blat, Bmail or use the CDO object in your script. You just need to input SMTP server, recipients and the password in the text body of your Email.
The second one is to publish the password on a Web page with an IIS server. Once the password is generated and attributed to our generic account, it will be written in an HTML file located in a folder on our IIS server. You should restrict access to this folder, therefore to this Web page, to nominative accounts that are entitled to use this generic account. For that you just need to set up NTFS rights on this folder:
- Service account running the scheduled task should be granted the write access.
- Nominative accounts that are entitled to use this generic account should be able to read the folder content, we will grant read access to a group containing the nominative accounts that should be aware of the password change. If a non-authorized person tries to access the page they will receive a 401.3 HTTP error.
Security can be further increased on this page: When authorised persons access it, the page remains blank. The user must place the cursor on a particular point on the page for the password to show up. This is done using the Javascript function OnMouseOver. Once your password has been generated by the script, simply add the following lines to your code:
'PathIISHTML is the path of your HTML file on your IIS Server PathIISHTML = "IISserverShareNameFile.html" Const ForWriting = 2 Set FSO = CreateObject("Scripting.FileSystemObject") Set f3 = fso.OpenTextFile(PathIISHTML,ForWriting,1) f3.writeline("<div id='myText' style='visibility: hidden'>"&pwd&"</div>") f3.writeline("<p onMouseOver="&chr(34)&"myText.style.visibility = 'visible'"&chr(34)) f3.writeline("onMouseOut="&chr(34)&"myText.style.visibility = 'hidden'"&chr(34)&">") f3.writeline("<BR>") f3.writeline("</p>") f3.close |
Download the full sample script here:
You will notice that with this type of code it is very simple to generate a HTML page. It can be used in other scripts to present reports a little more clearly than with simple text files.
A final remark: Before setting up a change of password for a generic account, ensure that it is not being used by a scheduled task, autologon workstation or windows service.
This post is also available in: French