Powershell Updating Local Admin Passwords Securely 2 of 3
Below is an example of how to remotely (using PowerShell) update and change the Local Administrator password securely. This is not my script, I received this script along with many others from the SANS SEC 505 course. I have not altered it in any way.
Updating the Passwords of the Local Administrator on remote mahcines (You must have a Certificate either from your CA or another Certificate Authority):
This script will recover the local administrator password that you have created with the first part (1 of 3) which is decrypted by your Private Key Certificate.
Copy this text into a PowerShell Script called Recover_PasswordArchive.ps1
[code ]
#################################################################################### #.Synopsis
Recover the plaintext password from an encrypted file originally
created with the companion script named Update-PasswordArchive.ps1.
#.Description
Recover the plaintext password from an encrypted file originally
created with the companion script named Update-PasswordArchive.ps1. The
file is encrypted with a public key chosen by the administrator. The
password generated by Update-PasswordArchive.ps1 is random. Recovery
of the encrypted password from the file requires possession of the
private key corresponding to the chosen public key certificate.
#.Parameter PasswordArchivePath
The local or UNC path to where the encrypted password files are kept.
#.Parameter ComputerName
Name of the computer with the local account whose password was reset
and whose password was encrypted and saved to a file. The computer
name will match the names of files in the PasswordArchivePath. This
parameter can accept a computer name with a wildcard in it.
#.Parameter ShowAll
Without this switch, only the most recent plaintext password is shown.
With this switch, all archived passwords for the computer are shown.
This might be necessary when the passwords of multiple local user
accounts are being managed with these scripts.
#.Example
.\Recover-PasswordArchive.ps1 -ComputerName LAPTOP47
Displays in plaintext the last recorded password updated on LAPTOP47.
The user running this script must have loaded into their local cache
the certificate AND private key corresponding to the certificate used
to originally encrypt the password archive files in the present
working directory. A smart card may be used instead.
#.Example
.\Recover-PasswordArchive.ps1 -PasswordArchivePath \server\share -ComputerName WKS*
Instead of the present working directory of the script, search the
password archive files located in \server\share. Another local
folder can be specified instead of a UNC network path. The wildcard
in the computer name will show the most recent password updates for
all matching computer names in \server\share.
#.Example
.\Recover-PasswordArchive.ps1 -PasswordArchivePath \server\share -ComputerName LAPTOP47 -ShowAll
Instead of showing only the last password update, show all archived passwords
in the \server\share folder for the computer named LAPTOP47.
#Requires -Version 2.0
#.Notes
Author: Jason Fossen, Enclave Consulting (http: //www.sans.org/windows-security/)
Version: 1.0
Updated: 11.Nov.2012
LEGAL: PUBLIC DOMAIN. SCRIPT PROVIDED "AS IS" WITH NO WARRANTIES OR GUARANTEES OF
ANY KIND, INCLUDING BUT NOT LIMITED TO MERCHANTABILITY AND/OR FITNESS FOR
A PARTICULAR PURPOSE. ALL RISKS OF DAMAGE REMAINS WITH THE USER, EVEN IF
THE AUTHOR, SUPPLIER OR DISTRIBUTOR HAS BEEN ADVISED OF THE POSSIBILITY OF
ANY SUCH DAMAGE. IF YOUR STATE DOES NOT PERMIT THE COMPLETE LIMITATION OF
LIABILITY, THEN DELETE THIS FILE SINCE YOU ARE NOW PROHIBITED TO HAVE IT.
#################################################################################### Param ($PasswordArchivePath = ".", $ComputerName = "$env:computername", [Switch ] $ShowAll)
Construct and test path to encrypted password files.
$PasswordArchivePath = $(resolve-path -path $PasswordArchivePath).path
if ($PasswordArchivePath -notlike "*") { $PasswordArchivePath = $PasswordArchivePath + ""
}
if (-not $(test-path -path $PasswordArchivePath)) { "nERROR: Cannot find path: " + $PasswordArchivePath + "
n" ; exit
}
Get encrypted password files and sort by name, which sorts by tick number, i.e., by creation timestamp.
$files = @(dir ($PasswordArchivePath + "$ComputerName+++*") | sort Name)
if ($files.count -eq 0) { "nERROR: No password archives for " + $ComputerName + "
n" ; exit
}
Get the latest archive file only, unless -ShowAll is used.
if (-not $ShowAll){ $files = @($files[ -1 ]) }
Load the current user’s certificates and private keys.
$flags = new-object System.Security.Cryptography.X509Certificates.OpenFlags #ReadOnly
$store = new-object System.Security.Cryptography.X509Certificates.X509Store #CurrentUser
if (-not $? -or ($store.GetType().fullname -notlike "X509Stor")) { "nERROR: Could not load your certificates and private keys.
n" ; exit
}
$store.open($flags)
$certstore = $store.Certificates
$store.close()
if ($certstore.count -eq 0) { "nERROR: You have no certificates or private keys.
n" ; exit
}
Process encrypted password archive files and $output objects.
foreach ($lastfile in $files) ` { $output = ($output = " " | select-object ComputerName,FilePath,UserName,TimeStamp,Thumbprint,Valid,Password)
$output.ComputerName = $($lastfile.Name -split ‘+’)[ 0 ] $output.FilePath = $lastfile.fullname $output.UserName = $($lastfile.Name -split ‘+’)[ 1 ] $output.TimeStamp = [DateTime ][Int64 ]$($lastfile.Name -split ‘+’)[ 2 ] $output.Valid = $false #Assume password recovery will fail. $output.Thumbprint = $($lastfile.Name -split ‘+’)[ 3 ]
Check for password reset failure files.
if ($output.Thumbprint -eq "PASSWORD-RESET-FAILURE") { $output.Password = "ERROR: Try to use prior password(s) for this computer." $output continue }
Read in password archive binary file.
[byte[] ] $ciphertext = get-content -encoding byte -path $lastfile.fullname if (-not $?) { $output.Password = "ERROR: Failed to read " + $lastfile.fullname $output continue }
Load the correct certificate and test for possession of private key.
$certpriv = $certstore | where { $_.thumbprint -eq $output.thumbprint } if (-not $certpriv.hasprivatekey) { $output.Password = "ERROR: You do not have the private key for this certificate." $output continue }
Attempt decryption with private key.
$plaintextout = $certpriv.privatekey.decrypt($ciphertext,$false) #Must be $false for my smart card to work. if (-not $?) { $output.Password = "ERROR: Decryption failed." } else { $output.Password = ([char[] ]$plaintextout -join "") }
Confirm that archive file name matches the nonce string encrypted into the file.
Nonce helps to thwart attackers and can be used for troubleshooting too.
if ($lastfile.name -like $output.Password.substring(0, 60) + "*") { $output.Password = $output.Password.substring(60) #Strip out the 60-char nonce. $output.Valid = $true } else { $output.Password = $output.Password.substring(60) #Strip out the 60-char nonce. $output.Password = "ERROR: Integrity check failure: " + $output.Password.substring(60) + " (" + $output.Password + ")" } $output }
[/code ]