This is a picture of me.

Simon Buckley

SMNBKLY.CO


Securely Store (and Retrieve) Credentials In Powershell Scripts

22 March 2019

Automating boring s**t with PowerShell is PowerShell’s whole shtick. If something happens regularly, and it’s pretty important, you should probably make it happen without bums in seats and hands on keyboards.

This is how PowerShell works. Just ask Jeff Snover.

For this, PowerShell automation is all sunshine and rainbows. Sometimes though, you need to automate stuff that requires credentials. Maybe we can do this? 👇

$mySuperSafePassword = 'P@ssword!'

Nope. Storing your password in plain text is not only stupid, it should probably be considered a dismissable offense!

Important disclaimer!No method of storing passwords in code is ideal. No method is 100% secure. In most situations, you shouldn’t even do this at all. In cases where it’s unavoidable, consider implementing additional controls to ensure that The Bad Guys don’t ever see this code.

With our disclaimers out of the way, now we need to encrypt and store our password. This is the easy bit. From a PowerShell console, run the below command. You’ll be prompted to enter a username and password. Enter whatever you want in the username field, as we’re only concerned with storing passwords for this tutorial.

(Get-Credential).password | ConvertFrom-SecureString

This single-liner takes the password you entered, stored as a SecureString object, and converts it to an encrypted string using the Windows Data Protection API. In short, it encrypts the string using a key derived from:

Store the output of the above line in your code as you wish. In this tutorial, we’re going to put it in a variable like below.

$encryptedPassword = '01000000d08c9ddf0115d1118c7a00c04fc297eb010000005b6e6f2c69930c4e9b6b1e1cdad79e3b0000000002000000000003660000c000000010000000d33c27e9bd07dab24012caf5f52a086a0000000004800000a000000010000000f17cf83e3101f8ee6da62930a3734cbd180000004e40a628f82ae2c4b90c5113d0fa64fb7b4d0c5515f809c314000000c073d2b4d97696689bdae675ba1b042831e7824e'

Now that we’ve stored our password, let’s see how we can use it. To begin with, let’s convert it to a SecureString object.

$encryptedPassword = $encryptedPassword | ConvertTo-SecureString

Taking our brand new SecureString, we use the Marshal.SecureStringToCoTaskMemUnicode method from .NET to copy the contents to a block of memory.

$pointer = [System.Runtime.InteropServices.Marshal]::SecureStringToCoTaskMemUnicode($encryptedPassword)

With that block of memory, using the Marshal.PtrToStringUni method, we convert it to a managed string to make it human-readable again.

$decryptedPassword = [System.Runtime.InteropServices.Marshal]::PtrToStringUni($pointer)

This bit is important! We need to remove the above from memory. This line below uses the Marshal.ZeroFreeCoTaskMemUnicode to zero out the pointer and free up the memory.

[System.Runtime.InteropServices.Marshal]::ZeroFreeCoTaskMemUnicode($pointer)

And that’s it! Now, using the $decryptedPassword variable, you can do what needs to be done. Let’s tie it all together:

$encryptedPassword = '01000000d08c9ddf0115d1118c7a00c04fc297eb010000005b6e6f2c69930c4e9b6b1e1cdad79e3b0000000002000000000003660000c000000010000000d33c27e9bd07dab24012caf5f52a086a0000000004800000a000000010000000f17cf83e3101f8ee6da62930a3734cbd180000004e40a628f82ae2c4b90c5113d0fa64fb7b4d0c5515f809c314000000c073d2b4d97696689bdae675ba1b042831e7824e'
$encryptedPassword = $encryptedPassword | ConvertTo-SecureString
$pointer = [System.Runtime.InteropServices.Marshal]::SecureStringToCoTaskMemUnicode($encryptedPassword)
$decryptedPassword = [System.Runtime.InteropServices.Marshal]::PtrToStringUni($pointer)
[System.Runtime.InteropServices.Marshal]::ZeroFreeCoTaskMemUnicode($pointer)

# Do something

Happy scripting!

Automation PowerShell Security

This post was last updated on 8 October 2019