Win32-OpenSSH icon indicating copy to clipboard operation
Win32-OpenSSH copied to clipboard

ssh-agent: permanent loaded ssh-key storage

Open mluypaert opened this issue 5 years ago • 76 comments

"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 avatar Oct 29 '19 09:10 mluypaert

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.

bagajjal avatar Oct 29 '19 18:10 bagajjal

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.

mluypaert avatar Oct 30 '19 08:10 mluypaert

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

bagajjal avatar Oct 31 '19 16:10 bagajjal

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

bagajjal avatar Oct 31 '19 16:10 bagajjal

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.

xdhmoore avatar Nov 07 '19 01:11 xdhmoore

@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.

mluypaert avatar Nov 07 '19 08:11 mluypaert

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.

lusitania avatar Nov 20 '19 11:11 lusitania

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.

feenes avatar Dec 05 '19 09:12 feenes

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.

jghal avatar Feb 12 '20 16:02 jghal

Has anyone found a way to disable this behaviour ?

NicoAdrian avatar May 12 '20 14:05 NicoAdrian

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

mluypaert avatar May 12 '20 15:05 mluypaert

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

xdhmoore avatar Jun 04 '20 19:06 xdhmoore

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 avatar Jul 09 '20 23:07 maertendMSFT

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...

xdhmoore avatar Jul 10 '20 04:07 xdhmoore

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.

mluypaert avatar Jul 10 '20 07:07 mluypaert

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.

xdhmoore avatar Jul 11 '20 18:07 xdhmoore

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.

bitkat avatar Mar 15 '21 12:03 bitkat

"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?

pdavies avatar May 16 '21 12:05 pdavies

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.

ahicks92 avatar Oct 19 '21 16:10 ahicks92

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

bagajjal avatar Oct 19 '21 17:10 bagajjal

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?

ahicks92 avatar Oct 19 '21 18:10 ahicks92

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.

aservedio avatar Nov 19 '21 18:11 aservedio

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?

bitkat avatar Nov 21 '21 12:11 bitkat

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.

bagajjal avatar Nov 30 '21 21:11 bagajjal

@bagajjal <<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.>>

thank you for reopening the issue. for my own key material, your workaround is sufficient. does this have a timeline?

also note, malware often runs in the context of a user. this may be due to a poisoned supply chain, or an infection, or deliberately installed "potentially unwanted software", or an intrusion. the mere existence of an unlocked key is a danger that ought to require opt-in on every reboot.

the digital world itself is now less safe because of microsoft's design choice here. as i wrote above, i can use your proposed workaround to restore consent in the management of my own keying material. but the default you propose to preserve will make it more likely that other microsoft devices in the world will be able to attack me (and others) in all kinds of ways.

good security is often at odds with user convenience. and that's why openssh (please don't call it "linux openssh" since many of us first encountered it on BSD) has the design it does. actual security experts decided that ssh-agent should not be persistent, for reasons microsoft seems to have misunderstood.

hopefully the microsoft implementation of gss/krb5 "tickets" does not have this same persistent behaviour.

vixie avatar Dec 31 '21 18:12 vixie

I protest the assertion that the Linux people should decide how SSH works on Windows. They do not understand the platform. No, the way Linux does things is not the perfect, nor is there any reason Windows should follow the Linux approach which is actually the result of Linux lacking a key manager, unlike Windows and macOS.

Because Linux lacks the platform key management of the modern platforms, they invented a set of solutions I regard as 'half baked' at best. I am not at all confident they really work on Linux, but trying to use Windows as if it was Linux is a sure fire way to end up in a security blunder.

Persisting user keys in the platform key vault is the obvious approach and should be the preferred approach. The windows platform does allow keys in the vault to be protected by an additional passphrase as an option. It makes sense to offer that as an option.

Contra Vixie, user convenience is a security issue. Bully users with half baked security controls imposed by some security bully and they just turn off the controls. And they are right to do that because most users understand their security needs better than a system designer that has never met them let alone one who doesn't even use their platform.

Reading this thread, it is clear that most of the people commenting have no idea of how DAPI works and have no interest in finding out.

Please abort these proposed changes immediately.

hallambaker avatar Jan 01 '22 02:01 hallambaker

phillip, i am not a linux person, but i object to your tone here. --paul

vixie avatar Jan 01 '22 04:01 vixie

What I object to is people who should know better writing things like this:

"the digital world itself is now less safe because of microsoft's design choice here"

You are far too prominent to make public statements of that sort, it would be bad form even if you were right. Do you know how many people's New Years Eve you have interrupted with your intervention here? You are entitled to your opinion but you not entitled to speak for 'security experts' in general.

There is a problem here but it is rather different to the one you raise. The real problem is that the behavior is not sufficiently documented and does not fully reflect the capabilities of the Windows platform. I don't believe in lowest common denominator security. Windows, macOS, iOS and Android all have key managers build into the platform, they work rather differently but cryptographic apps should make use of those features. We should level up, not down.

