Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for RemoteSession over SSH with Password #21114

Closed
Nova-Logic opened this issue Jan 20, 2024 · 19 comments
Closed

Support for RemoteSession over SSH with Password #21114

Nova-Logic opened this issue Jan 20, 2024 · 19 comments
Labels
Issue-Enhancement the issue is more of a feature request than a bug Resolution-Duplicate The issue is a duplicate. WG-Reviewed A Working Group has reviewed this and made a recommendation WG-Security security related areas such as JEA

Comments

@Nova-Logic
Copy link

Summary of the new feature / enhancement

It is currently possible with pwsh to connect from linux to windows over SSH
with an pubkey or with the help of a regular password.
Both methods are working, but the auth method with a password has some benefits
because the remote shell will run under the users credentials with a valid windows token.

Commands that require a valid windows credentials token will then work
Get-VM -ComputerName @("server1", "server2", "server2")

Proposed technical implementation details (optional)

Option1:
SSHConnectionInfo does currently not allow to set an user password.
it could await the output of "ssh" process on "Password:" and write
the password into the input stream

Option2:
Some command to upgrade the pssession with a valid WindowsUserToken
like "Switch-User"

@Nova-Logic Nova-Logic added Issue-Enhancement the issue is more of a feature request than a bug Needs-Triage The issue is new and needs to be triaged by a work group. labels Jan 20, 2024
@rhubarb-geek-nz
Copy link

rhubarb-geek-nz commented Jan 20, 2024

There are various Linux/UNIX solutions based around 'sshpass' but they all have the weakness that at some point the password is in the clear. The purpose of the public/private keys is that passwords are never sent over the net so cannot be subject to man-in-the-middle.

Windows authentication is an odd beast. My understanding is that you can use ssh with the public/private keys and gain full rights if the user is already currently logged into the machine, eg if you login with ssh to your own windows desktop machine while the desktop is logged in. So this does sound like a chicken and egg situation,

  • use some secure mechanism to login to windows on the machine using username/password to start a session
  • while that is alive you can login with ssh and the keys.

I would recommend against a custom PowerShell mechanism which involves passwords in cleartext.

My understanding is that the reason is that user profiles are only fully loaded from the registry etc with the username/password login. However Windows Desktop login today seems to use username and a pin.

That also said, it is a general problem that some component needs a password entered but it is deep in the chain and unaware of the actual UI mechanism in use. For instance gnupg lets you set up a password agent for entering the password. But then the whole point of the keys is to avoid this problem and let an ssh key agent manage the keys securely when hopping from one machine to another.

@Nova-Logic
Copy link
Author

The problem is with linux&windows interop. Currently if you’re connected with pub key you will not get windows/ad user session, that would be needed in a lot of cases. Also the only time when password would be clear -when an app actually will echo it to the session, and it would be in memory, since connection is already encrypted before the login.

@rhubarb-geek-nz
Copy link

The problem is with linux&windows interop.

I think you would have the same problem if you SSH from Windows to Windows using SSH keys.

Currently if you’re connected with pub key you will not get windows/ad user session

Yes, unless the user is already logged in, eg try SSH into a Windows desktop using keys with user already logged into desktop.

Also the only time when password would be clear

Password in the clear is still in the clear whether it is in memory, environment variable or command line argument. If you are on a shared host you are at risk of exposing those credentials, for instance this is why if you look at modern cryptographic API they use char array for passwords, not strings because you can clear the array after use, not so with a string which will only disappear when the garbage collector gets round to it. The password is still at risk over an encrypted session with a man-in-the-middle attack, especially if you were cavalier about accepting entries into your .ssh/known_hosts and did not validate the thumbprints.

I am sure you may find a solution but it does not mean it would not be acceptable all, or pass a serious security review.

If you are already on Linux, I would try arranging a pipeline that uses the existing sshpass mechanism, it already exists and its problems are understood, before writing a new component that needs to pass a security review before acceptance.

@rhubarb-geek-nz
Copy link

So that you know that I have a bit of knowledge in this area, I wrote Wishstream which uses SSH.NET for the SSH layer. This API provides a callback mechanism when a password is required, so code does not have monitor a stream looking for password prompts etc, the password is provided directly to the SSH API which passes it to the server in the SSH packets. As an example, in my app when the callback was invoked I presented a dialog to enter the password.

