How to use Passwords in PowerShell ?

Passwords in scripts. What are the options and how do you apply them? Are you saving passwords into the body of your script. Just for testing … It’s a a terrifying thing.
Just start with encrypting your passwords always. It’s not that difficult and you will never make the mistake of migrating that test script to production without changing the plain password in it.

In this blog I will show a number of possibilities of using passwords within PowerShell  . We start with a plain password. From there we will go deeper. I will show the following possibilities.

Plain Password

The easiest way is of course to simply put your password as a string. A string is just a piece of plain text. This string can be placed in a variable like in the example below. With this command we create the $password variables with the password in plain text.

$password = "PlainTextPassword"

You can then use this password in your script. Of course I don’t have to explain that it’s not safe but most cmdlets will not accept password in this form. That is why you can also convert it to a SecureString. This type is like the usual string, but its content are encrypted in memory. It uses reversible encrypting so the password can be decrypted when needed, but only by the principal that encrypted it.

$SecurePassword = $password | ConvertTo-SecureString -asPlainText -Force

Instead of a variable with the plain text password you can also provide a pop-up to enter your password with the cmdlet read-host.

Now that we have saved the password as a secure string, we can continue.  A SecureString is actually a password decrypted by the principal that encrypted it, in this case yourself.

Example:

# Convert Back to plain password
  $password       = "V3ryS3cr3t!!"
  $SecurePassword = $password | ConvertTo-SecureString -asPlainText -Force
  $BSTR           = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($SecurePassword)
  $PlainPassword  = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($BSTR) 
  Write-host "Your password is $PlainPassword" -ForegroundColor Green

Note: On my GitHub page you can find the PowerShell module PSPassword. In this module you can find the Convert-SecurestringtoPlainPassword cmdlet.

# Convert Back to plain password via Module
  $SecurePassword = Read-Host -Prompt "Add Password" -AsSecureString
  convert-SecurestringtoPLainPassword  -secureString  $SecurePassword 

Get-Credential

Within PowerShell you have default yhe cmdlet Get-Credential. Get-Credential will generate a PSCredential. PSCredential is a object with a username and password.

With the command below we create a PSCredential variable containing this object.

 $credential = get-credential -Message "test" -UserName "domainusername"

You will receive a pop-up screen to enter your password

The result is the object below with the parameters username and password as a SecureString.

If you do not want  a pop-up to you can use the next command. This command does the same as Get-Credential but you can provide the password yourself. Later in this blog we can get the password from a hash, the Windows Credential Manager, KeePass or HashiCorp Vault so you don’t have to use Get-Credential. The popup is of course very clumsy in an automatic script.

# Set Credential variable
  $Username       = "labadmininistrator"
  $SecurePassword = Read-Host -Prompt "Add Password" -AsSecureString
  $credential     = New-Object System.Management.Automation.PSCredential($Username,$SecurePassword)
  #or
  $credential     = New-object System.Management.Automation.PSCredential -ArgumentList $Username,$SecurePassword   

Hash (personal)

So far we have seen how we can turn a plain text password into a SecureString and even a PSCredential object. Another way we can go about hiding the password is by converting it to a hash.

We again use the Get-Credential cmdlet to create the $credential variable. To get the password hash we convert it from the SecureString with the cmdlet Convertfrom-SecureString.

  $credential     = get-credential -Message "Add credentials" -username "labadmininistrator"
  $hash           = $credential.Password | ConvertFrom-SecureString 

If we look what’s in the $hash variable, we see that we have a hash .

.

This hash can only be used by you and on machine where it was created. You can save it in a text file or put it in your script. See below.

Note: the hash below is normally much longer but I have shortened it so that it fits in the example ?

  $hash           = "01000000d08c9ddf0115d11efbsjgh67tyuhwqkjb36c1030000000d76b88edf78469acb012032fa6fd9acce9a77cf4272205280"
  $SecurePassword = $hash   | ConvertTo-SecureString

