6 min read
Encoding vs encryption? Understand the difference and choose wisely!
Understanding encoding vs encryption is essential for robust data security. But what is the difference between encoding...
Unlocking the Power of PowerShell: Tips for Success
Think your SecureString is safe? Not on all platforms! Discover the risks of cross-platform data encryption with SecureString in .NET. Read our first of four SecureString deep dives here:
SecureString is designed to simplify handling sensitive text (such as passwords): behind the scenes, .NET's System.Security.SecureString uses strong AES encryption to ensure that only the owner of a string can read it – regardless of whether you store it in a file or if an attacker finds it in a memory dump.
Unfortunately, while this works well on Windows, it silently fails on other platforms. It's time for a closer look in this mini-series. If you're interested in cross-platform solutions, a great overview of compatible cross-platform encryption can be found on Microsoft | Learn.
On Windows systems, SecureString is automatically protected, so you can use it to store local passwords. In the example below, you can enter credentials for three different servers (add more if you want) which are then serialized to an XML file:
$path = "$env:userprofile\mypasswords.xml"
@{
Server1 = Get-Credential -Message 'Enter password for Server 1' -UserName $env:USERNAME
Server2 = Get-Credential -Message 'Enter password for Server 2' -UserName $env:USERNAME
Server3 = Get-Credential -Message 'Enter password for Server 3' -UserName $env:USERNAME
} | Export-Clixml -Path $path
When you open the XML file in a text editor, the passwords are encrypted:
<ToString>System.Management.Automation.PSCredential</ToString>
<Props>
<S N="UserName">tobia</S>
<SS N="Password">01000000d08c9ddf0115d1118c7a00c04fc297eb01000000fca013869c24324fa191f7d1f5e8d46a00000000020000000000106600000001000020000000de26f1058a814b27a481821459eea01f8ad340a87512a6be0c21f871b46e8ee6000000000e8000000002000020000000cc97abd02f4f296d16338711331f1e9893e36da5ba397a3286891b06d329ff6710000000c7f9f9af2a5d3e7b980cab7acc7b22ee400000006dfc7c22382502e9ec47eb0ea28f990807dc336f1d673a06754c9de5a794b077633217176cfa027ee180073bb42965128442c917f40a25d7150d5536e325f82f</SS>
</Props>
That’s because credentials store sensitive information in the SecureString data type, which is automatically protected (while the username appears in clear text because it is a regular string).
Decrypting the encrypted information is just as transparent. If you need to read (and use) the credentials you persisted in the XML file above – such as by a script that needs to run unattended and use these credentials for logins – here is the fully transparent reverse process:
$path = "$env:userprofile\mypasswords.xml"
$mySecrets = Import-Clixml -Path $path
# retrieve the stored credentials
$mySecrets.Server1
# I am the owner, so I can always see the plaintext string, too
$mySecrets.Server1.GetNetworkCredential().Password
$mySecrets.Server2
$mySecrets.Server2.GetNetworkCredential().Password
$mySecrets.Server3
$mySecrets.Server3.GetNetworkCredential().Password
This process is secure because, on Windows only, there are two "secrets" used for AES encryption: you and your PC. The transparent decryption works only for the identity that encrypted the SecureString and only on the original PC. Anyone else cannot decipher the passwords from the XML file.
It is important to understand that the underlying encryption and decryption are performed by .NET whenever the data type System.Security.SecureString is serialized anywhere in your code:
# encryption
$path = Join-Path -Path $env:temp -ChildPath secret.xml
Read-Host -Prompt 'Enter your secret' -AsSecureString | Export-Clixml -Path $path
# decryption
$path = Join-Path -Path $env:temp -ChildPath secret.xml
$secureString = Import-Clixml -Path $path
$secureString
Again, the entered string is transparently AES-encrypted and written to the XML file.
$bstr = [Runtime.InteropServices.Marshal]::SecureStringToBSTR($secureString)
$plainText = [Runtime.InteropServices.Marshal]::PtrToStringAuto($bstr)
# free allocated memory
[Runtime.InteropServices.Marshal]::ZeroFreeBSTR($bstr)
$plainText
When you import the XML file, you retrieve the SecureString, and since you are the owner of the string, you can always convert it back to plaintext:
$bstr = [Runtime.InteropServices.Marshal]::SecureStringToBSTR($secureString)
$plainText = [Runtime.InteropServices.Marshal]::PtrToStringAuto($bstr)
# free allocated memory
[Runtime.InteropServices.Marshal]::ZeroFreeBSTR($bstr)
$plainText
The primary purpose of SecureString (on the Windows platform) is to protect sensitive information; however, a number of applications can be derived: since PowerShell shows a masked input box when you are prompted for a SecureString, you can now easily implement masked input boxes.
function Get-SomeSecret
{
param
(
[SecureString]
[Parameter(Mandatory)]
$Secret
)
$bstr = [Runtime.InteropServices.Marshal]::SecureStringToBSTR($Secret)
$plainText = [Runtime.InteropServices.Marshal]::PtrToStringAuto($bstr)
# Free allocated memory
[Runtime.InteropServices.Marshal]::ZeroFreeBSTR($bstr)
"The user entered: $plainText"
}
As you see, SecureStrings eliminate the need for handling secrets: the encryption key does not need to be known (or transferred). Instead, you and your machine are the keys.
To test whether SecureStrings are indeed safe to use on your platform, simply save a SecureString to an XML file in one of the illustrated ways. Then try to decrypt the file as a different user, or on a different machine. If this operation fails with an exception, your secret is safely encrypted. On Windows, this is the case.
However, the automatic AES encryption of SecureStrings has been quietly removed on non-Windows platforms such as Linux and macOS. All of the code above works there, too. However, the SecureString is not AES encrypted but merely encoded: anyone who gains access to the XML file can decode the secret.
This is because .NET (used by PowerShell 7) does not implement the encryption API on non-Windows systems. The dangerous side effect is that you may have been using a secure scripting solution based on SecureStrings on Windows, yet once you transfer it to another platform, your sensitive data is no longer protected, even if it seems to continue to work just fine.
While our first deep dive covered SecureString in .NET and answered the question how secure your sensitive data is across platforms, there are three more deep dives to come. The second one covers enhancing SecureString security: Alternatives and best practices on different platforms.
Unleash the full potential of PowerShell with our handy poster. Whether you're a beginner or a seasoned pro, this cheat sheet is designed to be your go-to resource for the most important and commonly used cmdlets.
The poster is available for download and in paper form.
Nov 27, 2024 by Aleksandar Nikolić and Dr. Tobias Weltner
Understanding encoding vs encryption is essential for robust data security. But what is the difference between encoding...
Nov 18, 2024 by Aleksandar Nikolić and Dr. Tobias Weltner
Think your SecureString is safe? Not on all platforms! Discover the risks of cross-platform data encryption with ...
Nov 20, 2024 by Aleksandar Nikolić and Dr. Tobias Weltner
How does Windows keep SecureString safe? Dive deeper into encryption methods and uncover cross-platform security gaps...
Tobias Weltner and Aleksandar Nikolić joinly wrote the blog post series 'Tobias&Aleksandar's PowerShell tips'. So we introduce both of them here:
----------------------------
Aleksandar Nikolić is a Microsoft Azure MVP and co-founder of PowerShellMagazine.com, the ultimate online source for PowerShell enthusiasts. With over 18 years of experience in system administration, he is a respected trainer and speaker who travels the globe to share his knowledge and skills on Azure, Entra, and PowerShell. He has spoken at IT events such as Microsoft Ignite, ESPC, NIC, CloudBrew, NTK, and PowerShell Conference Europe.
----------------------------
Tobias is a long-time Microsoft MVP and has been involved with the development of PowerShell since its early days. He invented the PowerShell IDE "ISESteroids", has written numerous books on PowerShell for Microsoft Press and O'Reilly, founded the PowerShell Conference EU (psconf.eu), and is currently contributing to the advancement of PowerShell as member in the "Microsoft Cmdlet Working Group". Tobias shares his expertise as a consultant in projects and as a trainer in in-house trainings for numerous companies and agencies across Europe.