Tags:
The passwords of local administrative accounts should be changed regularly and these passwords should be different from one computer to the next. But how can this been done securely and conveniently? How can it scale to thousands of computers? And how can this be done for free?
The Securing Windows and PowerShell Automation course at SANS (course SEC505) includes free PowerShell scripts to manage local account passwords. Download the scripts in the SEC505 zip file from BlueTeamPowerShell.com, then look inside that zip archive for the \Day3\UpdatePasswords folder.
These PowerShell scripts are intended to be relatively easy to understand and modify, you don't have to be a PowerShell guru, just have some basic familiarity. Like all scripts in the SEC505 zip file, these scripts are in the public domain too.
If you would prefer a non-PowerShell commercial product to manage admin passwords, here are few to consider:
- Synergix
- ManageEngine Password Manager Pro
- Cyber-Ark Privileged Identity/Session Management
- Lieberman Software Password Manager
- Thycotic Secret Server
- PasswordCourier Password Management
- NetWrix Privileged Account Manager
- AutoCipher
What about Microsoft LAPS?
There is also Microsoft's own Local Administrator Password Solution (LAPS). LAPS is free. You can get technical support when using LAPS, and it comes with a GUI client for admins as well as a PowerShell module.
However, note that LAPS 1) stores passwords in plaintext in the Active Directory database, using AD permissions to restrict access to the passwords, 2) requires an update to the Active Directory schema, 3) requires a Group Policy client-side extension to be installed (an MSI package) on all managed hosts, 4) is not for stand-alone servers or workstations because of the Active Directory and Group Policy components, 5) can only be used to manage one local user account on each machine, no more, 6) we don't have access to the C++ source code of the LAPS client-side extension if we need to customize it, and 7) though the LAPS tools themselves encrypt passwords while in transit over the network, admins must take care to use network encryption when using other tools when reading the passwords out of AD, e.g., a third-party utility might use LDAP in plaintext by default (this has nothing to do with LAPS per se, it's only something to be aware of).
The solution presented below never stores or transmits passwords in plaintext, not even temporarily, does not require an Active Directory schema update (or AD for that matter), does not require a Group Policy extension, works on stand-alone computers, can manage any number of local user accounts, you have access to the PowerShell source code for inspection or customization (it's in the public domain), and it works with any SMB server, including Samba and TrueNAS.
However, the solution does require, at a minimum, PowerShell to be on every managed host, and it scales best in an Active Directory environment with Group Policy. You will also need a digital certificate, either self-signed or from a PKI, but this is a good thing because it uses the public key from the certificate for encryption.
If the choice is between LAPS and doing nothing, then LAPS is far better than nothing. The PowerShell solution here is better though.
Solution
A trusted administrator should obtain or create a certificate and private key, then export that certificate to a .CER file into a shared folder (\\server\share\cert.cer). Any certificate from any source will do, but a 2048-bit or larger RSA public key from one's own PKI is preferred.
Copy the Update-PasswordArchive.ps1 script into that shared folder (\\server\share).
Using Group Policy, SCCM, a third-party EMS, schtasks.exe or some other technique, create a scheduled job on every computer that runs once per week (or every night) under Local System context which executes the following command:
powershell.exe \\server\share\Update-PasswordArchive.ps1 -CertificateFilePath \\server\share\cert.cer -PasswordArchivePath \\server\share -LocalUsername Administrator
This resets the password on the local Administrator account (or whatever account is specified at the command line) with a 15-25 character, random complex password. The password is encrypted in memory with the public key of the certificate (cert.cer) and saved to an archive file to the specified share (\\server\share).
When a password for a computer (for example, laptop47) needs to be recovered, the trusted administrator should run the following PowerShell script on the administrator's local workstation:
Recover-PasswordArchive.ps1 -PasswordArchivePath \\server\share -Computername laptop47 -Username administrator
This downloads the necessary encrypted files, decrypts them locally in memory using the private key of the administrator, then outputs the plaintext password within PowerShell. The password can then be piped into other commands to open an RDP session, copy files, execute another command, etc.
Requirements
PowerShell 2.0 or later must be installed on both the computer with the local user account whose password is to be reset and also on the administrators' computers who will recover these passwords in plaintext.
The Update-PasswordArchive.ps1 script, which resets the password, must run with administrative or Local System privileges.
The private key for the certificate cannot be managed by a Cryptography Next Generation (CNG) key storage provider, such as the Microsoft Software Key Storage Provider or Enhanced Cryptographic Provider.
Also, the certificate you use must have the "Key Encipherment" purpose in the "Key Usage" list in the properties of that certificate (see the Details tab). You get this when the template for the certificate on the Certification Authority (CA) has "Encryption" listed as an allowed purpose in the properties of that template (see the Request Handling tab in the properties of the certificate template).
Note that the scripts are not compatible with FIPS Mode being enabled in Windows.
Testing Example
From the SEC505 zip file, copy the Day3\UpdatePasswords folder to your hard drive.
In File Explorer, double-click the "Password-is-password.pfx" file to import the test certificate and private key into your current user store (accept all the defaults). The password is "password".
Open PowerShell with administrative privileges and run this command to reset the password on the Guest account:
.\Update-PasswordArchive.ps1 -LocalUserName Guest -CertificateFilePath .\PublicKeyCert.cer
Do a "dir" listing and you will see a new file with a very long name, similar to the following:
MYCOMPUTER+Guest+635108515647128197+F5FF0247B0CF6A8D2EBA4A141CB095F3
If you open the file in Notepad or a hex editor, you'll see that it has been encrypted with the public key in the PublicKeyCert.cer file. The private key for this public key has already been imported into your local user certificate store, hence, you can use your private key to extract the password from the encrypted file. Unless hackers have stolen your private key, they will not be able to decrypt the file and obtain the password inside it.
To obtain the plaintext password, run this command:
.\Recover-PasswordArchive.ps1 -ComputerName $env:computername -UserName Guest
The output is an object with the plaintext password and other properties, similar to this:
ComputerName : MYCOMPUTER FilePath : MYCOMPUTER+Guest+635108515647128197+F5FF024E83D2EBA4A141CB095F3 UserName : Guest TimeStamp : 7/31/2021 7:12:44 AM Thumbprint : F5FF0247B0CF6A81148CE83D2EBA4A141CB095F3 Valid : True Password : TheRandomComplexPassword
The password property can now be piped into other commands or copied into the wetware clipboard through your retina.
To see the full help for this script, run:
get-help -full .\Update-PasswordArchive.ps1
Notes
The password is never sent over the network in plaintext, never saved to disk in plaintext, and never exposed as a command-line argument, either when resetting the password or when recovering it later. The new password is generated randomly in the memory of the PowerShell process running on the computer where the password is reset. The process runs for less than a second as Local System as a background process.
Different certificates can be used at different times, as long as their private keys are available to the administrator. When recovering a password, the correct certificate and private key will be used automatically, even if multiple certificates are in use. A smart card can be used too. The script has been successfully tested with the Common Access Card (CAC) used by the U.S. military and DoD. It also works with YubiKeys.
If the shared folder is not accessible to the computer when the scheduled job runs, the password is not reset. The script first tests access to the shared folder before resetting the password.
If multiple administrators must be able to recover the plaintext passwords, export the relevant certificate and private key to a PFX file and import it into each administrator's local profile. Because this is not a certificate used to uniquely identify a person or device (non-repudiation is not an intended feature), everyone on the help desk could have a copy of its private key.
To delegate authority to different administrators over different computers, then simply use different public/private key pairs. When using Group Policy to create the scheduled job on the machines in an organizational unit, for example, any certificate can be specified, and this does not have to be the same certificate used for all machines in a domain. The corresponding private keys can be shared with whatever subset of administrators is desired. If the private key is on a smart card, that card can be physically protected from unauthorized admins.
The password update script writes to the local Application event log on the machine where it runs (Source: PasswordArchive, Event ID: 9013). When the password is used to log into the computer, this can also be logged if the appropriate audit policies are enabled. The SEC505 zip file includes another script (SendTo-SysLog.ps1) if you'd like to modify the update script to also send a syslog message whenever the script runs.
The script can only be used to reset the passwords of local accounts, not domain accounts in Active Directory, though it could be modified for this purpose.
Threats
Keep the private key for the certificate used to encrypt the password archive files secure, such as on a smart card. This is the most important factor. Do not use the sample keys provided here for anything other than testing.
If the private key for the certificate is compromised, create a new key pair, replace the certificate file (.CER) in the shared folder, and immediately remotely trigger the scheduled job on all machines using PowerShell remoting, Group Policy, schtasks.exe or some other tool. Once all passwords have been changed, the fact that the old private key has been compromised does not mean any current passwords are known.
Use an RSA public key at least 2048 bits in size. The public key encrypts the random 256-bit Rijndael key in each file which is used to encrypt the password in that file. Each archive file has a different Rijndael key. RSA and Rijndael are used for backwards compatibility (using AES explicitly requires .NET Framework 3.5 or later). Rijndael was selected by NIST for the AES cipher.
Prevent modification of the Update-PasswordArchive.ps1 script itself by digitally signing the script, enforcing script signature requirements, and using restrictive NTFS permissions. Only allow NTFS read access to the script to those identities (computer accounts) which need to run it. Use NTFS auditing to track changes to the script.
Attackers may try to corrupt the existing password archive files to prevent access to current passwords. Each archive file contains an encrypted SHA256 hash of the username, computer name, and password in that file in order to detect bit-flipping attacks; the hash is checked whenever a password is recovered.
To deter file deletion, it's best to store the certificate and archive files in a shared folder whose NTFS permissions only allow the client computer accounts the following permissions:
Principal: Domain Computers
Apply to: This folder, subfolders and files
Allow: Full Control
Deny: Delete subfolders and files
Deny: Delete
Deny: Change permissions
Deny: Take ownership
Deny: Create folders/append data
Principal: Domain Computers
Apply to: Files only
Deny: Create files/write data
The trusted administrators can be granted Full Control to the archive files, certificates, and scripts as needed of course. The above permissions are for just for Domain Computers.
An attacker might try to generate millions of spoofed archive files and add them to the shared folder. This is possible because the script and public key would be accessible to the attacker too. NTFS auditing on the share can log which computer(s) added the spoofed files and when. The archive files might be digitally signed, but with what key? We must assume the attacker can extract any signing keys from kernel memory on the computers that have already been compromised. Realistically, though, a DoS attack in which millions of new archive files are created would likely be of low value for the attacker since it would be easy to detect, easy to log the name or IP of the machine creating the new files, easy to use timestamps in the shared folder to identify post-attack files, nightly backups of the archive files can be retained for months, and the DoS attack would not allow the hacker to expand the hacker's existing control over new machines. Besides, the benefit to us of managing local administrative account passwords correctly far exceeds the potential negative of this sort of DoS attack.
IPsec permissions that limit access to the SMB ports of the file server is recommended, but not for the encryption, but for restricting access to the SMB ports (TCP 139/445) based on group memberhips, e.g., domain computer, administrators, help desk personnel, etc.
Tips
The output of the Recover-PasswordArchive.ps1 script can be piped into other scripts to automate other tasks which require the plaintext password, such as executing commands, doing WMI queries, opening an RDP session, or immediately resetting the password again when finished.
When recovering a password, you can pipe the password into Set-Clipboard or the built-in clip.exe utility to put the password into the clipboard, like this:
\\controller\password-archives\Recover-PasswordArchive.ps1 -PasswordArchivePath \controller\password-archives -ComputerName laptop47 -UserName Administrator | Select-Object -ExpandProperty password | clip.exe
What prevents an endless accumulation of encrypted password archive files in the shared folder? The CleanUp-PasswordArchives.ps1 script will remove older or obsolete archive files which are no longer needed. Run this script as a scheduled job once per month. See the help in that script for its command-line parameters to customize what it deletes, e.g., by default it keeps the last five password archive files for each computer and username combination, but this can be changed.
To optimize the performance of the Recover-PasswordArchive.ps1 script when there are more than 100,000 files in the folder containing the password archives, disable 8.3 file name generation and strip all current 8.3 names on the volume containing that folder. Search the Internet on "fsutil.exe 8dot3name" to see how.
To maximize fault tolerance and scalability, use Distributed File System (DFS) shared folders across two or more servers, and back up the folder at least weekly. You can also use SMB with TrueNAS, Ceph or Gluster. With Group Policy or Intune management of the scheduled jobs, the solution can scale to large networks.
The solution works on stand-alone computers as well, but the scheduled task, shared folder, and permissions will need to handled appropriately; for example, a wrapper script will likely be needed to automate the creation of the scheduled task and the copying of the encrypted password file to some kind of archival server, perhaps via SSH.
You can also perform an immediate password update with commands like these, but wrapped in a function or placed in another script:
Copy-Item -Path .PublicKeyCert.cer -Destination \\laptop47\c$ Invoke-Command -ComputerName laptop47 -filepath .\Update-PasswordArchive.ps1 -argumentlist "C:\publickeycert.cer","Administrator","c:" Copy-Item -Path \\laptop47\c$\laptop47+Administrator+* -Destination C:\LocalFolder Remove-Item -Path \\laptop47\c$\PublicKeyCert.cer Remove-Item -Path \\laptop47\c$\laptop47+Administrator+*
The above Invoke-Command can be done by specifying UNC paths instead, but this requires delegation of credentials to the remote computer, which is not ideal for limiting token abuse attacks, so the certificate and archive files should be copied back-and-forth manually. Besides, wrapped in a function or script with some error-handling code, all these steps would be hidden from us anyway.
Each password archive file name includes a ticks timestamp number. To manually convert the ticks timestamp in the file name (e.g., 635093865618276588) to a human-readable date and time in PowerShell, run this command:
[DateTime][Int64] 635093865618276588
If all the password archive files are moved to another volume, it would be convenient to reset the NTFS LastWriteTime property of the archive files to match the ticks timestamp in the archive file names themselves, such as with this command:
dir *+*+* | foreach { $_.LastWriteTime = [DateTime][Int64] $(($_.Name -split '+')[2]) }
Update History
24.Sep.2013: Thanks to Timothy Carroll for uncovering a formatting bug in the password generator found in Update-PasswordArchive.ps1. The fix does not affect compatibility with earlier versions of the other scripts or with previously-created encrypted password files.
25.Sep.2013: Added support for the minimum and maximum length of the random password generated.
13.Nov.2013: This is a breaking change from the prior 2.x versions. This update adds much improved support for keyboards and code pages outside of US-EN for international users, each encrypted archive file now includes an SHA256 hash for integrity checking, and a StatusMessage property has been added to the output for troubleshooting and easier international conversions.
16.Nov.2013: Removed a dependency on .NET Framework 3.5 which, unfortunately, also changed the file format again, hence, at version 4.0.
20.May.2014: Updated notes and scripts about incompatibility with CNG key storage providers. Thanks to Daniel F. for the heads up.
9.Jun.2015: Updated notes and scripts to warn about certificates not having the Key Encipherment allowed usage.
3.Sep.2015: Added a few notes about Microsoft LAPS.
22.Oct.2015: Added a note about FIPS Mode incompatibility.
18.May.2021: Fixed download link.