If you’ve been reading through some of our other blog posts, you’ll have noticed that we generally like to automate things using Powershell – which quite often requires storing credentials somehow. Preferably not in plain text.
In our existing scripts on this blog, the process has generally involved generating an encryption key, using that key to convert a password to an encrypted string, then storing both in individual files. While that method works fine and has some nice benefits, there’s another alternative that’s worth knowing about: storing credentials in Windows Credential Manager.
I’ll put the code for both methods further down, but first I’d like to list the main differences between the two methods:
Encrypted string in file
- Portable between users and computers
- Can be used in WinPE or wherever Powershell is available
- Only as secure as the NTFS permissions on the files storing the key and encrypted password (someone with read access can use powershell to reveal the password if they know what the files are for)
- Utilises a bit of ‘security by obfuscation’ – depending on how you name the files, no one is going to know what they’re for, and malware/viruses definitely aren’t going to realise the files are encrypted credentials that could be easily reverse-engineered.
- When used with Task Scheduler, the scheduled task can be run as any user/local system
Windows Credential Manager
- Only portable between computers if using roaming profiles; isn’t portable between users
- Can only be used in a full-windows environment that has Windows Credential Manager (ie: not in WinPE)
- Is as secure as the Windows account attached to the credential store (assuming a complex password, pretty secure)
- If the Windows account becomes compromised somehow (you leave the PC unlocked, malware/virus, etc), it’s a relatively simple process to pull any account details you’ve stored in Windows Credential Manager via Powershell.
- When used with Task Scheduler, the scheduled task has to be running as the Windows account attached to the credentials store
So, how do you do each of these?
#-----------Encrypting a password to a file-----------# #File Locations $KeyFile = "C:\Temp\KeyFile.key" $PasswordFile = "C:\Temp\PWFile.pw" #Create the encryption key and dump it to a file $Key = New-Object Byte[] 16 [Security.Cryptography.RNGCryptoServiceProvider]::Create().GetBytes($Key) $Key | out-file $KeyFile #Use the encryption key to encrypt the password and dump the encrypted password to a file $Password = Read-Host -assecurestring "Password: " $Password | ConvertFrom-SecureString -key $Key | Out-File $PasswordFile #-----------Retrieving an encrypted password from a file-----------# #File Locations $KeyFile = "C:\Temp\KeyFile.key" $PasswordFile = "C:\Temp\PWFile.pw" #Grab the key, decrypt the password and store it in a credentials object $key = Get-Content $KeyFile $MyCredential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList "<Username>", (Get-Content $PasswordFile | ConvertTo-SecureString -Key $key)
#-----------Storing credentials in Windows Credential Manager-----------# #Install Packages/Modules if required If(!(Get-PackageProvider -Name 'NuGet')){Install-PackageProvider -Name NuGet -Force} If(!(Get-Module -ListAvailable -Name 'CredentialManager')){Install-Module CredentialManager -Force}else{Import-Module CredentialManager} #Create new credentials - store against LocalMachine (so can be used by other sessions of the current user) New-StoredCredential -Target "PS_Azure" -Persist 'LocalMachine' -Credentials $(Get-Credential) | Out-Null #-----------Retrieving credentials from Windows Credential Manager-----------# #Retreive the credentials $Credentials = Get-StoredCredential -Target 'PS_Azure'