Powershell Secure password to work on any machine - powershell

I need to write a powershell script that i can run on any machine to connect to a server.
Does the secure-string encrypt using the machine or user i.e will a secure password work on any machine in the domain or can it only be decrypted on the machine it was created on. If it is the latter is there away to encrypt the password so i can run the script on any machine

To work on other machines you'll need to create a key for use with the ConvertTo-SecureString and ConvertFrom-SecureString cmdlets.
PS C:\> $Key = (3,4,2,3,56,34,254,222,1,1,2,23,42,54,33,233,1,34,2,7,6,5,35,43)
PS C:\>$StandardString = ConvertFrom-SecureString $SecureString -Key $Key
http://www.leeholmes.com/blog/2006/06/01/securestrings-in-powershell/
By default, the SecureString cmlets use Windows’ Data Protection API
when they convert your SecureString to and from a plain text
representation. The encryption key is based on your Windows logon
credentials so only you can decrypt the data that you’ve encrypted.
If you want the exported data to work on another system or separate
user account, you can use the parameter sets that let you provide an
explicit key.

That's a great question. Here's a link to how to save your credential. I got this set up and I'm going to try my credential string on another computer logged in with another account. I'll let you know my result.
Update
I would have to say it didn't work for me. I went on the other person's machine logged in as them. I have my Credentials set up in a script called Get-MyCred:
$username = 'Domain\MyName'
$password = cat '\\server\share\securestring.txt' | convertto-securestring
$cred = new-object -typename System.Management.Automation.PSCredential -argumentlist $username, $password
return $cred
When I run the line where it gets my password I get an error on the other persons machine.
ConvertTo-SecureString : Key not valid for use in specified state.
At line:1 char:56
+ Get-Content O:\BCKUP\MyScripts\Cred\securestring.txt | ConvertTo-SecureString
+ ~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [ConvertTo-SecureString], CryptographicException
+ FullyQualifiedErrorId : ImportSecureString_InvalidArgument_CryptographicError,Microsoft.PowerShell.Commands.ConvertToSecureStringCommand
I even get the error when I log into another computer with my credentials.

Related

Powershell securely logging in with user credentials

Is there a way in Powershell to securely log in to a server where the authentication process is "protected". I am fully aware of the use of credentials and secure strings to encrypt a password. My concern is what if someone gets gains access to the computer where the script resides and alters its intended usage but maintains the authentication information. Would they be able to then authenticate to AD and run their own script? Is there a way to prevent this with Powershell?
As far as I know, if you save your password like this:
read-host -assecurestring | convertfrom-securestring | out-file C:\cred.txt
It can only be used by you on that machine. So any other person that lays his hand on that file can not use it
Edit
Tested it. Tried to open such a file logged in as someone else:
PS> $pass = Get-Content .\credgj.txt|ConvertTo-SecureString
ConvertTo-SecureString : Key not valid for use in specified state.
At line:1 char:34
+ $pass = Get-Content .\credgj.txt|ConvertTo-SecureString
+ ~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [ConvertTo-SecureString], CryptographicException
+ FullyQualifiedErrorId : ImportSecureString_InvalidArgument_CryptographicError,Microsoft.PowerShell.Commands.ConvertToSecureStringCommand

Entering password automatically in enter-pssession

