How can I use powershell's read-host function to accept a password for an external service? - powershell

I have a script I'm writing that makes a connection to a SOAP service. After the connection is made, I need to pass in a the username/pass with every command I send. The problem I have is that when I use read-host to do this, my password is shown in cleartext and remains in the shell:
PS C:\Users\Egr> Read-Host "Enter Pass"
Enter Pass: MyPassword
MyPassword
If I hide it with -AsSecureString, the value can no longer be passed to the service because it is now a System.Security.SecureString object:
PS C:\Users\gross> Read-Host "Enter Pass" -AsSecureString
Enter Pass: **********
System.Security.SecureString
When I pass this, it does not work. I don't care about the passwords being passed to the service in cleartext, I just don't want them sticking around on a user's shell after they enter their password. Is it possible to hide the Read-Host input, but still have the password stored as cleartext? If not, is there a way I can pass the System.Security.SecureString object as cleartext?
Thanks

$Password is a Securestring, and this will return the plain text password.
[Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($Password))

You can save the password(input) as a variable and pass it to your service. If the code is run in a script or as a function, the variable containing the password will be deleted after it's done(they are stored in a temp. local scope). If you run the commands in the console(or dot-source the script like . .\myscript.ps1), the password variable will stay in the session scope, and they will be stored until you delete it or close the session. If you want to be sure the variable is removed after your script is run, you can delete it yourself. Like this:
#Get password in cleartext and store in $password variable
$password = Read-Host "Enter Pass"
#run code that needs password stored in $password
#Delete password
Remove-Variable password
To read more about how variables are stored in scopes, check out about_Scopes

There is a way to do this in PowerShell versions 6.x+:
$password = read-host -maskinput "Enter password"
, thanks to jborean93 for pointing this out to me.

Related

Pass Stored Creds to bat file

I am trying to figure out if there is a way to take a stored credential in Windows Cred vault and pass it to a bat file that needs the credentials. I found a very old bat file that has a username and password in clear text. These are used to authenticate against a portal and have to be read by the bat in clear text. I have stored credentials on my server that I want to use so I can close this security gap but I am not 100% sure how to pass the password because it has to be in clear text. Here is what I have:
$creds = Get-StoredCredential -Target "Username"
$password = $creds.Password
$username = $creds.UserName
Start-Process cmd.exe "/c C:\trigger.bat `"argument1`" $username $password `"Argument2`" Argument3" -NoNewWindow -Verbose
When I enter the password in clear text in my line it works. If I use $password it throws an auth error. I assume that this is because the $password is a stored PSObject and isn't getting passed to cmd "correctly". Is there a way around this?
PS: Get-StoredCredential is from the CredentialManager module.
If $creds contains a PSCredential object, then you should be able to replace this:
$password = $creds.Password
with this:
$password = $creds.GetNetworkCredential().Password
Get-StoredCredential, when called without -AsCredentialObject, yields PSCredential instances.
The PSCredential.Password property you are accessing is not a String but a SecureString, so you cannot retrieve the plain text password like you are attempting.
Based on Convert a secure string to plain text you can use the PSCredential to get a NetworkCredential and then use its Password property...
$password = $creds.GetNetworkCredential().Password
In any case, when you get an authentication error using $username and $password you should ensure those variables contain the values you expect them to.

Box input for Administrator password with secure string

Need little help ,
i need to create a Input Box that user your enter new Local Administrator Password .
very simple , so i wrote this script but it does not work ,
can you help me ?
$pass = Read-Host "Enter Password" -AsSecureString
net user administrator $pass
What Read-Host -AsSecureString returns is an instance of System.Security.SecureString, which by design cannot be used as plain text.
You can force its re-conversion to plain text as follows, but note that the very point of using a secure string is to avoid plain-text representations.
Given that calling external programs such as net user requires a plain-text representation, it's more secure to use .NET alternatives that can work directly with SecureString instances, if available.
If you must use net.exe, use the following:
# Read the password masked, into a SecureString instance.
$passSecure = Read-Host "Enter Password" -AsSecureString
# INSECURE: Force reconversion to plain text.
$passPlainText = [pscredential]::new('dummy', $pass).GetNetworkCredential().Password
# INSECURE: Pass the plain-text representation to `net user`
net user administrator $passPlainText

Prevent PowerShell script from being read

