I write a lot of PowerShell scripts where I need to access different kinds of services, servers and databases. Often these scripts needs to run on schedules in the background and so on.
Instead of having cleartext passwords scattered throughout the scriptfile I like to store a securestring version of the password in the script.
Normally you would build a credential object using something like this
$username = "domain\admin" $password = "password" | ConvertTo-SecureString -AsPlainText -Force $cred = New-Object -typename System.Management.Automation.PSCredential -argumentlist $username, $password
That means that anyone who can open and read the scriptfile, will know what the password for the account in question is. Which is VERY BAD.
It would be better if we could create the SecureString from the content of itself (does that make sense?)
It turns out that you can in fact output the content of a securestring to a string using ConvertFrom-SecureString
"password" | ConvertTo-SecureString -AsPlainText -Force | ConvertFrom-SecureString
The output is luckily not the unencrypted password we entered, it is a string containing the encrypted version of the password.
01000000d08c9ddf0115d1118c7a00c04fc297eb01000000b9fe0ca15a2ffb4a9e172d76a87afae40000000002000000000003660000c000000010000000875 eab73cc326c4acb70b609f170da6d0000000004800000a0000000100000001efe13d29355bea97995960f306c0009180000005a906fee5e408ccf685bbc56dd 1c3e3c91472d168c17d38a140000008bf9a9f060d1c46d1d96441d2080218ff0ada1a6
So in order to use this information as a password we need to reverse the process.
First we need to store the encrypted string in a variable
$password = "01000000d08c9ddf0115d1118c7a00c04fc297eb01000000b9fe0ca15a2ffb4a9e172d76a87afae40000000002000000000003660000c000000010000000875eab73cc326c4acb70b609f170da6d0000000004800000a0000000100000001efe13d29355bea97995960f306c0009180000005a906fee5e408ccf685bbc56dd1c3e3c91472d168c17d38a140000008bf9a9f060d1c46d1d96441d2080218ff0ada1a6"
The next step is to create the credentials object
$cred = New-Object -TypeName System.Management.Automation.PSCredential -argumentlist $username,($password | ConvertTo-SecureString)
As you can see the magic stuff happens when you pipe the $password variable through ConvertTo-SecureString
So far I have not yet come up with a way the decrypt the encrypted string back to a readable value.
And the cool part is that it works everywhere you use –credentials (or at least for all the things I have tried so far)
If you prefer to store the password in an external file or a registry key you can that.
$password = Get-Content password.txt
To write the securestring directly to the file you can use this
Though it is not advised to store credentials on the disk. But if you are really looking to do this then I have found that Export-CLiXML and Import-CLiXML with PowerShell v3 make this a little bit easy.
More details on how to here –> http://www.powershellcookbook.com/recipe/PukO/securely-store-credentials-on-disk
Regards,
Nice alternative solution DexterPOSH, I am thinking about encrypting the file containing the password or credentials to improve security.
In case you didn’t know, if you issue $cred.GetNetworkCredential().password you can have your password in cleartext..
@Gyz, you are right about that. So now I know … Thanks for your info
No one but your user can execute the script.
When a user encrypts a password he is the only one who can decrypt it.
So there is no bother in getting the password in cleartext with $cred.GetNetworkCredential().password
If you send that script to another user, when he executes it he will get an error with convertto-securestring cmdlet
Agreed, after playing with this stuff for about a day, I’ve decided it’s pointless.
Instead, I ended up using PS2EXE to convert the PS to an EXE file to conceal the password in my ps file.
the article you refer to is now on technet, I read:
-extract:”Filename” Extracts the PowerShell script inside the EXE and saves it as “Filename”. The script will not be executed.
not very secure if it was your intention to make it secure..
Hello,
I am trying to encrypt the password seprate and then use the same encryption in all other systems. but the issue is it is working fine only on the machine where I did encryption not on other machines.
I am using below code:
$test1 = “01000000d08c9ddf0115d1118c7a00c04fc297eb01000000ac83eb1515f4b44e84478d869b3f78ff0000000002000000000003660000c000000010000000cf044736de9f43b4a6a4d81bd65113310000000004800000a000000010000000786963e6a165bfc89e1eddc39b707e4830000000be609f5a88df9b72450ba756202f5e478759ec25f0eee89ee94f9b49b9ac02cb7c0421bbf8ab0ccec9f0b2b7dad488b714000000aee81fdb754414aed24d3bf91f2174ebb5e8a192”
$test2 = “testdomaintestuser”
$test3 = Convertto-SecureString -string $test1
$Ptr = [System.Runtime.InteropServices.Marshal]::SecureStringToCoTaskMemUnicode($test3)
$result = [System.Runtime.InteropServices.Marshal]::PtrToStringUni($Ptr)
Hi yashpal:
When you use the command ConvertTo-SecureString it encrypts the plaintext password with the encryption key on the local machine, under your user account. This means that if you export it to xml, you can only use it on that same local machine.
To make it work, you have to use the -Key parameter in order to use it across machines.
See my post for details:
http://stackoverflow.com/questions/23699500/convertto-securestring-gives-different-experience-on-different-servers/23700513?s=2|0.1373#23700513
[…] method is similar to the one used in this blog post. I’ve modified it to work across all user accounts and passwords. Generating the Secure […]
[…] Powershell: uložení šifrovaného hesla ve skriptu […]
Hi
I tried to use this procedure to run program (exe file) as porcess
Read-Host -AsSecureString | ConvertFrom-SecureString | Out-File c:UserskowalskijDocumentsPassword.txt
$password = type “c:UserskowalskijDocumentsPassword.txt” | ConvertTo-SecureString
$cred = New-Object -TypeName System.Management.Automation.PSCredential -argumentlist “domainadministrator2”,$password
Start-Process -Credential $cred -FilePath C:UserskowalskijDocumentsJava-64Bit.exe
and….. error:
start-Process : This command cannot be run due to the error: The directory name is invalid.
.
At line:1 char:1
+ Start-Process -Credential $cred -FilePath C:UserskowalskijDocument …
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [Start-Process], InvalidOperationException
+ FullyQualifiedErrorId : InvalidOperationException,Microsoft.PowerShell.Commands.StartProcessCommand
Do you know what does mean: This command cannot be run due to the error: The directory name is invalid.
and how to solve it?
Try this to decrypt password to clear text:
$cred.GetNetworkCredential().password
Guys,, I have used this info to create save an encrypted pass on a txt which I’m trying to pass as a parameter how ever its not working,,, script runs with no errors but the result says to me is not taking the password. could you please advise ?
Im trying to execute a .batch file using another user/password, password is saved on pass.txt
the .batch file basically opens a share folder which displays its content only to authorized users, the folder opens but no content is there so I assume is not taking the password
$build = “c:file.bat”
$username = “domainuser”
$password = Get-content C:pass.txt
$credentials = New-Object -typename System.Management.Automation.PSCredential -ArgumentList @($username,(ConvertTo-SecureString -String $password -AsPlainText -Force))
$argu = “-Credential ($credentials)”
Start-Process $build $argu
Any help would be really appreciated
Hi there, its nice piece of writing about media print, we
all be familiar with media is a fantastic source of facts.
I had created a PSCredential with the inline script and was able to access the credential until the PowerShell session which created the credential was open. When I have closed and reopened PowerShell to run the script again, I was not able to access $TFSAdminCred:
$UserID = “xyz”
$PswdFile = “\Server1TFSencrypt$Pswd.txt”
$KeyFile = “\Server1TFSencrypt$AES.txt”
$Key = New-Object byte[] 16
[System.Security.Cryptography.RNGCryptoServiceProvider]::Create().GetBytes($Key)
$Key | Out-File $KeyFile
$Key = Get-Content $KeyFile
$Pswd = “password” | ConvertTo-SecureString -AsPlainText -Force | ConvertFrom-SecureString -Key $Key | Out-File $PswdFile
$TFSAdminCred = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList
I have a very easy way for you guys, just watch this video and you should be fine. Its one of the best and secure ways to encrypt and decrypt password.
https://www.youtube.com/watch?v=ZV5xRrv6UO0&list=PLfr5_hAgPfYEVWjc2oSitEbcMR_8Oamhi&index=29&t=0s