SSH on Windows probably doesn't need the ssh_agent at all, if the ssh_client is talking to the key store directly, the functionality would probably make more sense in the key generation app.

The documentation is somewhat fuller than last time I looked, but it still needs more detail:

https://docs.microsoft.com/en-us/windows-server/administration/openssh/openssh_keymanagement

The documentation for the Windows version should explain what is going on and precisely which stores the keys are being loaded into. That allows those of us with different cryptographic approaches (threshold/ hardware tokens) to hook in.

Before making changes to the way the Windows version works, I would also look at whatever macOS is doing.

Binding a key to memory is not the ultimate in security. Since SSH supports Ed25519 it could at least in theory make use of a hardware key embedded in the platform that cannot be extracted from it with an application layer threshold overlay.

hallambaker avatar Jan 01 '22 06:01 hallambaker

on that basis, there's room for agreement. microsoft ported the openssh software (which should probably not be called "the linux implementation" since it's not linux-specific and did not originate on linux), and when they did that port, they changed a vital aspect of ticket lifetime (was ephemeral, is now persistent). you seem to want to focus on how this change wasn't documented or communicated well, and i have no argument against that position. i want to focus on how lifetime of authentication information is the worst possible case of violating the principle of least astonishment, and i don't think you're arguing otherwise.

we could go further, and look for other areas of agreement. i for example am sure that keeping one of these tickets alive when i am not aware of it, no matter how it's encrypted in the registry, will end in tears. microsoft's long-official position is that UAC is a hint not a barrier, and the long litany of related vulns and breakins bears that out. it's possible that some corner of that concept space overlaps with your position. happy to discuss it further if you're interested/willing.

i argued hard against the ssh agent model back in the mid 1990's, and several of the flaws of ssh1 were predictable thereby. in kerberos, a ticket has lifetimes (next renewal and final renewal), and key revocation that could invalidate tickets earlier than those renewals. ssh has got none of that, and so the ssh-agent equivalent of a "ticket" is valid anywhere it's recognized, without centralized visibility. if i had got my way on that back then, microsoft would not be opening quite so much of a "pandora's box" with their silent-persistence change in their ssh-agent port to windows.

i'm comfortable with the workaround microsoft has offered, since i know they have a large installed base of not-like-me users of their ssh-agent port, and they can't easily break working configurations there. but i'd like to get a timeline. meanwhile i'm investigating how to get "pageant" to replace microsoft's "ssh-agent" port so that i can fully control the destiny of my authentication information. i think you support that goal even if you don't agree with how i describe some aspects of it.

vixie avatar Jan 01 '22 06:01 vixie

Philip, I am very surprised about your comment.

I share vixies impression. For me personally the proposed fix is good. However most people use the default configuration of windows and with my (admittedly limited knowledge) the default implementation seems less secure and seems to increase the probability of stolen ssh-keys

This issue is not about Linux dictating how Windows should work. It is about an intentional security concept of openssh.

It is also about the fact, that people who use or know openssh are used to / expect a certain behavior of its security model.

Often ports of an open source solution ported to another platform try to stick as much as possible to the original behavior to avoid the element of surprise.

The whole concept of ssh-agent was (and for other platforms still is) that it tries to make it difficult to steal the private keys from a user. (they are stored in the RAM of one special process and no other process knows the key's value, but is able to only use it) and that the live cycle of keys can be controlled independently of the user's session.

I for example have many ssh-keys and only activate the ones, that I need and know, that the next time I power down / up my PC this key is protected again. (so any fix facilitating this for me is already great)

I may be a naive person, but when I first encountered this issue I thought that the current implementation was an attempt to increase the user's comfort and that certain security aspects were overlooked and that after being notified by the community open-ssh would be 'fixed'. What was overlooked is, that not all users might want to wish, that the live cycle of a user's session is identical to the live cycle of all private ssh-keys, that were added to the agent.

The resistance to make open-ssh work (security wise) the same way as it is working on other platforms was a big surprise for me. If there is a way to increase security by storing the keys in a place even safer than one's processes' RAM, then this is of course an improvement worth implementing. The negative surprise is the change in the life cycle of the keys.

I am no security expert, but if under windows one user process cannot inspect the memory of another process of the same user, then the security difference in both implementations is even bigger. One solution allowing any user process to retriever and copy the private keys stored in the registry vs. allowing any user process to use the private key, but not to copy it.

So the fact, that private keys stay persistent and can be read and copied by any user process seems to be (even if one is no security expert) less secure.

If the implementation were called ms-ssh or similar I would still be surprised by the choice of implementation, but I would just replace it with an open-ssh port if I wanted the well known open-ssh behavior.

So the proposed fix will make my PC safer which is already a relief for me.

feenes avatar Jan 01 '22 11:01 feenes