@jhoneill
Copy link

jhoneill commented Jan 20, 2024

Summary of the new feature / enhancement

It is currently possible with pwsh to connect from linux to windows over SSH with an pubkey or with the help of a regular password. Both methods are working, but the auth method with a password has some benefits because the remote shell will run under the users credentials with a valid windows token.

Actually that is not it. Some logons give you a session without any means of logging on from that session to another box. Classic case: I have a Kerberos Ticket Granting Ticket in my session; I want a session to remote box so I present my TGT to Kerberos and I get a ticket for the remote box. I present that to the box and get a session. I run a command in that session which wants to talk to a 3rd box but it can't ask Kerberos for ticket (no TGT). Search for "Two hop problem" :-)
If I logon to that remote box with my name and plain text password, there is the option for the box to keep the plain password in memory, and provide it on request, if the third box accepts plain text passwords, or something generated from them as a login we can get logged in.
Not surprisingly security folk don't like that.

@237dmitry
Copy link

Windows authentication is an odd beast. My understanding is that you can use ssh with the public/private keys and gain full rights if the user is already currently logged into the machine

If you are in the Administrators group, the keys and sshd_config are located in $env:ProgramData\ssh, so there is no need to log into your account on the Windows computer. I often connect to a Windows laptop that has just booted to the welcome screen and the network is up.

@Nova-Logic
Copy link
Author

actually my use case - I'm building API/lib to run some posh scripts on remote win machines. So I need not only administrator local access, but a valid domain session. without that it seems I would be needed to go not so go route to create an agent that would run needed scripts from service account. this looks odd since PowerShell meant to be an instrument for local+remote host management.
Microsoft stopped developing OMI for *nix platforms and remove proper PowerShell WSMan support for *nix platforms and made ssh support that is only partially usable. I think Microsoft SHOULD add proper ssh connection handling with password(and proper net user sessions for that case). that's what we have on every *nix system for remote administration. Without that it's hard to renderer remote admin of win hosts via ssh usable.

@rhubarb-geek-nz
Copy link

actually my use case - I'm building API/lib to run some posh scripts on remote win machines

If you are actually doing an API or lib then you could look at using SSH.NET to do the password authentication "correctly"

Microsoft SHOULD add proper ssh connection handling with password

However the rest of the world is moving away from SSH with password and recommending SSH keys and key agents. If you do "man ssh" on macOS or Linux, I don't think you will find a command line parameter or environment variable for password.

My theory ( only a theory ) is that a password is ultimately needed to authenticate with AD using the LDAP protocols, hence why things need an actual password at some point.

@jhoneill
Copy link

PowerShell meant to be an instrument for local+remote host management.

It is. But you can't make the double hop problem go away.

If I logon interactively to a windows machine that machine will use my credential to log on to other services (and this goes back before Kerberos came in). So I can connect to and manage any machine on the network, but crucially remote sessions don't get my credentials, so they can't logon to other further remote sessions. Although you're seeing this as an SSH / from-linux-to-windows issue, it's also a WSMan / from windows-to-windows issue. The one oddity is the security flaw-by-design in ssh which allows a session to opened using a plain text password which can the be accessed from the session.

@SteveL-MSFT
Copy link
Member

OpenSSH itself recommends against non-interactive password auth as it makes it more likely for people to put passwords in scripts and passwords are less secure than pub key auth. Recommendation would be use keyboard-interactive password auth the first time to deploy your pub key.

I also understand that some hardware that supports SSH ONLY supports an OEM pre-defined password. In those cases, you can use SSH_ASKPASS as a workaround.

@SteveL-MSFT SteveL-MSFT added WG-Security security related areas such as JEA WG-NeedsReview Needs a review by the labeled Working Group and removed Needs-Triage The issue is new and needs to be triaged by a work group. labels Jan 22, 2024
@Nova-Logic
Copy link
Author

Nova-Logic commented Jan 23, 2024

