How Linux protects SecureStrings (Not)

by Apr 29, 2021

When you serialize objects to XML in PowerShell on a non-Windows system, i.e. by using Export-CliXml, any SecureString data is encoded only, not encrypted. That’s a fundamental difference and the reason why safe code may become unsafe once ported to a non-Windows operating system.

If you serialize credentials, for example, the result is safe on Windows operating systems only:

Get-Credential | Export-Clixml -Path $env:temp\secret.xml

Inside the XML file, you can see how Export-CliXml has changed the representation of SecureString and turned it into a list of hex values. On Windows, SecureString data is safely encrypted and can be read only by the person (and while using the computer) that encrypted the data. Not so on Linux and macOS. Since here the Windows crypto API is missing, SecureStrings are encoded, not encrypted.  

To decode the plain text content found in serialized XML content on non-Windows operating systems, try code like this:

$secret = '53007500700065007200530065006300720065007400'
$bytes = $secret -split '(?<=\G.{2})(?=.)' |
ForEach-Object {
[Convert]::ToByte($_, 16)}
$plain = [Text.Encoding]::Unicode.GetString($bytes)

This takes the encoded string, splits it into pairs of two, turns the hex value into a decimal value and runs the resulting bytes through the appropriate Unicode decoder. The result is the original secret.  

In a nutshell, keep in mind that serialized SecureStrings are safely encrypted only on Windows operating systems. On Linux and macOS, sending sensitive data to Export-CliXml will not protect it.

Twitter This Tip! ReTweet this Tip!