igor - Fotolia

Tip

How to protect PowerShell credentials in task automation

When administrators use unencrypted credentials in PowerShell scripts, they expose sensitive information. Find out the ways to secure credential use with automated tasks.

Task automation eases the administrator's workload, but the IT staff needs to be mindful of properly handling PowerShell credentials to avoid security issues.

Let's say you need to retrieve the BIOS firmware version of 50 infrastructure servers. You operate a Windows 10 administrative workstation under domain user credentials, but need the script to run under domain administrative privileges.

To automate this task, you write the simple PowerShell function shown in Figure 1, but there is a glaring problem in the code.

PowerShell script with credentials
Figure 1. Our initial PowerShell script

The Get-BIOSInfo script works as expected. There is nothing inherently broken, but the issue is an exposed username/password credential set in plaintext. If a malicious user saw this file, they could hijack those credentials. Here are common workarounds to protect PowerShell credentials when running scripts.

Ways to secure PowerShell credentials

One way to authenticate PowerShell script permissions while preventing plaintext exposure is to generate the PSCredential object interactively.

Credentials dialog box
Figure 2. Interactively capturing credentials

The advantage to this is that credentials aren't recorded in the source code. The disadvantage is that you need to run your script interactively. This isn't a workable solution if you need to schedule the script to run unattended.

Let's investigate the $cred variable below:

$cred.GetType()

IsPublic   IsSerial   Name   BaseType

------     ------     ---     ----

True       True    PSCredential System.Object

 

$cred.UserName

adminaccount

 

$cred.Password

System.Security.SecureString

Notice that PowerShell doesn't reveal the plaintext password contained in the Password property. There are ways to uncover that data, however.

One way to authenticate PowerShell script permissions while preventing plaintext exposure is to generate the PSCredential object interactively.

Another method involves storing passwords in a separate file.

Read-Host -AsSecureString | ConvertFrom-SecureString | Out-File -FilePath .\cred.txt

$pass = Get-Content -Path .\cred.txt | ConvertTo-SecureString

$creds = New-Object -TypeName PSCredential -ArgumentList 'admin', $pass

A couple of PowerShell conversion cmdlets transformed the credentials into a secure string password. The Password property of a PSCredential object uses that data type.

PowerShell credentials get stored in encrypted form in a text file.

encrypted password
Figure 3. The encrypted password stored by PowerShell

The advantage to this is that credentials aren't recorded in the source code. The disadvantage is that you need to run your script interactively. This isn't a workable solution if you need to schedule the script to run unattended.

Let's investigate the $cred variable below:

$cred.GetType()

IsPublic  IsSerial  Name     BaseType

--------  --------   ----     --------                                                   

True     True   PSCredential System.Object 

 

$cred.UserName

adminaccount

 

$cred.Password

System.Security.SecureString

Notice that PowerShell doesn't reveal the plaintext password contained in the Password property. There are ways to uncover that data, however.

Another method involves storing passwords in a separate file.

Read-Host -AsSecureString | ConvertFrom-SecureString | Out-File -FilePath .\cred.txt

$pass = Get-Content -Path .\cred.txt | ConvertTo-SecureString

$creds = New-Object -TypeName PSCredential -ArgumentList 'admin', $pass

A couple of PowerShell conversion cmdlets transformed the credentials into a secure string password. The Password property of a PSCredential object uses that data type.

PowerShell credentials get stored in encrypted form in a text file.

The advantage here is convenience, but the disadvantage is the need to protect the password file. For example, you could use NTFS file permissions and the Encrypting File System to prevent the file from falling into the wrong hands.

Credential Manager puts a lock on login credentials

Credential Manager is where Windows stores Windows and web credentials. It's another option to maintain control over login information when used in conjunction with PowerShell.

To open the Credential Manager with PowerShell, enter the following code from the PowerShell prompt:

Show-ControlPanelItem -Name 'Credential Manager'


Credential management with
PowerShell

A developer named Dave Garnar wrote a great PowerShell module called CredentialManager that makes it easier to set and retrieve credentials from Credential Manager programmatically. Install the module by using PowerShellGet and the following code:

Install-Module -Name CredentialManager -Repository PSGallery -Verbose

You then can use the New-StoredCredential cmdlet to create a new credential object and store it in Windows Credential Manager. Note that the -Persist parameter has three options.

  • Session: The credential remains in Credential Manager only during the active PowerShell session.
  • Local Machine: The credential remains in Credential Manager permanently as a Windows credential.
  • Enterprise: The credential remains in Credential Manager permanently as a web credential.

The -Target parameter is effectively a label. By combining Get-Credential and New-StoredCredental, we can define a session-persistent credential.

Get-Credential -UserName 'tim' -Message 'Password please' | New-StoredCredential -Target 'PowerShellCred' -Persist Session

Figure 4 shows the refactored Get-BIOSInfo function code that uses Get-StoredCredential to retrieve the credential securely.

credential code
Figure 4. The adjusted PowerShell code retrieves credentials in a more secure manner.

If you have a Microsoft Azure subscription, then you can store and retrieve credentials by using Azure Key Vault. Adding a helper module, such as AxCredentialVault, makes it more convenient to work with the service.

Install-Module -Name AxCredentialVault -Repository PSGallery -Verbose

Import-Module -Name AxCredentialVault

You then can use the module's cmdlets to create an Azure Key Vault store, set PowerShell credentials and then get them as needed in your code.

Dig Deeper on Microsoft messaging and collaboration