You can also export the hash to a file. Later we can import it again.

Note: If you change you’re password you have to regenerate the Hash

# Export hash to text file  
  $hash | out-file C:\powershell\Passwordhash.txt 
# Import hash form text file
  $readhash       = get-content C\:powershell\Passwordhash.txt 
  $SecurePassword = $readhash  | ConvertTo-SecureString

In the PSPowershell module on my GitHub page you can also find a number of useful cmdlets/functions for this. See the examples below.

# Use The functions from the Module
  Create-SecurePasswordFile -username administrator -Exportfile C:\powershell\Passwordhash.txt 
  $credential = Get-PasswordFromSecureFile -importFile C:\powershell\Passwordhash.txt -username administrator
  ConverSecurestringtoPLainPassword -secureString   $credential.Password
  $hash = Create-SecurePasswordHash -username domainnameusername
  $credential = Get-PasswordFromHash -Hash $hash -username domainnameusername
  ConverSecurestringtoPLainPassword -secureString   $credential.Password

Hash with AES(key-file)

Imagine you want to use a hash but make sure others can use it. With PowerShell, we can generate a 256-bit AES encryption key and use that key to access our password file. The AES key is then the key to decrypt the password. The key can be stored in a file or a variable.

Note: this key gives you access to the password so handle it securely!

####################################################################################
#  AES Encryption
####################################################################################
 $password       = "V3rYSecr3t_w1thAES"
 $SecurePassword = $password | ConvertTo-SecureString -asPlainText -Force
# Create AES key 
  [int]$AESKeySize = 32
       $AESKey     = (New-Object Byte[] $AESKeySize)
# Create Random AES Key in length specified in $Key variable.
  [Security.Cryptography.RNGCryptoServiceProvider]::Create().GetBytes($AESKey)
  $AESKey
  $SecurePasswordinHash = ConvertFrom-SecureString -SecureString $SecurePassword -Key $AESKey

To revert to this password, you need the AES key of course.

# Convert back 
  $reversedPassword =  $SecurePasswordinHash | 
                         ConvertTo-SecureString -key $AESKey | 
                           ForEach-Object {[Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($_))}
  $reversedPassword

Secure the AES Key aswell

We had already seen how we could hash our password with our personal token. The AES key could therefore also be hashed that way. This allows anyone who has the AES token to safe this key secure as a hash which can be used to decrypt the password.

#---------------------------------------------------
# Extra : Secure the AES key aswell
#---------------------------------------------------
# Secure The AES Key with personal Hash
  #Create AES Key
  $AESKey               = new-AESKey -AESKeySize 16  
  #Convert AES to Hash 
  $AESKeyHash           = $($AESKey -join " ") | ConvertTo-SecureString -asPlainText -Force  | ConvertFrom-SecureString
  #save Hash to file
  $AESKeyHash | out-file C:powershellSecure_AES_hash.txt
  #read Hash from file
  $AESKeyHash           = get-content  C:\powershell\Secure_AES_hash.txt
# Load Password
  $password       = "Z33rGeheim_metAESHASH"
  $SecurePassword = $password | ConvertTo-SecureString -asPlainText -Force
  $securePassword = Convert-PLainpasswordtoSecurestring -token $password
# Convert Back AES Key for AES Key Hash
  $SecureStringToBSTR  = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($($AESKeyHash | ConvertTo-SecureString))
  $AESKey              = ([System.Runtime.InteropServices.Marshal]::PtrToStringAuto($SecureStringToBSTR)) -split (" ")  
# create a Password hash
  $SecurePasswordinHash = ConvertFrom-SecureString -SecureString $SecurePassword -Key $AESKey
  $SecurePasswordinHash
  #ConvertBAck to plain password
  Convertfrom-SecureHashAES -Hash $SecurePasswordinHash -AESKey $AESKey

Windows Credential Manager

