Encrypting and Decrypting in Powershell
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:
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!