Skip Ribbon Commands
Skip to main content

Quick Launch

Todd Klindt's home page > Todd Klindt's Office 365 Admin Blog > Posts > Save Encrypted Passwords to Disk with PowerShell
April 14
Save Encrypted Passwords to Disk with PowerShell

I’ve posted a lot of PowerShell scripts here over the years. Some good, some not-so-good. Okay, mostly not-so-good. Besides my very obvious lack of PowerShell prowess, one thing has constantly bugged me about a few of the scripts I’ve written, they contain passwords in plain text. Here are a few examples:

How to Upload Files to SharePoint 2013 with PowerShell

How to schedule SharePoint backups with PowerShell

The PowerShell script I use to create Active Directory users

Using PowerShell to set up a test environment

How to use PowerShell to replace DCPROMO in Windows Server 2012

In each of those scripts I did a bad, bad thing, I put the password for a privileged account in plain text. Shame on me. My penance for this sin is that I have to write this blog post, explaining a more secure way to handle this situation. I also said “Hail Jeff Snover” 100 times.

The TLDR version is that instead of putting the passwords in plain text in the script, we should save them, encrypted in a file, and use them from there. PowerShell is constantly improving. It’s getting stronger. I’m pretty sure Skynet uses PowerShell when it takes over the world. SharePoint 2010 uses PowerShell v2, which has one way to save encrypted passwords. SharePoint 2013 uses PowerShell v3, which has a better way. I’ll show you both here. Both versions will work with SharePoint 2013, only the first will work with SharePoint 2010. And yes, while you can install PowerShell v3 on a server running SharePoint 2010, you can’t use the SharePoint 2010 SnapIn in PowerShell v3, so you’d have to use the PowerShell v2 regardless.

SharePoint 2010 (PowerShell v2)

First, we need to create the file that contains the encrypted password. Here is the PowerShell I use to do that:

# Create-EncryptedPasswordFile
$password = Read-Host "Enter Password: " -AsSecureString
$filename = Read-Host "Enter file to save as: "
$secure = ConvertFrom-SecureString $password
$secure | Out-File $filename

Here’s what it looks like in practice:


The password I entered was the venerable pass@word1. You can see the file it creates is plain text, but it bears no resemblance at all to pass@word1 so bad guys can’t see what your passwords are.

Of course creating the encrypted password is only half the battle, and maybe even the easy half. You actually have to be able to use the password for this to be any fun. Let’s look at the How to Upload Files to SharePoint 2013 with PowerShell blog post. Scenario 2 could take advantage of this. Let’s look at the piece of the original script that dealt with authentication:

# Since we’re doing this remotely, we need to authenticate
$securePassword = ConvertTo-SecureString "pass@word1" -AsPlainText -Force
$credentials = New-Object System.Management.Automation.PSCredential ("contoso\johnsmith", $securePassword)

There’s that password in plain text <shudder>. Let’s fix that. Here’s what it would look like using the file we created above:

# Since we’re doing this remotely, we need to authenticate
$temp = Get-Content C:\temp\secretfile.txt
$securePassword = ConvertTo-SecureString -String $temp

$credentials = New-Object System.Management.Automation.PSCredential ("contoso\johnsmith", $securePassword)

Now you can run your scripts with piece of mind. Let’s check out the SharePoint 2013 version.

SharePoint 2013 (PowerShell v3)

The PowerShell v3 method is a little smoother. Here’s how we create the file:

# Create-EncryptedCredentialFile
$credentials = Get-Credential
$filename = 'C:\temp\secretfile.txt’
$credentials | Export-CliXml -Path $filename

Notice that the file stores both the username and the password, not just the password like the v2 version. Here’s how you would use it in the same example as above:

# Since we’re doing this remotely, we need to authenticate
$credPath = 'C:\temp\secretfile.txt’
$credentials = Import-CliXml -Path $credPath

That would replace the entire section, not just the yellow highlighted pieces that the PowerShell v2 solution replaces. It’s also important to know that only the user that exported the file can import it. This is great from a security standpoint, but it gets tricky if you are using the exported credentials for scheduled tasks. If that’s the case you’ll need to log in as (or at least run PowerShell as) the service account and export the file that way.

Wrapping It Up

Muuuuch better. We didn’t have to force PowerShell to do anything it doesn’t want to do. Now, no matter what access a bad guy has to your server, short of a key logger, they have no way of figuring out your password. Now, if they have that file, and they know what it is and what account it’s for they can use it to do stuff as that account. So you still need to keep your scripts and this password file secure. This can be used for good though, too. Now you can write scripts that run as a specific account without the person running that script needing to know what the password is, or being able to discover it. This is great for people building SharePoint farms, or support personnel.

I’d like to apologize for publishing PowerShell scripts that might encourage bad behavior. Please forgive me. In the future I’ll try to use this more secure method for baking passwords in. Hopefully you can also use this technique to make your environments more secure too.

I would also like to give a hearty “Thanks” to Lori Gowin (Blog | Twitter) and Mike Robbins (Blog | Twitter). They both very graciously read through this blog post multiple times and offered several valuable suggestions. It sucks way less because of their input. Thanks again.



Additional v2 Powershell

Great Blog Post.
Since there are multiple ways to skin a cat with Powershell, this is how I normally create the secure files.

## Exporting Credentials
# Path to save secure Credentials
$path = "C:\temp\secure-credentials.txt"
# Prompt for Credentials and allow them to be editable
$cred = (Get-Credential) | Select-Object *
# Convert Password from Securestring to Hash
$cred.Password = $cred.Password | ConvertFrom-SecureString
# Export credentials to the path above
$cred | Export-Clixml $path

## Importing Credentials
# Path to save secure Credentials
$CredPath = "C:\temp\secure-credentials.txt"
# Import Secure Credentials to variable
$Cred = Import-Clixml $CredPath
# Convert credentials to secure String
$Cred.Password = $cred.Password | ConvertTo-SecureString
# Push Credentials to PSCredential variable that can be used
$Credentials = New-Object System.Management.Automation.PsCredential($Cred.UserName, $Cred.Password)

Don't you need to decrypt the file with the same machine and user account that encrypted it with?
 on 4/14/2014 8:02 PM

Great Post!

Many thanks!
It helped me a lot!
 on 5/19/2015 4:42 AM

Add Comment

Items on this list require content approval. Your submission will not appear in public views until approved by someone with proper rights. More information on content approval.


Body *

Today's date *

Select a date from the calendar.
Please enter today's date so I know you are a real person


Want a message when I reply to your comment? Put your Twitter handle here.