Until now we have seen that we can store passwords via Hash and AES somewhat safely on your machine or in your script instead of in clear text.

Now there is another method for securely storing your passwords. You also make excellent use of the Windows Credential Manager. After all, this is on every Windows machine.

You can read this easily via  PowerShell (under your own credentials). This is easier and safer than a Hash (file).

As far as I know, the Windows Credential Manager cannot be read remotely.

The only thing you need is the PowerShell module CredentialManager which you can install via the Microsoft package manager Nuget (https://www.nuget.org/).

Note : 

  • Find-Module does not work on a 2012 server, but modules also cause problems here!
  • You need an internet connection to download the module.
  • If you do not have an internet run then the command Find-Module -name CredentialManager on a machine that does have an internet connection.
  • Then copy the folder “C:Program FilesWindows  PowerShellModules CredentialManager” to “C:Program FilesWindows  PowerShellModulesCredentialManager” on the machine that does not provide internet and where you want to use the module.
  • You can then import the module with the command:
 # Import Module via the psd1 file
 import-module "C:\Program Files\Windows PowerShell\Modules\CredentialManager\2.0\CredentialManager.psd1" -force -verbose

The PowerShell commands:

# Install and download the CredentialManager PowerShell Module.
Install-Module -name CredentialManager
#Create New Credentials
New-StoredCredential -Target Administrator -UserName Administrator -Password "ZeerGeheimPassword!
# Get Credential
$Credential = Get-StoredCredential -Target Administrator
$Credential 
# Get Credential as Plaintext
$Plaintext = (Get-StoredCredential -Target Administrator -AsCredentialObject).Password
$Plaintext  
# get all saved Credential
Get-StoredCredential  
# Remove Credential
Remove-StoredCredential -Target Administrator
# Check if credential is removed
Get-StoredCredential  

KeePass Password Safe

KeePass is a free open source password manager, which helps you to manage your passwords in a secure way. You can put all your passwords in one database, which is locked with one master key or a key file. So you only have to remember one single master password or select the key file to unlock the whole database.

Note : You can of course safely store this password using the methods above I have created a few KeePass cmdlets/functions in the PSPassword module to communicate with KeePass via PowerShell

####################################################################################
#  KEEPASS
####################################################################################
# GET PASSWORD form keepass
  $PathTokeepassDB      = "C:\powershell\TestDatabase.kdbx"
  $KeePassPassword      = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($(read-host -Prompt "Password of KeePASS ($i/3) : " -AsSecureString))
  Connectto-Keepass -PlainPassword $([System.Runtime.InteropServices.Marshal]::PtrToStringAuto($KeePassPassword))  -PathTokeepassDB $PathTokeepassDB 
  $EntryToFind   = "You're entry in Keepass"
# secure Password
  $Passwordfromkeypass = (get-KeePassPassword -PathToDB  $PathTokeepassDB `
                                              -EntryToFind $EntryToFind `
                                              -keepassPassword $([System.Runtime.InteropServices.Marshal]::PtrToStringAuto($KeePassPassword)) ).password | 
                                                Convertto-SecureString -asPlainText -Force

Save a credential in KeePass.
For this function we can use the Set-KeePassPassword  from the module.

 # Safe an entry with password to Keepass
  $Entryname     = "Powershell"
  $EntryUsername = "Powershell"
  $entryPassword = "ThisIsAPasswordInKeePass"
  set-KeePassPassword -PathToDB $PathTokeepassDB `
                      -Entryname $Entryname `
                      -EntryUsername $EntryUsername `
                      -EntryPassword $entryPassword `
                      -EntryURL "www.google.com" `
                      -EntryNotes "testaccount" `
                      -force `
                      -keepassPassword $([System.Runtime.InteropServices.Marshal]::PtrToStringAuto($KeePassPassword))
  get-KeePassPassword -PathToDB $PathTokeepassDB `
                      -EntryToFind $Entryname `
                      -keepassPassword $([System.Runtime.InteropServices.Marshal]::PtrToStringAuto($KeePassPassword))

Hashicorp Vault with PowerShell.

I have already written a blog about Hashicorp Vault in combination with PowerShell on a Windows host.
To me, Hashicorp is a fantastic tool for storing credentials within your company. With LDAP you can log in with your AD credential in Vault. Hashicorp Vault will use a token and you can use this in your script. In Vault you can create policies with ACL rights by using groups and these groups can be linked to your Active Directory groups. Ideal in a corporate environment. Vault is an API. So it can be read from everywhere.

Note : I will write another blog how to link Hashicorp Vault with Active Directory.

####################################################################################
#  Hashicorp Vault with API and psVault module
####################################################################################
# GitHUB Page 
& "C:Program FilesMozilla Firefoxfirefox.exe" https://github.com/D2CIT/Hashicorp-Vault

Create Secret Engine KV (Key-Value)

# Create  Secret Engine
    $SecretEngineName = "kv_powershell_2"
    $uri              = "$($vaultobject.uri)/v1/sys/mounts/$SecretEngineName" 
    $KV_version       = 2
    #API CAll
    $payload = "{
        `"type`": `"kv`",
        `"options`": {
            `"version`": `"$KV_version`"
        }
    }"
    Invoke-RestMethod -uri $uri -headers $($vaultObject.auth_header) -Method post -body $payload
    #use function from psVault module
    new-VaultSecretEngine -vaultobject $VaultObject -SecretEngineName $SecretEngineName
# Get KV Engine configuration
    $uri     = "$($vaultobject.uri)/v1/$SecretEngineName/config"
    Invoke-RestMethod -Uri $uri -Method get -Headers $VaultObject.auth_header  
# Set KV Engine configuration
    $uri     = "$($vaultobject.uri)/v1/$SecretEngineName/config"
    $payload = '{
        "max_versions": 5,
        "cas_required": false
    }'
    Invoke-RestMethod -Uri $uri -Method post -Headers $VaultObject.auth_header -body $Payload   

Create Secret in Secret Engine

# Create Secret
    $SecretEngineName = $SecretEngineName
    $Application      = "vsphere_api"
    $environment      = "prd" 
    $secretPath       = "$Application/$environment"
    $uri_V1           = "$($vaultobject.uri)/v1/$SecretEngineName/$secretPath" 
    $uri_V2           = "$($vaultobject.uri)/v1/$SecretEngineName/data/$secretPath"
    #Secret to store
    $username         = "Administrator"
    $password         = "P@SSW0rd12!"
    $Server           = "srv01"
    #API Call
    $data ="{`"data`": { `"username`": `"$username`", `"password`": `"$Password`",`"server`": `"$server`" }}"
    Invoke-RestMethod -uri $uri_v2 -headers $($vaultObject.auth_header) -Method post -body $data

Functions from PSVault module

   # use function from psVault module
    set-VaultSecret -VaultObject $vaultobject -secretEnginename $SecretEngineName `
                                              -SecretPath $secretPath `
                                              -username $username `
                                              -password $Password `
                                              -environment $environment `
                                              -tag $tag `
                                              -server $server
    get-VaultSecret -VaultObject $vaultobject -secretEnginename $SecretEngineName -SecretPath $secretPath 

Create PSCredential from Vault

  # Set PSCredential with Username and Password from Hashicorp Vault
    $Secret         = get-VaultSecret -VaultObject $vaultobject -secretEnginename $SecretEngineName -SecretPath $secretPath
    $username       = $Secret.username
    $password       = $Secret.password | ConvertTo-SecureString -asPlainText -Force
    $credential     = New-object System.Management.Automation.PSCredential -ArgumentList $username, $password  

Geef een reactie

Het e-mailadres wordt niet gepubliceerd. Vereiste velden zijn gemarkeerd met *