I have the below PowerShell script (myscript.ps1) in which I ask for username and password. Depending on the username and password it copies a file to a certain destination.
$credentials = Get-Credential
if ($credentials.Username -eq "user1" -And $credentials.GetNetworkCredential().password -eq "pass1")
{ Copy-Item "test1.pdf" "\test\test1.pdf"; }
else
{ Copy-Item "test2.pdf" "\test\test2.pdf"; }
Requirement: I want to make this file protected so no one can edit it and see the username and password.
PS2EXE
I found a solution found here which converts the PowerShell script to an .exe file. When I originally run the script using PowerShell a dialog box appears allowing me to enter the username and password:
After the .exe is generated and when I run it the credentials dialog box no longer appears. Instead, the console appears saying "Credential:"
I don't know why? I want the credentials form to still appear when running the exe. Any thoughts please?
Q: Why does the EXE prompt with "Credential"?
This isn't an answer to the real question, and is based on guessing/supposition about PS2EXE, but I hope it is useful to clear up some confusion.
Having looked briefly at the PS2EXE page linked above, it seems that this utility encodes the script in Base64 and bundles it with a lightweight (?) custom PowerShell host. When run, I suppose the EXE starts the host, decodes the script and runs it.
The problem is that the Get-Credential cmdlet is running within a PS host that probably can't interact with the desktop. That is, it can't put up the GUI prompt for credentials. It therefore needs to prompt for the Credential property on the command line, explaining why you see that behaviour.
Workaround with Read-Host?
Instead of trying to use Get-Credential to prompt for username and password, you could embrace what PS2EXE seems to be doing and just use Read-Host:
$UserName = Read-Host "Enter username"
$Password = Read-Host "Enter password" -AsSecureString
$Credentials = New-Object System.Management.Automation.PSCredential $UserName,$Password
if ($credentials.Username -eq "user1" -And $credentials.GetNetworkCredential().password -eq "pass1")
{ ... }
Using -AsSecureString will hide the password on the screen. The $Password variable will be of type System.Security.SecureString, which can be used to create a PSCredential object as shown.
You'd need to test this, but it seems that you're able to read from the shell but not from a GUI prompt.
And just to be clear: none of this is anywhere near best-practice security. If you need authentication/authorization for these activities, step back and look at the problem again.
Workaround with two scripts?
It seems that PS2EXE doesn't support -AsSecureString in the same way that normal PowerShell does, i.e. it doesn't hide the characters. A possible workaround for this would be to collect the username and password from the user in one script and then pass them to a PS2EXE-converted script for processing.
Launch-MyScript.ps1:
$Credentials = Get-Credential
& MyScript.exe $Credentials.Username $Credentials.Password
MyScript.exe (coverted with PS2EXE):
param($Username,$Password)
$Credentials = New-Object System.Management.Automation.PSCredential $Username,$Password
if ($Credentials.Username -eq "user1" -and
$Credentials.GetNetworkCredential().password -eq "pass1")
{
...
}
The user runs Launch-MyScript.ps1 and completes the password prompt. Then the EXE is run automatically with the username and password passed in as arguments. Note that, as shown above, the password is a Secure String. Test this; I'm not using PS2EXE so it's a theoretical solution at the moment.
If you can't pass $Password along the pipeline as a Secure String object, you can convert it to text with ConvertFrom-SecureString in the first script, then conver it back with ConvertTo-SecureString in the second one.
According to this article http://windowsitpro.com/powershell/protect-your-powershell-scripts you should first set ur execution policy to AllSigned by Set-ExecutionPolicy AllSigned, then create a certificate using makecert cmdlet.
Then u can sign single script using Set-AuthenticodeSignature cmdlet or use .pfx File to Sign a Script which appears even safer.
Hope it helps a bit.

Powershell Automation - Passing Password after executing a exe file

I working on automating the specific task using powershell and getting error while passing the password. Below is my task. Below are the tasks I need to automate.
Execute exe file (For ex: export.exe)
It will prompt for password twice (Enter your password and Reenter your password)
After Entering our password Twice, It will ask for confirmarion Yes or No: (I need to give 'Yes' or No to continue )
I tried automating the above first two steps. First I get the stored password in a file using the below command
$password = get-content C:\cred.txt | convertto-securestring
Then I tried executing the below commands in script
$cred = new-object -typename System.Management.Automation.PSCredential -argumentlist $pass
Invoke-Expression "& `"C:\Program Files\XX\XX\bin\export.exe`""
But I dont know how to use the password from the file twice to continue the script. I am new to powershell. Please help me.
I don't think that your application will accept PowerShell's PSCredential object. More likely, you just have to pass plaintext password twice and then Yes.
Try this (assuming that export.exe is console application):
'Password', 'Password', 'Yes' | & 'C:\Program Files\XX\XX\bin\export.exe'
This will send 3 strings, separated by the newline (Enter) to the export.exe's stdin.

Consecutive SecureString hashes don't match

An encrypted password is stored in my .ps1 script. When setting up the script in a new environment, user has to manually configure this password at the beginning of the script. I've set up a switch parameter so the user can run the script that way and it will give the user the required hash. However, when prompting to input the password twice to make sure there are no typos - or such - in it I cannot get the password hashes to match. To demonstrate, I can manually enter this in PowerShell twice in a row and get different results entering the exact same password:
Read-Host -AsSecureString 'Enter password' | ConvertFrom-SecureString
This is with or without -Key or -SecureKey parameter. How can I prompt the user for password (twice to make sure they match) and if/when they do match, output the password hash?
This isn't a very pretty solution, but does the job decrypting the given passwords and then comparing them:
if ([Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringtoBSTR(($enterpw | ConvertTo-SecureString -Key $key))) -ne [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringtoBSTR(($enterpw2 | ConvertTo-SecureString -Key $key)))) {
Write-Host "Given passwords do not match"
Break
}