Part 2: Managing Local Administrator Passwords
Overview
This is Part 2 of a multi-part series on managing local admin passwords. In case you missed it, you can view Part 1 here
The Problem
One of the challenges associated with generating a random local admin password is how to make the generated password as random as possible. In many of the example PowerShell random password generation scripts that I have seen, the system.random object is used as the random character generator. The problem with this is that that particular object, while random, is not as good as using the System.Security.Cryptography.RNGCryptoServiceProvider. This object generates a cryptographically random number and is documented on MSDN here.
The Solution
The following function relies on a cryptographic random character generation function to create a random password of configurable complexity and length using cryptographically randomly generated characters. If the function is called without any parameters then the function will generate a 16 character password with 2 lowercase and 2 upper case characters, 2 numbers, 2 special characters, and no ambiguous characters.
#==================================================================================
# Generate Random Password
#==================================================================================
function fnGeneratePassword
{Param ([int]$PassLength=16,[int]$iLCaseNeeded=2,[int]$iUCaseNeeded=2,[int]$iNumNeeded=2,[int]$iSpecNeeded=2,[int]$AvoidAmbiguous=$true)
#Calculates minimum password length required to meet complexity
$MinPwdLength = $iLCaseNeeded + $iUCaseNeeded + $iNumNeeded + $iSpecNeeded
#Feedback if password is too short
if($PassLength -lt $MinPwdLength){
#Convert Integer to String
$MinPwdLength = [string]$MinPwdLength
#Log Output
#fnLog -LogPath $LogDir -LogFileName $LogFileName -Data "ERROR: Requested password length must be $MinPwdLength or more characters"
#Exit
return "ERROR"
}
#NonAmbiguous Characters
$sLCase = "abcdefghijkmnpqrstuvwxyz"
$sUCase = "ABCDEFGHJKLMNPQRSTUVWXYZ"
$sNum = "23456789"
$sSpec = "!#$%&()*+,-./:;<=>?@[\]^_{}~"
#Adds Ambiguous Characters if desired
if($AvoidAmbiguous -eq $false){
$sLCase += "lo";$sUCase += "IO";$sNum += "01";$sSpec += "`"'``|"
}
#Creates Character Arrays
$sLCase = $sLCase.ToCharArray();$sUCase = $sUCase.ToCharArray();$sNum = $sNum.ToCharArray();$sSpec = $sSpec.ToCharArray()
$sFullSet = $sLCase + $sUCase + $sNum + $sSpec; $aCharacters = @{}
#Selects Lower Case Characters
for($i =0;$i -lt $iLCaseNeeded;$i++){
$aCharacters.Add((fnRandom),$sLCase[(fnRandom) % $sLCase.Count])
}
#Selects Upper Case Characters
for($i =0;$i -lt $iUCaseNeeded;$i++){
$aCharacters.Add((fnRandom),$sUCase[(fnRandom) % $sUCase.Count])
}
#Selects Numerical Characters
for($i =0;$i -lt $iNumNeeded;$i++){
$aCharacters.Add((fnRandom),$sNum[(fnRandom) % $sNum.Count])
}
#Selects Special Characters
for($i =0;$i -lt $iSpecNeeded;$i++){
$aCharacters.Add((fnRandom),$sSpec[(fnRandom) % $sSpec.Count])
}
#Selects from all characters until password length is met
for($i=$aCharacters.Count;$i -lt $PassLength;$i++){
$aCharacters.Add((fnRandom),$sFullSet[(fnRandom) % $sFullSet.Count])
}
#Sorts Characters
$aCharacters = $aCharacters.GetEnumerator() | Sort-Object Name
return New-Object System.String(($aCharacters | % {$_.value}),0,$aCharacters.Length)
}
The function above calls the fnRandom function which is what actually creates the random characters. fnRandom is below.
#==================================================================================
# Returns random number
#==================================================================================
function fnRandom{
#Crypto Random Number Generator
$rng = New-Object System.Security.Cryptography.RNGCryptoServiceProvider
#Byte Storage
[byte[]]$byte = New-Object byte[] 4
#Generate Random Value
$rng.GetBytes($byte)
#Convert to Integer
return [system.bitconverter]::touint32($byte,0)
}
After loading both functions into memory using PowerShell ISE, you can then call fnGeneratePassword without any parameters to see some of the sample random passwords as shown below.
The keen observer may have noticed that I commented out the fnLog function in the examples above. Both functions above are a part of a larger local administrator password management solution which I will reveal in greater detail in the 3rd part of this series. What you have so far is a configurable random password generator which can be integrated into pretty much any random password script, and a cryptographically random character generator which can also be used for many different purposes.
The upcoming parts in this series will explain how to do the following:
- Connect to Active Directory using a Kerberos secured connection
- Set the local administrator password based on fnGeneratePassword
- Write a log file that logs the success and failure of each function
- Create a confidential attribute to store the local admin password
- Create fnMain to control the order in which all of the functions are called
- Create a XAML based secure password viewer to retrieve the local admin password
Each portion of the solution is modularized using functions which allows the IT administrator to make use of all or just parts of the solution and allows the IT administrator to easily integrate any portion they wish into a larger script or even a different solution entirely. So stay tuned as Part 3 discusses how to create a Kerberos encrypted and signed connection to Active Directory.
Comments
- Anonymous
January 01, 2003
Looking forward to part3 - Anonymous
February 17, 2014
Par - Anonymous
February 17, 2014
Overview In this multi part series I will walk you through how to manage the local admin password - Anonymous
February 17, 2014
This is Part 4 of a multi-part series on managing local admin passwords. In this part I will discuss how to update the password of a local user account using PowerShell - Anonymous
February 17, 2014
Overview This is Part 5 of a multi-part series on managing local admin passwords. In this part I will - Anonymous
April 02, 2014
This is Part 6 of a multi-part series on managing local admin passwords. In this part I will discuss how to extend the Active Directory schema to create a new confidential attribute which is where the workstation's local administrator password will - Anonymous
May 13, 2014
This is Part 7 of a multi-part series on managing local admin passwords. In this part I will provide - Anonymous
May 15, 2014
Pingback from Manage Local Admin Passwords – Additional Comments | JohanPersson.nu - Anonymous
August 12, 2014
This is Part 8 and the final part of a multi-part series on managing local admin passwords. In this part