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

ssh-agent: permanent loaded ssh-key storage #1487

Open
mluypaert opened this issue Oct 29, 2019 · 76 comments
Open

ssh-agent: permanent loaded ssh-key storage #1487

mluypaert opened this issue Oct 29, 2019 · 76 comments
Labels

Comments

@mluypaert
Copy link

"OpenSSH for Windows" version
7.7.2.2

Server OperatingSystem
Irrelevant

Client OperatingSystem
Windows 10 Home (18362.418)

The problem
I am using private SSH-keys encrypted with a passphrase. When using any SSH-agent, that means I have to provide my passphrase to be able to load the key and use it. I've used pageant before and there you load the key and provide the passphrase. Whenever pageant gets terminated (by shutdown, rebooting, ...) the key is removed from memory, and I have to provide my passphrase again the next time I want to use it. Every time, hence the security advantage of having an encrypted SSH key.
With the windows openssh agent however, that's a different story. I have my agent set to automatically start with windows (I believe by running Set-Service ssh-agent -StartupType Automatic) just like I did with pageant. However, the windows openssh agent seems to permanently store my SSH key somewhere after loading it to the agent once (ssh-add), because when I run ssh-add l after a restart of my computer, they encrypted key which I loaded before the restart is automatically loaded again, without requiring my passphrase again. This completely voids the advantage of a passphrase-protected SSH key and to my opinion is a big security issue.

Proposed solution
Do not store my SSH key permanently when I load it into the agent, but only temporarily store it in the agent's memory. Or at least store it in it's passphrase-encrypted form and ask for my passphrase every time the key gets loaded.

@mluypaert mluypaert changed the title ssh-agent: remove all loaded keys when shutting down ssh-agent: permanent loaded ssh-key storage Oct 29, 2019
@bagajjal
Copy link
Collaborator

ssh-agent stores the key in registry.. It is fully encrypted, only the current user can access it.. If you login to the same machine as a different user, you wouldn't be able to see the keys of others.

@mluypaert
Copy link
Author

Agreed, but other users also can't access my SSH key files if they are in my home folder, that's not the point. My point is that by storing the key in registry without the passphrase-encryption, a level of security is taken away. Anyone that can gain access to my account (malicious intruder or virus for example) now immediately has access to my unencrypted keys, without needing to know my passphrase. This completely voids the use of passphrase-protection on SSH keys, and I'm sure many users (including myself) want that extra layer of security back.

@bagajjal
Copy link
Collaborator

Not really. The registry is only accessible for SYSTEM, ADMINISTRATORS.

@bagajjal
Copy link
Collaborator

fyi, User keys are stored in Computer\HKEY_CURRENT_USER\Software\OpenSSH\Agent\Keys.

@xdhmoore
Copy link

xdhmoore commented Nov 7, 2019

Not a security expert, but this makes sense to me as well. If someone gets access to my account, they can ssh into any server I have access to since the passphrase is not required. The security of the key storage is important but not the main question. It's more about the user flow of requiring a separate password to use the key.

Also, this seems to be the behavior of ssh-agent on other systems.

@mluypaert
Copy link
Author

@xdhmoore I totally agree. (Open)SSH agents on other systems only temporarily store the key in memory, not permanently anywhere else (registry here). A config option for the windows openSSH agent to disable this permanent registry copy would fix this.

@lusitania
Copy link

lusitania commented Nov 20, 2019

Different angle: I was looking for a reason why an outdated and invalid key kept showing up in ssh-add -l although I previously removed all entries with ssh-add -D (and restarted my WSL session) while my pass vault wasn't even running. It took me an hour to find this issue and eventually found and deleted the key from the registry. IMO having ssh-add/agent store keys persistently is very non-standard and leads to confusion, uncertainty and unease. There's a reason why we use pluggable backends (KeePassXC in my case, keychain on MacOS, ...). ssh-agent is expected to be just that, an agent. Not a caretaker.

@feenes
Copy link

feenes commented Dec 5, 2019

