Encrypting and Decrypting in Powershell

2 minute read

Intro

Hello, 🌎! Knowing how to encrypt and decrypt data in PowerShell can come in handy. Not only are you able to secure sensitive data, but you are also able to use the full capability of some PowerShell cmdlets which require encrypted data, such as Invoke-Command or New-PSSession. In this blog, I’ll show you how how simple it is to encrypt/decrypt data in PowerShell and how we can use encrypted data to create security credential objects.

Encrypting and Decrypting in PowerShell

In PowerShell, the cmdlets ConvertTo-SecureString and ConvertFrom-SecureString can be used to encrypt and decrypt a standard System.String to a System.Security.SecureString.

Here is an example where a string is being encrypted and stored into a variable:

$data = "This is some extremely important data"
$encryptedData = ConvertTo-SecureString -String $data -AsPlainText

If we type the name of the variable containing the encrypted string, we see its of type System.Security.SecureString as expected:

system-secure-string

We can also decrypt the data stored in a System.Security.SecureString object like this:

ConvertFrom-SecureString -SecureString $encryptedData -AsPlainText

Using Encrypted Strings for PowerShell Credentials

Being able to execute a cmdlet as a different user can be useful. For example, red teamers who’ve managed to obtain credentails for a compromised user, might want to try and execute commands on a remote machine as this user using these stolen credentials. Well cmdlets that define a Credential parameter allow us to specify the credentials that the cmdlet should be ran as. The value passed to the Credential parameter must be a PSCredential object. And in order for us to create PSCredential object, we need a user’s username and password, in the form of a secure string, which means we’ll need to encrypt the password.

To securely encrypt a string, its best practice not to specify the plaintext password in the command line as arguments. This is because PowerShell logging or any command line logging that is enabled, may log these plaintext credentials, which is not good! So instead, the password should be read in from stdin and stored in a variable. To simplify things, the Read-Host cmdlet, which allows us to read data from stdin, has a parameter called AsSecureString, which converts the data read from stdin into a System.Security.SecureString for us.

With the following PowerShell code, I can read data from stdin and save it to a variable as a secure string:

$password = Read-Host -AsSecureString

We can then take this secure string and create the required PSCredential object like this:

$Cred = New-Object System.Management.Automation.PSCredential("domain\user", $password)

We can now use this PSCredential object with cmdlets that allow us to specify a Credential parameter. Here’s how I’d execute the Invoke-Command cmdlet on a remote machine running WINRM, as a differnt user, using the PSCredential we’ve created:

Invoke-Command -Credential $Cred -ScriptBlock { whoami } -ComputerName 10.10.1.11

Happy Hacking!

EOF

If you enjoyed reading this blog and learned something, keep an eye out for more of my posts and maybe consider following me on GitHub, where I work on cybersecurity projects. And if you are feeling really generous, consider buying me a coffee!

References

comments powered by Disqus