Convert a secure string to plain text - powershell

I'm working in PowerShell and I have code that successfully converts a user entered password into plain text:
$SecurePassword = Read-Host -AsSecureString "Enter password" | convertfrom-securestring | out-file C:\Users\tmarsh\Documents\securePassword.txt
I've been tried several ways to convert it back, but none of them seem to work properly. Most recently, I've tried with the following:
$PlainPassword = Get-Content C:\Users\tmarsh\Documents\securePassword.txt
#convert the SecureString object to plain text using PtrToString and SecureStringToBSTR
$BSTR = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($PlainPassword)
$PlainPassword = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($BSTR)
[Runtime.InteropServices.Marshal]::ZeroFreeBSTR($BSTR) #this is an important step to keep things secure
This gives me an error as well.
Cannot convert argument "s", with value: "01000000d08c9ddf0115d1118c7a00c04fc297eb0100000026a5b6067d53fd43801a9ef3f8ef9e43000000000200000000000366000
0c0000000100000008118fdea02bfb57d0dda41f9748a05f10000000004800000a000000010000000c50f5093f3b87fbf9ee57cbd17267e0a10000000833d1d712cef01497872a3457bc8
bc271400000038c731cb8c47219399e4265515e9569438d8e8ed", for "SecureStringToBSTR" to type "System.Security.SecureString": "Cannot convert the "01000000
d08c9ddf0115d1118c7a00c04fc297eb0100000026a5b6067d53fd43801a9ef3f8ef9e430000000002000000000003660000c0000000100000008118fdea02bfb57d0dda41f9748a05f10
000000004800000a000000010000000c50f5093f3b87fbf9ee57cbd17267e0a10000000833d1d712cef01497872a3457bc8bc271400000038c731cb8c47219399e4265515e9569438d8e8
ed" value of type "System.String" to type "System.Security.SecureString"."
At C:\Users\tmarsh\Documents\Scripts\Local Admin Script\PlainTextConverter1.ps1:14 char:1
+ $BSTR = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($PlainPassw ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodException
+ FullyQualifiedErrorId : MethodArgumentConversionInvalidCastArgument
Cannot find an overload for "PtrToStringAuto" and the argument count: "1".
At C:\Users\tmarsh\Documents\Scripts\Local Admin Script\PlainTextConverter1.ps1:15 char:1
+ $PlainPassword = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($BSTR ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodException
+ FullyQualifiedErrorId : MethodCountCouldNotFindBest
Cannot convert argument "s", with value: "", for "ZeroFreeBSTR" to type "System.IntPtr": "Cannot convert null to type "System.IntPtr"."
At C:\Users\tmarsh\Documents\Scripts\Local Admin Script\PlainTextConverter1.ps1:16 char:1
+ [Runtime.InteropServices.Marshal]::ZeroFreeBSTR($BSTR) #this is an important ste ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodException
+ FullyQualifiedErrorId : MethodArgumentConversionInvalidCastArgument
Password is: 01000000d08c9ddf0115d1118c7a00c04fc297eb0100000026a5b6067d53fd43801a9ef3f8ef9e430000000002000000000003660000c0000000100000008118fdea02bfb57d0dda41f97
48a05f10000000004800000a000000010000000c50f5093f3b87fbf9ee57cbd17267e0a10000000833d1d712cef01497872a3457bc8bc271400000038c731cb8c47219399e4265515e9569
438d8e8ed
Does anyone know of a way that will work for this?

You are close, but the parameter you pass to SecureStringToBSTR must be a SecureString. You appear to be passing the result of ConvertFrom-SecureString, which is an encrypted standard string. So call ConvertTo-SecureString on this before passing to SecureStringToBSTR.
$SecurePassword = ConvertTo-SecureString $PlainPassword -AsPlainText -Force
$BSTR = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($SecurePassword)
$UnsecurePassword = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($BSTR)
[Runtime.InteropServices.Marshal]::ZeroFreeBSTR($BSTR)

You can use PSCredential.GetNetworkCredential() :
$UnsecurePassword = (New-Object PSCredential 0, $SecurePassword).GetNetworkCredential().Password

The easiest way to convert back it in PowerShell
[System.Net.NetworkCredential]::new("", $SecurePassword).Password

In PS 7, you can use ConvertFrom-SecureString and -AsPlainText:
#Requires -Version 7.0
$UnsecurePassword = ConvertFrom-SecureString -SecureString $SecurePassword -AsPlainText
https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.security/ConvertFrom-SecureString?view=powershell-7#parameters
ConvertFrom-SecureString
[-SecureString] <SecureString>
[-AsPlainText]
[<CommonParameters>]

Related

Signing password and get value back

We migrated one Windows Server 2008 to Server 2016.
Now I'm getting an error at this script:
cls
$key = (2,3,56,34,254,222,1,1,2,23,42,54,33,233,1,34,2,7,6,5,35,43,6,6,6,6,6,6,31,33,60,23)
$pass = Read-Host -AsSecureString
$securepass = $pass | ConvertFrom-SecureString -Key $key
$bytes = [byte[]][char[]]$securepass
$csp = New-Object System.Security.Cryptography.CspParameters
$csp.KeyContainerName = "SuperSecretProcessOnMachine"
$csp.Flags = $csp.Flags -bor [System.Security.Cryptography.CspProviderFlags]::UseMachineKeyStore
$rsa = New-Object System.Security.Cryptography.RSACryptoServiceProvider -ArgumentList 5120,$csp
$rsa.PersistKeyInCsp = $true
$encrypted = $rsa.Encrypt($bytes,$true)
$encrypted | Export-Clixml 'C:\Temp\encrypted_ysastaginpro_PRE.txt' -Force
Error Code:
New-Object : Exception calling ".ctor" with "2" argument(s): "Object already
exists."
At C:\Program Files\Staging\MESDI\Create_PSW_File_Poly.ps1:13 char:10
+ ... $rsa = New-Object System.Security.Cryptography.RSACryptoServiceP ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [New-Object], MethodInvocationException
+ FullyQualifiedErrorId : ConstructorInvokedThrowException,Microsoft.PowerShell.Commands.NewObjectCommand
Exception calling "Encrypt" with "2" argument(s): "Bad Length."
At C:\Program Files\Staging\MESDI\Create_PSW_File_Poly.ps1:18 char:3
+ $encrypted = $rsa.Encrypt($bytes,$true)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : CryptographicException
I found the the solution.
Run the PS Script as adminstrator.

Powershell 3.0: Unable to send e-mail to myself using send-mailmessage cmdlet

I've been trying to debug this for a couple of days now and I'm at my wits end. Here's the code:
$gmailPwd = 'password'
$gmailUser = 'my.email#gmail.com'
$cred = New-Object System.Management.Automation.PSCredential ($gmailUser,$gmailPwd)
$param = #{
SmtpServer = 'smtp.gmail.com'
Port = 587
UseSsl = $true
Credential = $cred
From = $gmailUser
To = $gmailUser
Subject = 'Test'
Body = "Test"
}
Send-MailMessage #param
I keep getting the following error message:
New-Object : Cannot convert argument "1", with value: "Password1234", for "PSCredential" to type "System.Security.SecureString": "Cannot convert the "Password1234" value of type "System.String" to type
"System.Security.SecureString"."
At line:4 char:9
+ $cred = New-Object System.Management.Automation.PSCredential ($gmailUser,$gmailP ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [New-Object], MethodException
+ FullyQualifiedErrorId : ConstructorInvokedThrowException,Microsoft.PowerShell.Commands.NewObjectCommand
Send-MailMessage : The SMTP server requires a secure connection or the client was not authenticated. The server response was: 5.5.1 Authentication Required. Learn more at
At line:15 char:1
+ Send-MailMessage #param
+ ~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (System.Net.Mail.SmtpClient:SmtpClient) [Send-MailMessage], SmtpException
+ FullyQualifiedErrorId : SmtpException,Microsoft.PowerShell.Commands.SendMailMessage
I'm just not really sure what the error message is getting at. And, for the record, no Password1234 is not really the password, but it is analogous to the real thing.
A [PSCredential]'s constructor doesn't accept plain text passwords. It has to be a secure string.
From How to create a PSCredential object:
$secpasswd = ConvertTo-SecureString "PlainTextPassword" -AsPlainText -Force
$mycreds = New-Object System.Management.Automation.PSCredential ("username", $secpasswd)

Argument errors with office 365 cmdlet

I'm having issues feeding variables into the New-MsolUser cmdlet. I'm getting the following error.
New-MsolUser : A positional parameter cannot be found that accepts argument 'â?UserPrincipalName ausertest#test.ie â?UsageLocation'.
At C:\users\test\Documents\test.ps1:148 char:1
+ New-MsolUser -DisplayName $TargetFullname â?"UserPrincipalName $TargetEmail â?" ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [New-MsolUser], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : PositionalParameterNotFound,Microsoft.Online.Administration.Automation.NewUser
The code I am using is:
$Source = "AnotherADUser"
$TargetFname = "New"
$TargetLname = "User"
$Target = "ausertest"
$TargetFullname = [string]::Concat($TargetFname ," ", $TargetLname)
$SourceEmail = (Get-ADUser $source -Property EmailAddress).EmailAddress
$SourceDomain = $SourceEmail.split("#")[1]
$TargetEmail = ([string]::Concat($Target , "#" , $SourceDomain))
New-MsolUser -DisplayName $TargetFullname –UserPrincipalName $TargetEmail –UsageLocation "IE" | Set-MsolUserLicense -AddLicenses "TESTINSTALL:EXCHANGESTANDARD"
This command works when I hardcode the details..
–UserPrincipalName and –UsageLocation use not the minus character but the
character with code 8211. Maybe it's fine but try to use the standard minus
instead, just to be sure.

Powershell SecureString Encrypt/Decrypt To Plain Text Not Working

We are trying to store a user password in the registry as a secure string but we can not seem to find a way to convert it back to plain text. Is this possible with SecureString?
Here is the simple test script we are trying to use...
Write-Host "Test Start..."
$PlainPassword = "#SomethingStupid" | ConvertTo-SecureString -AsPlainText -Force
$BSTR = ` [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($PlainPassword)
$PlainPassword = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($BSTR)
Write-Host "Password is: " $PlainPassword
Read-Host
This is the error we are getting...
The term ' [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR'
is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
At C:\test.ps1:4 char:71
+ $BSTR = ` [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR
<<<< ($PlainPassword)
+ CategoryInfo : ObjectNotFound: (
[System.Runtim...ureStringToBSTR:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
Cannot find an overload for "PtrToStringAuto" and the argument count: "1".
At C:\test.ps1:5 char:75
+ $PlainPassword =
[System.Runtime.InteropServices.Marshal]::PtrToStringAuto <<<< ($BSTR)
+ CategoryInfo : NotSpecified: (:) [], MethodException
+ FullyQualifiedErrorId : MethodCountCouldNotFindBest
What is with the backtick in the $BSTR = ... line? I agree with Graham above. If I remove the backtick it work just fine:
$PlainPassword = "#SomethingStupid" | ConvertTo-SecureString -AsPlainText -Force
$BSTR = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($PlainPassword)
$PlainPassword = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($BSTR)
Write-Host "Password is: " $PlainPassword
Outputs:
Password is: #SomethingStupid
You're not trying to run this on something like Windows RT or some other PowerShell configuration where the language is restricted - are you?
Here's a kludgy but much simpler way to decrypt a secure string, taking advantage of the fact that the PSCredential class has a constructor that accepts the password as a secure string and a method (GetNetworkCredential) that returns that password in plain text:
(New-Object System.Management.Automation.PSCredential 'N/A', $secure_string).GetNetworkCredential().Password
Although it's intended for use with credentials, there's nothing that prevents you from using this to decrypt any secure string* regardless of purpose, supplying a dummy argument for the username (the username argument can't be null or an empty string, but any meaningless string will do).
* Under the context of the account that encrypted the secure string to begin with, of course

Powershell - Secure String for Passwords and SFTP

I am trying to implement a way to use a stored secure string so that my SFTP password is not visiable in the script. For example, I'd like to generate a variable $password that could be used instead. I found the following examples online but I can't get them to work unfortunately. I've done something similar in the past but can find my notes or links to the website that explained how to complete the task.
read-host -assecurestring | convertfrom-securestring | out-file C:\securestring.txt
$pass = cat C:\securestring.txt | convertto-securestring
$mycred = new-object -typename System.Management.Automation.PSCredential -argumentlist "test",$pass
Here is my script. Here is a link to the snapin if anyone is interested. http://www.k-tools.nl/index.php/sftp-in-powershell/
#Add the SFTP snap-in
Add-PSSnapin KTools.PowerShell.SFTP
#Define some variables
$sftpHost = "ftp.domain.com"
$userName = "user"
$userPassword = "password"
$localFile = "C:\bin\emp1.xlsx"
#Open the SFTP connection
$sftp = Open-SFTPServer -serverAddress $sftpHost -userName $userName -userPassword $userPassword
#Upload the local file to the root folder on the SFTP server
$sftp.Put($localFile)
#Close the SFTP connection
$sftp.Close()
Again, thanks for everyones help!
UPDATE
I tried this:
$pass = cat c:\bin\ftpcreds.txt | convertto-securestring
$mycred = new-object -typename System.Management.Automation.PSCredential -argumentlist "usertest1",$pass
$sftpHost = "ftp.domain.com"
$userName = $mycred.username
$userPassword = $mycred.password
$sftp = Open-SFTPServer -serverAddress $sftpHost -userName $userName -userPassword $userPassword
$sftp.Put($localFile)
$sftp.Close()
And get this error:
Method invocation failed because [Tamir.SharpSsh.jsch.JSchException] doesn't contain a method named 'Put'.
At C:\bin\SFTP Upload Samples.ps1:21 char:1
+ $sftp.Put($localFile)
+ ~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : MethodNotFound
Method invocation failed because [Tamir.SharpSsh.jsch.JSchException] doesn't contain a method named 'Close'.
At C:\bin\SFTP Upload Samples.ps1:36 char:1
+ $sftp.Close()
+ ~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : MethodNotFound
Any suggestions?
Thanks!
If your SFTP is wanting to use a decrypted version of your secured password then you'll want to extract it from your $mycred by:
$userpassword = $mycred.getnetworkcredential().password.tostring()