@SteveL-MSFT thanks for reply. But the problem is more complicated. I am needed not just an access via script, but from dotnet(c#), and usage of SSH_askpass in that cases looks like I would actually be needed to implement it in some extension to your lib, but this functionality is much more important . Let's look at some use cases:
1)listing of domain smb shares via remote posh call
2)making calls to other domain services like DC's and so on
3)actually I believe that lack of that( not only lack of ssh password auth, but it also seems lack of win-openssh ability to get user/domain user session from AD) is part of there reason why admin center currently win only, since only wsman supports user+pass auth that allows getting net user session
Pubkey auth can actually work, but if win-openssh would start to support AD auth via stored in AD public key, that would allow getting proper network session

@jborean93
Copy link
Collaborator

jborean93 commented Jan 23, 2024

An alternative is to use Kerberos auth and enable delegation. Like WinRM using Kerberos delegation is more secure than things like CredSSP/plaintext password auth as your password isn't actually send across the wire. Sending your password across the wire is a massive risk because if the target host is compromised, or the network transport encryption used is breakable then the bad actors have your password to do whatever they want. The password is not time limited and can be used to easily translate to other authentication protocols that a service might need.

Using Kerberos with delegation not only stops your password from every leaving the device but it also allows you to constrain the services the delegation is for allowing you to limit the exposure when connecting to a compromised host. Even better is that if done correctly you don't even need to have a password embedded in your script, you can either rely on things like PAM to get a ticket for you at logon like Windows does or setup a keytab to avoid embedding a password in your script.

Three things need to be in place to use Kerberos authentication

  • Kerberos is setup and configured on your client
    • This is probably the hardest bit to solve but if you have Linux devices in your domain environment there's a good chance it's already done so
    • In my case I just have installed the Kerberos libraries installed and DNS does the rest for me
    • You can use the /etc/krb5.conf file if you cannot rely on things like DNS or want custom settings for your environment
  • Client needs to be told to allow Kerberos auth
    • This can be done through ~/.ssh/config or through the -Options parameter on Invoke-Command
    • I typically add the following to my ~/.ssh/config to avoid having to do it as part of Invoke-Command
Host *.domain.com
    GSSAPIAuthentication yes
# This will do unconstrained kerb delegation, this can be dangerous so set as your own risk.
# Depending on your krb5.conf settings this might also require AD to be configured to allow
# this or not
    GSSAPIDelegateCredentials yes
  • Server
    • The server needs to allow Kerberos auth, GSSAPIAuthentication yes in the sshd_config
    • If using constrained or resource based delegation you need to configure AD accordingly

Once setup you can utilise it in PowerShell

Invoke-Command -HostName server.domain.com { 'foo' } -UserName user@DOMAIN.COM

# If you don't have it enabled in your ssh config file
Invoke-Command -HostName server.domain.com { 'foo' } -UserName user@DOMAIN.COM -Options @{GSSAPIAuthentication='yes'}

In the end you have a few options available to you to avoid the double hop problem

  • Auth that supports delegation in some way
    • Kerberos (constrained or unconstrained), CredSSP for WinRM
    • Kerberos (constrained or unconstrained), Plaintext Password for SSH
  • -Credential option on many cmdlets that can be used to auth on the next hop
  • Impersonation on the remote side with explicit credentials, useful when a cmdlet doesn't support a -Credential option

While it would be nice if PowerShell did support a password option through something like the -Credential parameter it's unfortunately not practical to do so in the way it's been implemented currently. This is because ssh (the binary pwsh calls) doesn't have a native way to provide a password non-interactively outside of SSH_ASK_PASS. There exists tools like sshpass that try to provide a workaround for this scenario but they cannot be guaranteed to be present as it's separate from ssh itself. There's also the problems inherent with password auth like weak passwords, how to embed them safely in a script where other protocols are generally recommended.

In short delegation is a complex issue, it's full of security risks as how you do the delegation can have dramatic implications on server trust and what you are allowed to delegate to. I don't think PowerShell is in the position here to solve that problem unfortuantely.

@Nova-Logic
Copy link
Author

Nova-Logic commented Feb 7, 2024

@jborean93 in the docs for the RunspaceConnectioninfo for the SshConnectionInfo I don't see a way to use that in my C# project. https://learn.microsoft.com/en-us/dotnet/api/system.management.automation.runspaces.runspaceconnectioninfo?view=powershellsdk-7.4.0

