Converting System.Security.SecureString to String (in PowerShell)

I appreciate that most people won’t want to ever convert a secure string into a normal string however there’s a couple of reasons why you would even though there are security concerns. In my case I’m providing PowerShell scripts that are nothing more than a wrapper around a command that must be executed from the command line to for the purpose of simplifying deployment instructions I’m writing for a deployment guide. I like to do this as it provides a predictable, repeatable and consistent experience, e.g. when Microsoft first shipped the server core version of Windows Server 2008 I found myself doing this quite a lot using CMD scripts, e.g. wrappers around things like NETDOM and NETSH, etc.

Anyway, I want to take a password and make use of the star notation via the Read-Host cmdlet, e.g. when you enter something that will be read into a variable by Read-Host I don’t want what’s being typed visible at the console. To do this I need to use the -AsSecureString parameter of Read-Host and assign the value to a [System.Security.SecureString] variable. However I then need to get the actual string value in a plain, unencrypted form so that I can provide it to, for example, MSIEXEC or NETDOM. The PowerShell product group have obviously not made this easy, however it is possible. Here’s how:

[System.Security.SecureString]$secureStringValue = Read-Host "Enter the service account password: " -AsSecureString; 
[String]$stringValue = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($secureStringValue)); 

In the above snippet I read the value entered by the user as a secure string into $secureStringValue and then store the plain string in the string attribute $stringValue.

Put into context I want someone to execute my script in a way not dissimilar to a multitude of command line applications, i.e. you either enter your password within the confines of your command; you supply a wildcard; or you supply no password at all and the application prompts for a password, e.g. here’s an example of the RUNAS application:

PS C:\dev\lang\ps1\fim\unattended-installation> runas /noprofile /user:dev\paulw-admin cmd 
Enter the password for dev\paulw-admin: 

Here’s a slightly larger snippet taken directly from a script that I use to perform an unattended installation of FIM. The script is intended to be used interactively. It’s not part of a larger deployment, e.g. a System Center Configuration Manager (SCCM) deployment, but a simplistic “run this script, provide two arguments and FIM is installed” type thing.

if($ServiceAccountPassword -eq "*") 
 [System.Security.SecureString]$ServiceAccountPassword = Read-Host "Enter the service account password: " -AsSecureString; 
 [String]$syncSvcAccountPassword = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($ServiceAccountPassword)); 
 [String]$syncSvcAccountPassword = $ServiceAccountPassword; 

I then execute the script in either of the following ways:

  • Showing the password:
PS C:\dev\lang\ps1\fim\unattended-installation> .\UnattendedInstallation.ps1 -XmlConfigFile .\InstallationProperties.xml -ServiceAccountPassword @C0mp3xP@55w0rd! 
  • Telling the script to prompt for the password:
PS C:\dev\lang\ps1\fim\unattended-installation> .\UnattendedInstallation.ps1 -XmlConfigFile .\InstallationProperties.xml -ServiceAccountPassword * 
  • Blissfully unaware of what options are available re. the needed password value:
PS C:\dev\lang\ps1\fim\unattended-installation> .\UnattendedInstallation.ps1 -XmlConfigFile .\InstallationProperties.xml 

Anyway, thanks go to Lee Holmes of the PowerShell product group via Chrissy LeMaire who documented this technique in this post. I might stop writing CMD wrapper scripts now. J


About Paul Williams

IT consultant working for Microsoft specialising in Identity Management and Directory Services.
This entry was posted in Scripting and tagged , , , , . Bookmark the permalink.

3 Responses to Converting System.Security.SecureString to String (in PowerShell)

  1. Randall C says:

    Thanks for this… using it for NETDOM actually…

  2. Pingback: Jamie Thomson : Prompt for a password with a mask using Powershell

  3. Rodney Nagel says:

    This is awesome! Works beautifully! Thanks for the blog, will definitely follow!

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s