Im currently making a Powershell Script in Powershell ISE that is going to be used for entering all of the servers we're hosting and grabbing all the users from the servers ActiveDirectory. To do that I have to connect to all servers automatically (There are many servers but only 42 that we need to access). Let me explain what I've done so far and what te actual problem is.
So as you know there are many different servers, so we had to read all the server IP:S/Usernames/Passwords from a excel file that a colleague made, and then place them into arrays.
From there, we made a for loop looking like this:
for ($S = 0; $ -le $ServerAdressArray.Length; $S++)
{
if ($ServerAdressArray[$S] -like '192.168.*.10')
{
GetData($S)
}
}
What it does is going through the array filtering out all the local IP-Adresses from the array, if it finds a local ip adress, it runs the GetData function which looks like this at the moment:
function GetData([int]$arg1)
{
Enter-PSsession -ComputerName $ServerAdressArray[$arg1] -Credential $UsernamesArray[$arg1] $PasswordArray[$arg1]
}
What I want it to do is to use the row number it found the local IP-Adress on and then use that number to locate the correct Username and Password to log in with on that specific server.
The problem is, i have to enter the password in powershell for every single server. And i just want to enter it on the same line as Enter-PSSession.
If you want more specific details, let me know. Also, I'm new to this type of scripting so if you cold be as basic as possible in your explanations that would be great :)
Thank you.
The problem here is how you're passing the "Credential" parameter. It should be of type PSCredential.
Assuming you've stored the username and password in clear text in your file you can create a credential object directly:
New-Object PSCredential -ArgumentList #("a", ("p"|ConvertTo-SecureString -AsPlainText -Force))
For your example :
Enter-PSsession -ComputerName $ServerAdressArray[$arg1] -Credential (New-object PSCredential -ArgumentList #($UsernamesArray[$arg1], ($PasswordArray[$arg1]|ConvertTo-secureString -AsPlainText -Force)))
However; if you're interested in returning some data for each server back to the executing host (e.g. for further processing) you wouldn't want to enter the session, you would want to use Invoke-command instead.
E.g.
Invoke-command -ComputerName $ServerAdressArray[$arg1] -Credential (New-object PSCredential -ArgumentList #($UsernamesArray[$arg1], ($PasswordArray[$arg1]|ConvertTo-secureString -AsPlainText -Force))) -Scriptblock $scriptblockToExecute
Hi CmdrTchort/Richard (:P). Thank you for the answer!
All the passwords in the excelfile are encrypted for security reasons. I am currently working on a function that will decrypt the password before using it.
I've looked around a bit more on the internet and i stumbled across this post:
Using PowerShell credentials without being prompted for a password
I tried what Jeroen Landheer said and the function now looks like this:
function GetData(int[$arg1])
{
$secstr = New-Object -TypeName System.Security.Securestring
$PasswordArray[$arg1].ToCharArray() | ForEach-Object {$secstr.AppendChar($_)}
$cred = new-object -typename System.Management.Automation.PSCredential -argumentlist $username, $secstr
$session = new-pssession -computername $ServerAdressArray[$arg1] -credential $UserNameArray[$arg1] $PasswordArray[$arg1]
}
The Prompt is appearing so the password hasn't automatically been filled in and when i close the prompt(s). I get this error:
New-PSSession : A positional parameter cannot be found that accepts argument '(encryptedpassword)'.
At C:\xxxxxxx\xxxxx\xxxxxx\superfile.ps1:109 char:16
+ ... $session = new-pssession -computername $ServerAdressArray[$arg1] -cr ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [New-PSSession], ParameterBindingException
+ FullyQualifiedErrorId : PositionalParameterNotFound,Microsoft.PowerShell.Commands.NewPSSessionCommand
Do I have to enter some kind of positional parameter or does it now work because its encrypted?

Run BAT file as a Local User Account

I pulled this from another question, but I cannot seem to make this work.
I need to run this .bat file as a local admin account. I want users to be able to run and install this without having local admin rights.
I'm not sure what's wrong though.
$username = 'localadmin'
$password = 'passwordforlocaladmin'
$securePassword = ConvertTo-SecureString $password -AsPlainText -Force
$credential = New-Object System.Management.Automation.PSCredential $username, $securePassword
Start-Process -Filepath "p:\kaceInstaller\kaceinstall3.bat" -Credential $credential
The error I'm getting back is:
Start-Process : This command cannot be executed due to the error: The directory
name is invalid.
At P:\kaceInstaller\misc\kaceSetup.ps1:7 char:14
+ Start-Process <<<< cmd -Credential $credential
+ CategoryInfo : InvalidOperation: (:) [Start-Process], InvalidOperationException
+ FullyQualifiedErrorId : InvalidOperationException,Microsoft.PowerShell.Commands.StartProcessCommandy
If you want to allow users to run something as a local administrator account without effectively giving them the password to the local admin account, I would suggest to create a scheduled task running as a local admin. Users can manually trigger that task, which will then be executed under the local admin account. Creating the task withoug saving the credentials should work, but even if you have to save the credentials they won't be accessible to your users.
For access to network shares you may need to connect/disconnect the share with explicit credentials from within the script that the scheduled task runs, though, because the local account usually doesn't have permission to access the network drives mapped by your domain user.
net use X: \\server\share\kaceInstaller password /user:DOMAIN\user
call X:\kaceinstall3.bat
net use X: /d
Make DOMAIN\user a dedicated account that has access only to \\server\share and nothing else to minimize risk.
Note that you must make sure that the script run by the task is not writable by regular users, otherwise they will be able to run arbitrary commands with admin privileges by simply modifying the script.

How to avoid the crendetial dialog box while conecting to different system using powershell?

I am making connection to the diferent system using powershell. I want this process to be automated in a way that once user hits the powershell script he gets connected to different system without entering username and password details into the dialog box. So, currently my.PS1 script as follows:
Enable-PSRemoting -Force
Set-Item wsman:\localhost\client\trustedhosts CP0001256
Restart-Service WinRM
Test-WsMan CP0001256
$credential = Import-CliXml -Path "D:\$Env:USERNAME_pass.xml"
Invoke-Command -ComputerName CP0001256-ScriptBlock { Get-ChildItem D:\ }-credential $credential
Before running my.PS1 i have executed follwing script:
$credential = Get-Credential
$credential | Export-CliXml -Path "D:\$Env:USERNAME_pass.xml"
So, when i execute my.PS1 i got error as:
Invoke-Command : Cannot process argument transformation on parameter 'Credential'. username
At my.PS1:7 char 86
+ Invoke-Command -ComputerName CP0001256-ScriptBlock { Get-ChildItem D:\ } -credential <<<< $credential
+ CategoryInfo : InvalidData: (:) [Invoke-Command], ParameterBindin..mationException
+ FullyQualifiedErrorID : ParameterArgumentTransformationError,Microsoft.Powershell.Commands.InvokeCommand
So, tell me what i am doing wrong and how can i avoid getting the credential dialog box pop up appearing.
This is a question of how to store credentials in a script. Keep in mind that this always carries some risk. You can of course store them in plain text. Then anyone with access to the script has those credentials.
Another thing you can do is take advantage of the [PSCredential] object, and store the password encrypted. Consider running this code (outside of that script):
$credential = Get-Credential # dialog pops up here, enter server creds
$credential | Export-CliXml -Path "C:\Script\$Env:USERNAME_Credential.xml"
Now in your script, you can do this:
$credential = Import-CliXml -Path "C:\Script\$Env:USERNAME_Credential.xml"
Invoke-Command -ComputerName CP0001256-ScriptBlock { Get-ChildItem D:\ }-credential $credential
The password is encrypted within that XML file, and it's encrypted with a key that is specific to the user who ran the first set of commands, so only that user will be able to effectively run the script if you do this.
This is also why I use the USERNAME environment variable as part of the file name. You can have multiple employees run the first code snippet to generate a separate encrypted file for each of them. Then your script will work successfully when any of them run it.
It also works if you have an account used for a scheduled task for example; run the snippet as that user once, then the scheduled task will work.

powershell credential rejected from server

I need to store credential in powershell to be used several times. Here on StackOverflow there are a lot of example, so I took one
$tmpCred = Get-Credential
$tmpCred.Password | ConvertFrom-SecureString | Set-Content "pwd.dat"
$password = Get-Content "pwd.dat" | ConvertTo-SecureString
$credential = New-Object System.Management.Automation.PsCredential "myDomain\myUser", $password
Get-ADUser -Credential $credential
Unfortunately I get this error and I can't find a solution
Get-ADUser : The server has rejected the client credentials.
At line:5 char:11
+ Get-ADUser <<<< "xxx" -Credential $credential
+ CategoryInfo : NotSpecified: (xxx:ADUser) [Get-ADUser], AuthenticationException
+ FullyQualifiedErrorId : The server has rejected the client credentials.,Microsoft.ActiveDirectory.Management.Commands.GetADUser
I can't see anything obviously wrong with your code, I'm guessing that this is just an example of how you are using it as you mention you need to use it in several places. Just to check that it really is the storing of the secure string failing you could check using the following, which should prove that the credentials worked before being persisted to disk:
Get-ADUser -Credential $tmpCred
One option would be to pass around the credentials rather than a file or securestring, using the type [System.Management.Automation.PSCredential] which is returned from your call to Get-Credentials and stored in the variable $tmpCred.
You could also temporarily add a call to the method GetNetworkCredentials() to ensure that your password has been decrypted correctly, the following will show the username and password (unencrypted):
$tmpCred.GetNetworkCredential().Username
$tmpCred.GetNetworkCredential().Password
Hope that helps...