In my opinion this is a bad choice.
Several reasons.
1.) people who used other OS'es before do expect a certain behaviour from ssh-add. GIving a program the same name, but implement it differently is confusing by definition.

2.) There is a degree of freedom and security taken away. If I chose different pass phrases for different keys, then I do have a reason and don't want my OS to decide that protecting it with my account's password is good enough until I remove the key explicitly.

If the PC ever gets stolen only one password has to be cracked and all keys are compromised

3.) As far as I know (without any explicit configuration) ssh has will try out all private keys while logging into a server. if I work for several days (add one key, logout, add another key, logout, ...)
then my agent will remember all these keys. (Let's imagine it's 20 different keys)

Only drawback is, that most servers will abort after a few wrong keys have been presented.
So not always a good idea to always drag along all ssh-keys ever added during the history of a suer account.

@jghal
Copy link

jghal commented Feb 12, 2020

It's hugely non-obvious that ssh-agent would behave this way. Everyone familiar with the OpenSSH tools is expecting the traditional ephemeral state of keys in ssh-agent. I can see how some people would want this behavior, but the default behavior here should be exactly the same as standard OpenSSH on every other OS. This should be an opt-in behavior that the user must explicitly request.

@NicoAdrian
Copy link

Has anyone found a way to disable this behaviour ?

@mluypaert
Copy link
Author

Has anyone found a way to disable this behaviour ?

@NicoAdrian I countered this behavior by defining a task through the Windows task scheduler that triggers on every shutdown or reboot and which executes a powershell script that simply executes ssh-add.exe -D

@xdhmoore
Copy link

xdhmoore commented Jun 4, 2020

Has anyone found a way to disable this behaviour ?

For what it's worth, the workaround I've landed on has been turning off the key agent and typing my all key passwords. :S

@maertendMSFT
Copy link
Collaborator

This is by design, if you would like to not have the keys registered, then you can create a cron job/scheduled task to clear them

@xdhmoore
Copy link

xdhmoore commented Jul 10, 2020

