Powershell SecureString Encrypt/Decrypt To Plain Text Not Working - powershell

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

Related

Why does PowerShell reject my secure string and say it cannot convert it to a secure string?

I am working on a script that will run New-RemoteMailbox with a generated string as the password argument. I have specific requirements for generating the password. It should begin with "Welcome" and then include some numbers and a few acceptable symbols. These are OTPs that will be used shortly after creation so I don't need them to be very strong.
Below is the code where I generate the password and convert it to a secure string:
[string]$Prefix = 'Welcome'
$Numbers = -join ((48..57) | Get-Random -Count 3 | % {[char]$_})
$Symbols = -join ((35..38)+(42)+(63..64)+(33) | Get-Random -Count 2 | % {[char]$_})
$Password = $Prefix + $Numbers + $Symbols
Write-Output "Temporary Password: $Password"
$Password = ConvertTo-SecureString -string $Password -AsPlainText -Force
Then here's where I use the variable later:
New-RemoteMailbox -Name "$FullN" -Password $Password -UserPrincipalName $Address -FirstName $FirstN -LastName $LastN -ResetPasswordOnNextLogon $true -SamAccountName $SamName
When I do that, I get the following error:
Cannot process argument transformation on parameter 'Password'. Cannot convert the "System.Security.SecureString" value of type "System.String" to type "System.Security.SecureString".
+ CategoryInfo : InvalidData: (:) [New-RemoteMailbox], ParameterBindin...mationException
+ FullyQualifiedErrorId : ParameterArgumentTransformationError,New-RemoteMailbox
The rest of this script seems to work without issue. This particular problem only showed up once I introduced the custom password generation (the prebuilt password method often recommended online did not suit our needs, as it generates (){}[]-./\|=+;:, potentially needlessly complicating the process for a new user, but the method was not causing this error). I see there have been questions about this particular error before, but the solution to the ones I've seen was using ConvertTo-SecureString, which I have in the code. I also can add Write-Output $Password any time before the conversion and it seems to output what I would expect (example: Welcome267#&).
Any ideas?
As #MathiasR.Jessen said in the replies, the issue was that I declared [String]$Password (not shown in the question), which prevented it from converting to a secure string. Changing the declaration or just using a new variable both seem to work.

Unable to run powershell script within powershell

If i run this code it will run the file
{Write-host "Please Enter the email address of the user you want to check the permissions"
$user = Read-Host
Powershell.exe C:\Temp\Report\Reports.ps1}
But if i run it like this which is what i need to do
{ Write-host "Please Enter the email address of the user you want to check the permissions"
$user = Read-Host
Powershell.exe C:\Temp\Report\Reports.ps1 -processOneDrive $true -OneDriveEmail $user}
I get this error
Powershell.exe : C:\Temp\ReportSharedFiles\ReportSharedFiles.ps1 : Missing an argument for parameter 'OneDriveEmail'. Specify a
At C:\Temp\ReportSharedFiles\Full Exchange Script Menu.ps1:88 char:2
+ Powershell.exe "c:\Temp\ReportSharedFiles\ReportSharedFiles.ps1" -pr ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (C:\Temp\ReportS...il'. Specify a :String) [], RemoteException
+ FullyQualifiedErrorId : NativeCommandError
parameter of type 'System.String' and try again.
At line:1 char:71
+ ... haredFiles\ReportSharedFiles.ps1 -processOneDrive True -OneDriveEmail
+ ~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [ReportSharedFiles.ps1], ParameterBindingException
+ FullyQualifiedErrorId : MissingArgument,ReportSharedFiles.ps1
What am i doing wrong and how can i get this to work? any help will be appreciated
I believe its asking you for a sting parameter in the error
parameter of type 'System.String' and try again.
Hope this works out>
{ [string]$user = Read-Host "Please Enter the email address of the user you want to check the permissions"
Powershell.exe C:\Temp\Report\Reports.ps1 -processOneDrive $true -OneDriveEmail $user}
Type String >
I have figured it out. It seems when running the powershell script within another script and to have the arguments in. when it comes to the -processOneDrive $true It tried to convert that to boolem which caused errors. i changed this to 1 which im sure means true so code looks like this
Powershell.exe "c:\Temp\Report\Reports.ps1" -processOneDrive 1 -OneDriveEmail $user
Now it runs smoothly. Thanks for everyone that tried to help me with this :)

Error: ConvertTo-SecureString : Key not valid for use in specified state

We have one script which has been used to store password to a text file and then the mail script recalls/reuses this password from the password text file to run the master script.
I am getting below error,after changing the password.
Script used to generate secure password:
"Password" | ConvertTo-SecureString -AsPlainText -Force | ConvertFrom-SecureString | Out-File "D:\Scripts\Password.txt"
Error we are getting now:
At C:\Scripts\Lync_HealthCheck_Prod.ps1:1199 char:82
+ $PasswrdS = Get-Content C:\Windows\System32\SecStrng.sec | convertto-securest
ring <<<<
+ CategoryInfo : InvalidArgument: (:) [ConvertTo-SecureString], C
ryptographicException
+ FullyQualifiedErrorId : ImportSecureString_InvalidArgument_Cryptographic
Error,Microsoft.PowerShell.Commands.ConvertToSecureStringCommand
New-Object : Exception calling ".ctor" with "2" argument(s): "Cannot process ar
gument because the value of argument "password" is null. Change the value of ar
gument "password" to a non-null value."
At C:\Scripts\Lync_HealthCheck_Prod.ps1:1218 char:27
+ $Creds1 = New-Object <<<< System.Management.Automation.PSCredential -A
rgumentList $CheckUser1, $PasswrdS
+ CategoryInfo : InvalidOperation: (:) [New-Object], MethodInvoca
tionException
+ FullyQualifiedErrorId : ConstructorInvokedThrowException,Microsoft.Power
Shell.Commands.NewObjectCommand
Would be great if you can help.
The error message claims that you are handling null values:
"Cannot process argument because the value of argument "password" is null.
So, double-check that you actually are reading good content from the password file. The location in C:\Windows\System32 very hints that the process is looking for it from wrong location.
$PasswrdS = Get-Content C:\Windows\System32\SecStrng.sec
Exactly same problem, due to NTFS rights mismatch on the sec file. Get-content is OK, but not call of Convertto-SecureString.
User who created the password file was not the user who executed the program.
I put total control on this file for both users. It is OK now.
To be more accurate : I connected with account needed to run, drop and recreated the secure file containing credentials. This file is useful only for this account

Convert a secure string to plain text

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>]

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()