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
Related
Environment:
PowerShell 5.1
Windows 2016 Standard
Windows 10 Pro
Just asking here if syntax is fundamentally correct...
$hostSession = New-PSSession -ComputerName $hostName -Credential $cred
$versionFolder = "c:\temp"
$sspLatestVer = Invoke-Command -Session $hostSession -ScriptBlock { param($path) (Get-ChildItem $path | Sort-Object LastWriteTime -Descending | Select-Object -First 1).Name } -ArgumentList $versionFolder
Update:
The following works on one machine but not on another:
$versionFolder = "\\COMPUTER01\c$\temp"
$sspLatestVer = (Get-ChildItem $versionFolder | Sort-Object LastWriteTime -Descending | Select-Object -First 1).Name
Error Message for machine that doesn't work
Get-ChildItem : Cannot find path '\\COMPUTER01\c$\temp' because it does not exist.
At C:\temp\candidate2.ps1:24 char:18
+ $sspLatestVer = (Get-ChildItem $versionFolder | Sort-Object LastWrite ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (\\COMPUTER01\c$\temp:String) [Get-ChildItem], ItemNotFoundException
+ FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetChildItemCommand
OP Error Message:
New-PSSession : [COMPUTER01] Connecting to remote server COMPUTER01 failed with the following error message : WinRM cannot process the request. The following error with errorcode 0x80090311 occurred while using
Kerberos authentication: We can't sign you in with this credential because your domain isn't available. Make sure your device is connected to your organization's network and try again. If you previously signed in on
this device with another credential, you can sign in with that credential.
Possible causes are:
-The user name or password specified are invalid.
-Kerberos is used when no authentication method and no user name are specified.
-Kerberos accepts domain user names, but not local user names.
-The Service Principal Name (SPN) for the remote computer name and port does not exist.
-The client and remote computers are in different domains and there is no trust between the two domains.
After checking for the above issues, try the following:
-Check the Event Viewer for events related to authentication.
-Change the authentication method; add the destination computer to the WinRM TrustedHosts configuration setting or use HTTPS transport.
Note that computers in the TrustedHosts list might not be authenticated.
-For more information about WinRM configuration, run the following command: winrm help config. For more information, see the about_Remote_Troubleshooting Help topic.
At C:\Users\RSTEST\Documents\candidate2.ps1:17 char:16
+ ... hostSession = New-PSSession -ComputerName $hostName -Credential $cred
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : OpenError: (System.Manageme....RemoteRunspace:RemoteRunspace) [New-PSSession], PSRemotingTransportException
+ FullyQualifiedErrorId : AuthenticationFailed,PSSessionOpenFailed
Invoke-Command : Cannot validate argument on parameter 'Session'. The argument is null or empty. Provide an argument that is not null or empty, and then try the command again.
At C:\Users\RSTEST\Documents\candidate2.ps1:19 char:41
+ $sspLatestVer = Invoke-Command -Session $hostSession -ScriptBlock { p ...
+ ~~~~~~~~~~~~
+ CategoryInfo : InvalidData: (:) [Invoke-Command], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.PowerShell.Commands.InvokeCommandCommand
Remove-PSSession : Cannot validate argument on parameter 'Name'. The argument is null or empty. Provide an argument that is not null or empty, and then try the command again.
At C:\Users\RSTEST\Documents\candidate2.ps1:20 char:24
+ Remove-PSSession -Name $hostSession
+ ~~~~~~~~~~~~
+ CategoryInfo : InvalidData: (:) [Remove-PSSession], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.PowerShell.Commands.RemovePSSessionCommand
Two issues here:
First, see WinRM cannot process the request. Error 0x80090311
If the remote system is in the same domain, and you are already logged in with a domain account that is an administrator on that system, then there would be no need to specify a credential for New-PSSession
If the systems are in different forests that have a trust with each other, note that there is a need to use the fully qualified domain name (FQDN) of the remote host for Kerberos authentication to function correctly.
Second, regarding:
$versionFolder = "\\COMPUTER01\c$\temp"
Note that remote sessions normally do not have access to network shares, even when presumably running under the credentials of an administrative user.
This is known as the "second hop problem". There have been various posts about it:
https://learn.microsoft.com/en-us/powershell/scripting/learn/remoting/ps-remoting-second-hop?view=powershell-5.1
https://devblogs.microsoft.com/scripting/enable-powershell-second-hop-functionality-with-credssp/
This may work from COMPUTER01 itself, since it could be aliased to local drive access.
I'm trying following powershell script to remowe to windows 2016.
$password = ConvertTo-SecureString "Password" -AsPlainText -Force
$cred= New-Object System.Management.Automation.PSCredential ("username", $password )
enter-pssession -computername 192.168.xxx.xxx -credential $cred
When login with user that has "Adminstrators" permission, it works just fine, but when login with user that only has "Users" permission, it gets access is denied error.
So, What should I do to make "Users" to login with powershell?
OK, I follow the guide below
https://www.sevecek.com/EnglishPages/Lists/Posts/Post.aspx?List=f6e49214-a43d-4fa5-9537-fb46eabe0cb8&ID=4&Web=6dbd0194-ad16-4838-ad08-7f33e3009473
And I can remote Windows Server 2016 with normal user.
But when I tried following script, the exception happens again.
[192.168.XXX.XXX]: PS C:\Users\TestUser\Documents> ([ADSI] "WinNT://localhost/TestUser,user").ChangePassword("#EDC4rfv", "1qaz#WSX")
And the error message is
Exception calling "ChangePassword" with "2" argument(s): "Access is denied.
"
At line:1 char:1
+ ([ADSI] "WinNT://localhost/TestUser,user").ChangePassword("#EDC4rfv", " ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : CatchFromBaseAdapterMethodInvokeTI
Does that mean even normal user can remote to Windows Server 2016, they still can't run commands?
To use PowerShell remoting(default endpoint "Microsoft.PowerShell"), the user should be part of Administrators group in remote machine.
You can tackle this by creating an Endpoint and giving the normal user permission to access it on the remote machine.
More about it is in below link.
https://blogs.technet.microsoft.com/heyscriptingguy/2014/03/31/introduction-to-powershell-endpoints/
I’m trying to run a PowerShell script on SYSTEM1, which executes robocopy on SYSTEM2, copying files to SYSTEM3,4,5,etc.
SYSTEM1 and SYSTEM2 are on the same domain, but SYSTEM2 is not behind a firewall (hence the need to run robocopy from SYSTEM2 and not SYSTEM1).
SYSTEM3,4,5 are on different domains than SYSTEM2, as well as different domains than each other.
I set the script up like this (it uses the net use command to prompt the user for credentials for the different domains):
Foreach($server in $servers) {
$command = {
param($cred, $server);
$error.clear();
# Stored credentials in local variables
$user = $cred.GetNetworkCredential().username
$pass = $cred.GetNetworkCredential().password
#establish connection from SYSTEM2-> $server
net use \\$server\c$\Deployments /delete
net use \\$server\c$\Deployments /USER:$user $pass
# Check to see if C:\Deployments exists on server, and if not create it.
if ((Test-Path \\$server\c$\Deployments) -eq $FALSE) {
$c = {
New-Item \\$server\c$\Deployments -type directory
}
$ws = Invoke-Command -ComputerName $server -Credential $cred -ScriptBlock $c
}
# Copy over the deployment packages
$dest = "\\$server\Deployments\$DeploymentDate\$CurrentDirectoryName"
robocopy $CurrentDirectoryPath $dest /W:20 /R:15 /e /XF CopyPackage.ps1
# Delete connection from SYSTEM2 -> $server
net use \\$server\c$\Deployments /delete
However, the net use command returns an error after the credentials are entered:
The network connection could not be found.
+ CategoryInfo : NotSpecified: (The network con...d not be found.:String) [], RemoteException
+ FullyQualifiedErrorId : NativeCommandError
+ PSComputerName : SYSTEM2
More help is available by typing NET HELPMSG 2250.
System error 55 has occurred.
+ CategoryInfo : NotSpecified: (System error 55 has occurred.:String) [], RemoteException
+ FullyQualifiedErrorId : NativeCommandError
+ PSComputerName : SYSTEM2
The specified network resource or device is no longer available.
[SYSTEM3] Connecting to remote server failed with the following error message : WinRM cannot process the request. The
following error occured while using Kerberos authentication: There are currently no logon servers available to service
the logon request.
Possible causes are:
-The user name or password specified are invalid.
-Kerberos is used when no authentication method and no user name are specified.
-Kerberos accepts domain user names, but not local user names.
-The Service Principal Name (SPN) for the remote computer name and port does not exist.
-The client and remote computers are in different domains and there is no trust between the two domains.
After checking for the above issues, try the following:
-Check the Event Viewer for events related to authentication.
-Change the authentication method; add the destination computer to the WinRM TrustedHosts configuration setting or
use HTTPS transport.
Note that computers in the TrustedHosts list might not be authenticated.
-For more information about WinRM configuration, run the following command: winrm help config. For more
information, see the about_Remote_Troubleshooting Help topic.
+ CategoryInfo : OpenError: (:) [], PSRemotingTransportException
+ FullyQualifiedErrorId : PSSessionStateBroken
+ PSComputerName : SYSTEM2
The network connection could not be found.
+ CategoryInfo : NotSpecified: (The network con...d not be found.:String) [], RemoteException
+ FullyQualifiedErrorId : NativeCommandError
+ PSComputerName : SYSTEM2
More help is available by typing NET HELPMSG 2250.
I’ve read this could be a “double-hop” issue (as detailed here), but I’m not sure how to edit the script to use CredSSP instead of Kerberos (or if this is even the problem).
Any ideas?
Posting this solution in case someone is still having an issue with a simple resolution to DoubleHop without using CredSSP.
Try this out:
https://www.powershellgallery.com/packages/Invoke-PSSession
It Invokes a PSSession, then Registers a PSSessionConfiguration with the Credentials that you provided. Basically providing the credentials for that DoubleHop
Then use Invoke-Command with that new PSSession. It should have the required privileges to do what you need.
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...
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.