Did some experimenting with an alternative today. I've had a little bit of luck using wsl-ssh-pageant as a bridge from pageant to Win32-OpenSSH. The basics seem to work so far, but pageant doesn't seem to have much of a CLI interface to work with, unfortunately, so I'm not sure how adding/removing the keys will work, exactly. Maybe there's a way to kill pageant when the terminal exits to dump the keys (I don't see another way to remove them). I like how the AddKeysToAgent ssh config option works on Mac, so maybe one could add an ssh wrapper that adds the the key every time to pageant right before calling ssh. Adding a key seems to be idempotent or whatever--and it only prompts for your passphrase the first time, so I think that would probably work. Of course, that is smoothest if you only have one key...

@mluypaert
Copy link
Author

This is by design, if you would like to not have the keys registered, then you can create a cron job/scheduled task to clear them

@maertendMSFT I'm aware that this behavior is by design, but is is counterintuitive and unlike any other openSSH implementations most developers are familiar with (through other systems). Therefor I'm requesting to disable this behavior or at least provide an option to do so without involving some hacky cron/scheduler job (like indicated in one of my previous posts), to make Win32-OpenSSH act like any other (more secure) standard OpenSSH implementation.

@xdhmoore
Copy link

xdhmoore commented Jul 11, 2020

I agree that at least an option to turn off saving the key in the registry would be nice.

Another alternative that seems to work as an agent for Win32-OpenSSH is KeeAgent with wsl-ssh-pageant.

@bitkat
Copy link

bitkat commented Mar 15, 2021

Discovering that Windows apparently stores my private key in unlocked form was a rather unpleasant surprise. This is NOT what I expect from ssh-agent. Like most people, I use ssh-agent explicitly to have my key in volatile memory so it will disappear automatically on logout, etc. I strongly disagree with those who want an option to turn the current behaviour off (implying that it should be on by default). Following both the principle of least surprise and the principle of making default behaviour secure, it should actually be off by default.

@pdavies
Copy link

pdavies commented May 16, 2021

"Working as designed" is no defence against a design that incorporates a security vulnerability.

The purpose of the passphrase is to provide protection if the key is leaked, which in practice, often means the system on which the key is stored getting compromised. The passphrase means that the key is protected even if the user's account is compromised, so an attacker can't follow a breadcrumb trail of SSH keys to penetrate further and further into a network.

That protection is removed by storing the passphrase. It's irrelevant that the registry is encrypted, when it's decryptable with the very same malicious access we're trying to mitigate against. Worse, the protection offered by the passphrase has been taken away without the user's consent and contrary to their expectations.

Any time that a user is led to believe that they benefit from a security protection when they do not, you have a security vulnerability.

@maertendMSFT, please can you reopen this issue?

@ahicks92
Copy link

I'm also going to add my voice to this issue. I started using ssh-agent with VSCode a few days ago, and finding out that my keys are stored unencrypted in the registry is a blocker and I'm going to have to avoid using it for that reason. I can't justify putting keys which connect to our prod infra into something that's permanently keeping them around like this. this needs to be off by default.

@bagajjal
Copy link
Collaborator

@ahicks92 , The keys stored in the registry are DPAPI encrypted. only the current log in user can access them.

@ahicks92
Copy link

I still end up with implicitly unencrypted keys that just build up forever every time my laptop is logged in unless I go out of my way to delete them. For example, just deleting the file and restarting--which works on every other platform--isn't good enough, yeah? But even so, this does mean that if my laptop is ever in a shared environment even if I haven't used ssh this boot, my keys are available if anyone gains access while it's signed in.

I'm not really sure why this isn't considered a problem. Deletion cron jobs etc. are fail dangerous, not fail safe. Those of us who want them only in memory want them only in memory with reasons, I understand the "the registry is protected" argument, but it's still not good enough for my case. Am I missing something?

@aservedio
Copy link

Here I was about to promote the ideal win10 dev setup. Docker inside WSL2, not working off mounted files, and using Windows ssh-agent.

I can see now from the discussion here that the 2nd part was a bad idea.

@bitkat
Copy link

bitkat commented Nov 21, 2021

Since this issue was closed because, apparently, this is how it was designed, the obvious question arises how to address the underlying design issue. Alternatively, it might be a good idea changing the name to something that does not suggest functional equivalence with OpenSSH's ssh-agent so future users may avoid this trap. @maertendMSFT could you please share your thoughts on the proper way forward?

@bagajjal
Copy link
Collaborator

We are reopening the issue.

We are planning to enhance the ssh-agent to align with the Linux implementation and at the same time maintain the backward compatibility with previous win32-openssh ssh-agent releases.

We will allow the ssh-agent to run interactively from a terminal. If ssh-agent runs interactively then the behavior will be inline with the Linux implementation. The registered ssh keys will not be persisted.

When ssh-agent started as service, the existing behavior will continue. This is to maintain the backward compatibility. Please note, ssh-agent service is disabled by default. If user starts the ssh-agent as service then the ssh keys will be DPAPI encrypted and stored in the registry. Only the owner can retrieve the keys and no other user (including administrator) can retrieve the DPAPI encrypted keys.

@egfx-notifications
Copy link

Edit: Thinking of the ideal workflow I would like it to key the identities but re-prompt me for the passphrase after a session or expiration, but I'm not sure how that work flow would actually work on the backside when you do ssh hostname.

@immersivegamer For what it's worth, I'd also really like Windows ssh-agent to improve as so many suggested, however in the meantime you can get a more convenient and secure workflow with KeePass + KeeAgent, in current releases of KeeAgent you can turn on WindowsOpenSSH support in the settings and for me it works quite well so far. You can even configure to be prompted with a confirmation dialog each time an application wants to use a key:
https://github.com/mendhak/keepass-and-keeagent-setup

@krisavi
Copy link

krisavi commented Jul 8, 2022

From a security perspective I do think ssh-agent should not store keys forever by default. Give users the option if they want to store for longer or forever. Personally the work arounds are good enough for me to keep using as is. I'll probably use a combination of ssh-add -t option when adding more secure keys and a scheduled task with ssh-add -D as suggested for keys I don't mind hanging around for a little while or for cleanup incase I missed using -t for keys. As someone else mentioned in this thread, this not as graceful as a failure to cleanup is worse than a failure to persist.

ssh-add -t unfortunately does not work

OpenSSH_for_Windows_8.9p1, LibreSSL 3.4.3
ssh-add -t 15
Could not add identity "C:\Users\user.name/.ssh/id_rsa": communication with agent failed

Unfortunately neither does ssh-add -c work, even though it has no relation to how keys are stored or their lifetime.

I used OpenSSH ssh-agent for some time and added that workaround to somehow restore normal and expected operation. So I set up scheduled task to remove keys on boot, because in Windows you cannot so easily put on shutdown scheduled jobs. But since the key usage verification or confirmation is required at workplace I set up pageant with proper patch and ssh-wsl-bridge. For compatibility reasons I had to disable the service, so Scheduled job just fails silently every bootup. Now I had to come back to ssh-agent and tinker a bit with YubiKey because Pageant does not support -sk keys and to my surprise nothing except -sk keys support has changed and still after reboot I am able to log in without any key usage confirmation or any key passphrase or anything alike to work production servers. Heck even starting the service and I was surprised that the keys that I last added year ago were loaded in, while the keys real passphrase had been changed long time ago.
Another usage we had to test was setting time to expire for keys, that is basically only used for automation purposes and does not ask key usage for every machine it wants to access, just as long as it creates all the connections in first 60 seconds. All is well from Mac's or Linux hosts, but Windows no luck, just getting error, does not matter if I start ssh-agent from command line or through the service.

Like many others have expressed, then if MS sees that storing them in Vault or registry using DPAPI is better than storing them encrypted in memory, then great, that is just improvement, but the concerns here raised are more towards key lifecycle. I guess the problems with lifecycle comes from how MS has decided to store the keys, that there isn't any real way to clean it up automatically and adding some process to clean it up from registry when machine boots up seemed to be too much hassle. Traditional OpenSSH implementation cleans up as soon as process dies, may it be due to reboot or it being killed, just because they are stored in process memory and it is not there after reboot and is cleaned up by garbage collector when process dies. So that is where storage implementation affects the key lifecycle and on Windows there has to be extra steps done to ensure same or similar operation.

Looking at how SSH is used in practice, the issues raised in this thread are nowhere near my top concern. Hence my irritation at being called out to what I was told was a five alarm fire.

That sounds like "works for me" argumentation. If you look by thumbs ups and thumbs down reactions or comment and main concerns then if one person is happy with how things work on Microsoft, then it might not be how majority of people expect it to work from experience with the BSD, Mac, Unix, Linux etc. implementation of OpenSSH. MS version is the odd one doing things drastically different here to even call it OpenSSH port. It might have been called WinSSH as well. At least then there would have been excuse to do things different. Usecases in practice are different, MS deviation makes it unusable in my usecase, while the more traditional implementation gives enough options to make it work for me. MS version caters only specific ones, while OpenSSH catered most of them (might have been some edge cases where it was not possible to use)

Just for it not to have only criticizing, then from my side possible way how things could be changed, some inspired (stolen) from other comments, some not:
I would propose change more like that. Add possibility to generate keys into MS vault using ssh-keygen. If keys are generated that way, then you could store them in registry and autoload them on service start, but if it is from real file that has a passphrase, then after reboot they should be reloaded just in case the passphrase had been changed. I believe that is approach that should fit to everyone. If the limitation is how MS is storing the keys, then add PID of ssh-agent in there and if ssh-agent starts up with different PID, then remove the keys that have PID set up, if no PID is set for reg keys, then those are "OK" to run on different agents across all sessions. Same approach could be applied to make ssh-add -t to work. When it start to use the key, check if key is "expired" and if that is the case, then remove it and ask for passphrase to add it again. Would emulate more similar approach to other implementations than the current Windows implantation is. Yeah, there are caveats on someone modifying the time of the key and possibly being able to start ssh-agent with same PID, but it is still better than current solution where I have to add them manually if I want to set timeout for them or remove them manually before restart or just after restart via workaround to ensure that if someone had access to my Windows password cannot penetrate further into work environment.

In addition we have to rely on DPAPI to ensure the safety of the keys while adding another possible point of failure.

@alaincao
Copy link

alaincao commented Jul 8, 2022

Well, I'll do like everybody here and add my own story. This is how I even discovered this issue:

On my first try to setup SSH on Windows, everything was working as expected. A breeze. I discovered there was an ssh-agent, behaving just like everywhere else. Good! I even saw there was a service for it, so there is even no need to start it every times. Absolutely awesome! They implemented the thing like it should!
For literal weeks, every time I wanted to connect to a prod server, I did an ssh-add, entered my password and connected.
Until one day, I tried to connect, forgetting to add the key. Had I just type the return key, I noticed my mistake and was preparing myself to get rejected and retry. Then I connected... Wait a minute, how TF did I connect ?!?
I rebooted and tried again to be sure, then googled around, then landed here... and was absolutely horrified!

Had I even knew this was happening, I would have organized myself differently.
In one afternoon, I changed my mind from being amazed by the implementation to a complete lost of trust. I now make sure none of my personal SSH keys ever lands on a Windows computer. Ever. Because I fear there are other shenanigans that could be unearthed.

So from my POV, the "it works differently because Windows" and "When ssh-agent started as service, the existing behavior will continue" is a real problem. You have to make sure somehow the users know it's not behaving the same way as everywhere else. Having a different name would have been a clue...
Anyway, permanently storing the key should be an explicit option, not the default behaviour.

@vixie
Copy link

vixie commented Jul 9, 2022 via email

@alexandre-abrioux
Copy link

alexandre-abrioux commented Jan 17, 2023

While waiting for this update, I created a scheduled task that clears the keys on boot.
I'm sharing here the parameters I've used:

  1. Open the Task Scheduler (Start Menu > Search "Task Scheduler")
  2. Create a new task
  3. For the trigger, use "At log on" and select your user account
  4. For the action, use the following:
    • program: cmd.exe
    • arguments: /C "ssh-add -D"

I hope this can help others 🙂

@vixie
Copy link

vixie commented Jan 17, 2023 via email

@HiFiPhile
Copy link

HiFiPhile commented Jan 29, 2023

For anyone interested, I've created a fork which the ssh-agent storage credentials in the traditional non-persist way and has telemetry removed:
https://github.com/HiFiPhile/openssh-portable

PKCS11 is untested

@ioMatrix
Copy link

ioMatrix commented Mar 19, 2023

The latest version pageant is able to start with a --openssh-config option which will generate a named pipe usable by OpenSSH.

Details on how to enable are available here:

https://the.earth.li/%7Esgtatham/putty/0.78/htmldoc/Chapter9.html#pageant-cmdline-openssh

@J-Sorenson
Copy link

I discovered this issue within my company when we started moving from PuTTY to Microsoft's built-in OpenSSH implementation for our secure connections. We require that the SSH connections to have a separate passphrase so that if someone were to illicitly gain admin access to the PC, they still won't have access to the engineering network. I was hoping to work around this with the usual "-t" option, but apparently that is still not supported per issue #1056 from Feb 2018.

Putty Pageant drops the keys on logout. Linux ssh-agent drops the keys on logout. I don't think those design decisions were random, so permanently unlocking the keys is a perplexing "by design" decision that is counter to other implementations. We've implemented the "ssh-add -D" logout script in the group policy as a work-around, but that doesn't resolve a hard power-off situation.

We look forward to seeing ssh-agent using a more common and secure implementation in the near future.

@HiFiPhile
Copy link

@J-Sorenson

You can give a try of my fork if you want.

@J-Sorenson
Copy link

Thanks for the offer, but that won't be permitted on the corporate network. It needs to come from Microsoft or an approved 3rd-party software solution.

@vixie
Copy link

vixie commented May 20, 2023

i'm using MSYS2 now which has a normal openssh and ssh-agent, plus a terminal application called UCRT64 that's very complete. added tmux and i'm in happy land. note that i'd prefer to use microsoft's ssh but with their insistence on keeping my unlocked key in persistent (across logout or reboot) storage is so completely wrong that i can't imagine letting it possess my keying material in any form.

@aservedio
Copy link

Personally since then I fully switched to working from within WSL and using ssh-agent within it. Event went as far as building a packaging system to build WSL images pre-setup with ssh-agent and gpg-agent.

Very Linux focused, so no integration with Windows at all. But it does work nicely with VSCode and devcontainers! :)