And that is the main problem. In 2024 ,after so many years from powershell core release, from the release of win-openssh it is really strange that there are simply no good way to manage windows hosts remotely from *nix. I believe it is the main reason why admin center could be deployed only on windows, since this problem just do not exist due to using of wsman, which is allowing just that.
And actually Microsoft intentionally doing that:
https://learn.microsoft.com/en-us/windows-server/administration/openssh/openssh_keymanagement

A remote session opened via key based authentication does not have associated user credentials and hence is not capable of outbound authentication as the user, this is by design.

If windows ssh server for example would have such thing as storing ad pub keys in AD and verify them via ad and auth user as net user that would also be good solution. We already have linux servers that authenticates into AD via keys stored in custom AD field

Class which defines connection path to a remote runspace that needs to be created. Transport specific connection paths will be derived from this.
Learn about OpenSSH Server key-based authentication, generation and deployment for Windows using built-in Windows tools or PowerShell.

@jborean93
Copy link
Collaborator

jborean93 commented Feb 7, 2024

in the docs for the RunspaceConnectioninfo for the SshConnectionInfo I don't see a way to use that in my C# project.

You can use this constructor to create an SSHConnectionInfo with custom options. The actual property is unfortunately not exposed publicly so you cannot set them after creating the object but this constructor will still at least be able to set them.

One thing to note is that I did notice SSHConnectionInfo requires a valid Runspace to be set on the default thread for it to work. It uses it to find the ssh executable do if running this from a pure C# code you would have to do

Runspace.DefaultRunspace = Runspace.CreateRunspace();
Runspace.DefaultRunspace.Open();

// Define the SSH options
Hashtable sshOptions = new()
{
    { "GSSAPIAuthentication", "yes" }
};
// Create the connection info with the options
SSHConnectionInfo connInfo = new("user@DOMAIN.COM", "computer", null, 22, "powershell", 30, sshOptions);

using Runspace remoteRunspace = RunspaceFactory.CreateRunspace(connInfo);
remoteRunspace.Open();

// You no longer need the thread Runspace to be set.
Runspace.DefaultRunspace.Close();
Runspace.DefaultRunspace = null;

using PowerShell ps = PowerShell.Create(remoteRunspace);
ps.AddScript("'test'");
ps.Invoke();

In 2024 ,after so many years from powershell core release, from the release of win-openssh it is really strange that there are simply no good way to manage windows hosts remotely from *nix.

It's honestly the same as well for the other way around, it's ssh which generally frowns upon password authentication in favour of other things like ssh key auth. If you really want to use password auth have a look out for the community meeting in March where I'm hoping to showcase my RemoteForge project which I have a sudo and ssh example with support for a credential provided in PowerShell

PS /home/jborean/dev/SSHForge> $sshInfo = New-SSHForgeInfo -Credential user

PowerShell credential request
Enter your credentials.
Password for user user: ...

PS /home/jborean/dev/SSHForge> Invoke-Remote $sshInfo { whoami }
user

@Nova-Logic
Copy link
Author

@jborean93 many thanks! I would definitely try that!

@franklupo
Copy link

Hi,
why not use Renci.SshNet instead of the ssh and ssh.exe commands?

best regards

@SteveL-MSFT
Copy link
Member

Dupe of #5782

@SteveL-MSFT SteveL-MSFT added WG-Reviewed A Working Group has reviewed this and made a recommendation Resolution-Duplicate The issue is a duplicate. and removed WG-NeedsReview Needs a review by the labeled Working Group labels Apr 22, 2024
Copy link
Contributor

This issue has been marked as duplicate and has not had any activity for 1 day. It has been closed for housekeeping purposes.

Copy link
Contributor

microsoft-github-policy-service bot commented Apr 23, 2024

📣 Hey @Nova-Logic, how did we do? We would love to hear your feedback with the link below! 🗣️

🔗 https://aka.ms/PSRepoFeedback

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Issue-Enhancement the issue is more of a feature request than a bug Resolution-Duplicate The issue is a duplicate. WG-Reviewed A Working Group has reviewed this and made a recommendation WG-Security security related areas such as JEA
Projects
None yet
Development

No branches or pull requests

7 participants