References: info on wsl.geekstuff.dev, example for ubuntu 22.04 with systemd

@tlartaud
Copy link

tlartaud commented Aug 17, 2023

This issue is opened for years now. Is there an official fix now?

Also, I just wanted to share my opinion, from a newbie perspective. I am absolutely not expericenced as you all and cannot judge the technical aspects of the decisions made in Windows' OpenSSH. However, I think that the way the process is designed actually breaks the User Experience.

Like many users there, I was, at first usintg Putty, or even OpenSSH on Linux (or more formerly, Git for WIndows' agent), and I was expecting the same behaviors when switching to the Windows version. This means that, since more than a year, I am unnecessarily re-loading my keys through ssh-add before running a VM, or before attempting to connect to a remote server, and I am unnecessarily re-typing the passphrase again, almost every day, while my keys are already stored somewhere without my knowledge: ssh-add doesn't notice you that the key is already loaded. There are probably many users that reload their keys after a reboot, and they probably don't even know they do not need to do that. What's the point of permanently storing a key if the end-user doesn't know about it?

One day I tried to SSH to my remote, and I instantly realized I forgot to first ssh-add... But it worked... I was just shocked. At a first glance, I thought that my OpenSSH was buggy or corrupted (reboot scripts not being executed?), so I reinstalled it, and rebooted the computer. Once reinstalled, i did an ssh-add -L, and all the keys were still there, still loaded, even after a reinstallation of OpenSSH.

Well, this was really confusing.

@vixie
Copy link

vixie commented Aug 18, 2023

This issue is opened for years now. Is there an official fix now?
...

so, i can't speak for microsoft, but i think ssh has been embraced and extended, in order to differentiate windows from other ssh-capable platforms. my prediction is they'll document what the behaviour is and that it is intentional, will not change their ssh client to make this optional or add a knob to turn it off, and that this ticket will remain open until long after we are all drinking mead together in valhalla. i hope i'm wrong about any part of that.

@J-Sorenson
Copy link

Well, I was rather hoping Microsoft had abandoned the old technique of "embrace, then conflict" like they did with IE6 web standards, or the XML document standard, or... Anyhow, our solution was to apply a "ssh-add -D" to the logout process. It's not perfect, but it gets us close enough for now.

@ahicks92
Copy link

it seems that this is now quite off topic, but MS has only slight control over the SSH protocol if any at all. Just because a specific implementation is different doesn't mean they're trying to take it over, and indeed they probably can't even if they wanted to. Not having this issue resolved is annoying, but I don't think it's fair to attack people over what is almost certainly just a priority decision.

@vixie
Copy link

vixie commented Aug 18, 2023 via email

@metzz1
Copy link

metzz1 commented Sep 5, 2023

While waiting for this update, I created a scheduled task that clears the keys on boot. I'm sharing here the parameters I've used:

  1. Open the Task Scheduler (Start Menu > Search "Task Scheduler")

  2. Create a new task

  3. For the trigger, use "At log on" and select your user account

  4. For the action, use the following:

    • program: cmd.exe
    • arguments: /C "ssh-add -D"

I hope this can help others 🙂

this solution works well, thanks for sharing :)

@mokeyish
Copy link

mokeyish commented Oct 7, 2023

While waiting for this update, I created a scheduled task that clears the keys on boot. I'm sharing here the parameters I've used:

  1. Open the Task Scheduler (Start Menu > Search "Task Scheduler")

  2. Create a new task

  3. For the trigger, use "At log on" and select your user account

  4. For the action, use the following:

    • program: cmd.exe
    • arguments: /C "ssh-add -D"

I hope this can help others 🙂

this solution works well, thanks for sharing :)

It would be better if you could write a wrapper for ssh-add. When using ssh-add, a task is automatically created and delayed for 30 minutes to execute ssh-add -D.

@ynuwenhof
Copy link

ynuwenhof commented Nov 1, 2023

The workaround for this issue that I used to remove all identities on shutdown:

  1. Create a very simple PowerShell script with echo "ssh-add -D" > ssh-flush.ps1
  2. Move the PowerShell script into the C:\Windows\System32\GroupPolicy\Machine\Scripts\Shutdown folder
  3. Press WIN + R and enter gpedit.msc
  4. Navigate to Local Computer Policy > Computer Configuration > Windows Settings > Scripts (Startup/Shutdown) > Shutdown
  5. Click on the PowerShell Scripts tab and click add
  6. Click browse next to the Script Name: text box and select the previously created and moved ssh-flush.ps1 script
  7. Click OK and Apply

Now your SSH identities should be removed automatically every time you shut down Windows.

Optionally, the PowerShell script can also be executed on logoff instead of shutdown by navigating to User Configuration instead of Computer Configuration.

@vixie
Copy link

vixie commented Nov 1, 2023 via email

@snowzach
Copy link

snowzach commented Nov 8, 2023

I am not sure if anyone else is in the same boat as me but the only reason I used SSH from Windows-Land in the first place is to use the Remote SSH plugin in VS Code. Otherwise all SSH'ing I do is from WSL where the agent works as expected. I just discovered if you want to force VSCode to use SSH from WSL instead of Windows and stop using Windows SSH and agent altogether you can:

Create a bat file somewhere like your home directory called C:\Users\YourUser\ssh.bat with the contents:

C:\Windows\system32\wsl.exe bash -ic 'ssh %*'

This forces it to run the login scripts which was important for me because that sets up the SSH agent inside of the WSL environment. I happen to use this in a bashrc to start the ssh-agent:

if [ -z "$SSH_AUTH_SOCK" ]; then
   # Check for a currently running instance of the agent
   RUNNING_AGENT="`ps -ax | grep 'ssh-agent -s' | grep -v grep | wc -l | tr -d '[:space:]'`"
   if [ "$RUNNING_AGENT" = "0" ]; then
        # Launch a new instance of the agent
        ssh-agent -s -t 14400 &> ~/.ssh/ssh-agent
   fi
   eval `cat ~/.ssh/ssh-agent`
fi

Then from within VSCode set the Remote SSH Option: Remote.SSH Path: C:\\Users\\YourUser\\ssh.bat
I just did that and turned off the Windows SSH agent. Hopefully that will help a portion of you.

Edit: If it doesn't work, you may need to set your default WSL with the command: wsl --setdefault ubuntu-20.04 or whatever instance you want to use.

@ahicks92
Copy link

ahicks92 commented Nov 8, 2023

Another way to work around this if connecting to local VMs is to have a local-only passwordless key that can connect only to those VMs. This doesn't widen the impact because anyone with access to the laptop or w/e would have access to the VM data anyway.

(not always applicable of course but I don't do dev on remote servers directly)

@drujd
Copy link

drujd commented Apr 7, 2024

Optionally, the PowerShell script can also be executed on logoff instead of shutdown by navigating to User Configuration instead of Computer Configuration.

Actually, it ONLY works as a user logoff script, NOT as shutdown script run by SYSTEM. "ssh-add -D" must be run as the same user as ssh-agent.

This doesn't work (well, unless you run ssh-agent as SYSTEM):

4. Navigate to `Local Computer Policy > Computer Configuration > Windows Settings > Scripts (Startup/Shutdown) > Shutdown

@vixie
Copy link

vixie commented Apr 7, 2024 via email

@logicalextreme
Copy link

logicalextreme commented Aug 17, 2024

I just wasted over an hour trying to figure out what exactly Microsoft must be doing to cache my passphrase or decrypted key after noticing I was only getting prompts from Pageant (I still use a PPK version for other stuff).

This is mad behaviour. I get that the plaintext key is encrypted with the DPAPI, but nobody familiar with OpenSSH or any SSH agent that I'm aware of would expect this behaviour. You start the agent, you add your key, you decrypt it with your passphrase, and then if the key is removed from the agent or the agent is terminated, that key ceases to exist.

If it's going to store it in the registry like this then I don't see much point in the agent, other than being able to add keys stored outside the default path. For my use case I may as well not use the agent and store my key unencrypted in the default location in my home directory — it's still protected by the DPAPI, so anything more than that is really security through obscurity.

At first I wasn't sure whether I was more surprised by the fact this behaviour exists, the fact that it uses the Registry of all things, or that this issue has been open for almost five years without a fix. However I then realised that the behaviour's even worse than it seems and I can't see anyone having mentioned this above — not only do decrypted keys persist in the registry across reboots and agent restarts, they persist even if you delete the key files from disk and restart the agent. This may not surprise anybody familiar with this issue as the problem is that the in-memory behaviour has simply been changed to use the Registry and thus no reference to the original filepath is stored (as far as I can tell…), but I think it highlights how bonkers this is.

The behaviour of the original OpenSSH agent was modified on purpose making it less secure, and when you consider that this behaviour affects private keys and certificates it lowers the overall security of multiple systems and resources way beyond the machine running the agent. I've been really enjoying using Windows Terminal and the built-in OpenSSH client so I'm going to try out KeeAgent (thanks for the pointer @egfx-notifications!).

However it's been interesting reading the posts above and getting a feel for the difficulties that have been faced in making an "official" WIndows OpenSSH implementation. All I can do is echo others in saying that the behaviour documented in this issue really does heavily violate the principle of least astonishment for many users, and I believe that adding a section explaining the behaviour (how keys are stored, that this storage is permanent, and how to remove them) to this page on the MS docs (or even a new page in the same area documenting the agent and covering basic usage) would go a long way towards mitigating this astonishment. And even save people some time :)

@bitkat
Copy link

bitkat commented Sep 23, 2024

Shouldn't fixing this get some priority in light of Microsoft's Secure Future Initiative?

@vixie
Copy link

vixie commented Sep 25, 2024

Shouldn't fixing this get some priority in light of Microsoft's Secure Future Initiative?

security is in the mind of the beholder. if microsoft thought keeping a copy of my unlocked key in their persistent registry wasn't secure, they would not have put it there. so there's no question that they won't be taking it out, even as an option let alone as the default. my workaround was to uninstall this and install https://www.msys2.org/ instead. (this also comes with a pretty decent terminal emulator.) this uses ssh-agent in the traditional way (similar to pageant) such that when the agent dies, the unlocked key in its memory heap dies with it. just like bsd and linux. i think microsoft will never stop embracing-and-extending.

@bitkat
Copy link

bitkat commented Sep 26, 2024

i think microsoft will never stop embracing-and-extending.

It is productive nor necessary to discuss and speculate about MS' motivations. To me, this is a simple and rather obvious error that still needs to be corrected. The name "ssh-agent" is widely understood to imply certain essential functionality, but expectations are not met. Either correct that, or rename the program to protect users from unwittingly walking into a trap. The SFI has both "Secure by design" and "Secure by default" as stated security principles so there's little wiggle room here.

So, yes, they may have thought of the current behaviour as secure, which caused the issue. Time to re-think. SFI provides guidance.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests