Alexander Wuerstlein
2016-Jan-14 19:12 UTC
Proposal: always handle keys in separate process
Hello, in light of the recent CVE-2016-0777, I came up with the following idea, that would have lessened its impact. Feel free to ignore or flame me, maybe its stupid or I missed something :) - private key material should only ever be handled in a separate process from the SSH client. ssh-agent (maybe slightly extended) seems the logical choice. - in places where the client currently reads ssh-keys (load_public_identity_files), automatically spawn an ssh-agent instead if none is available. Connection to the agent might be via the usual SSH_AUTH_SOCK or via an inherited pipe() or socketpair() if newly spawned. Those anonymous filedescriptors would mean that this ssh-agent is 'private' to this one client. Where I'm not quite sure how to handle things would be: - If a ssh-agent is already running, but the client needs to read more keys: Spawn and handle a second, private agent? Use ssh-add? The former would be preferable but more complicated because two different agents would have to be handled. The latter would have the unwanted side-effect of exposing keys via the ssh-agent that maybe shouldn't be. - If a key is password-protected, the client would have to read the password and pass it on to ssh-agent. Could this be done in a better way, maybe without exposing the password to the ssh-client? This would mean that: - ssh client could be stripped of any code that reads ssh-keys directly. - or using the mechanism above could be made an option SpawnPrivateAgent (possibly defaulting to 'yes') - maybe, if that works, one could do a similar thing for sshd and its hostkeys. Ciao, Alexander Wuerstlein.
> Von: openssh-unix-dev [mailto:openssh-unix-dev- > > Hello, > > in light of the recent CVE-2016-0777, I came up with the following idea, > that would have lessened its impact. Feel free to ignore or flame me, > maybe its stupid or I missed something :) > > - private key material should only ever be handled in a separate process > from the SSH client. ssh-agent (maybe slightly extended) seems the > logical choice. > - in places where the client currently reads ssh-keys > (load_public_identity_files), automatically spawn an ssh-agent instead > if none is available. Connection to the agent might be via the usual > SSH_AUTH_SOCK or via an inherited pipe() or socketpair() if newly > spawned. Those anonymous filedescriptors would mean that this > ssh-agent is 'private' to this one client.I would avoid direct spawn or even connect via socket(see proposal at bottom). That way the network/terminal interacting process could be built not only without having access to private key material, but also having no access to most operating system resources (including open/connect/...) even when remote code execution was successful.> Where I'm not quite sure how to handle things would be: > - If a ssh-agent is already running, but the client needs to read more > keys: Spawn and handle a second, private agent? Use ssh-add? The > former would be preferable but more complicated because two different > agents would have to be handled. The latter would have the unwanted > side-effect of exposing keys via the ssh-agent that maybe shouldn't > be. > - If a key is password-protected, the client would have to read the > password and pass it on to ssh-agent. Could this be done in a better > way, maybe without exposing the password to the ssh-client?See below: As the management process would need the password, it could suspend the network/terminal process, read the password and then response to the key signing request. This would not per se block the current password stealing attacks on ssh client, where malicious remote side just pretends after successful login, that passphrase for key was wrong and requests the use to re-enter the phrase again. But it could make it easier to circumvent this condition, e.g. when management process puts a preamble before asking the password, one that an attacker has hard time to guess (e.g. Are you [user somebode], logged in since [time] on [machine] really sure, that you want to connect to service [local name of remote service], trust its key requests for [local key name] and allow sign requests, then enter your password ...)> This would mean that: > - ssh client could be stripped of any code that reads ssh-keys directly. > - or using the mechanism above could be made an option SpawnPrivateAgent > (possibly defaulting to 'yes') > - maybe, if that works, one could do a similar thing for sshd and its > hostkeys.What do you think of a following procedure? * On startup, at first management process is created. This process is somehow privileged, as it still can execute all operating system calls without special restrictions. This management process may connect to an agent or launch agent process by itself (if needed) to have access to key material. * From the management process, have network/terminal process forked, reexec itself (thus get rid of any virtual memory information shared with management process, e.g. address space layout, strings already loaded - e.g. host name, user name, config parameters, ... thus eradicating any information present in the management process) * Let management process seccomp secure the network/terminal process to allow only file descriptor read/write operations, ..., that what is really needed but no other syscalls (especially no open/exec,.../xxxxat style of calls). Thus the terminal process efficiently loses all capabilities to access key material by himself, which is enforced by the OS (this will work only on platforms, that support it, others will have to leave out this step). * Use the socket from the network/terminal process to the management process only to query (search for) keys, request signing of material. * Let the management process suspend the terminal process and ask for key passphrases when needed. * Let the management process immediately suspend the network/terminal process if rate of key search/sign requests exceeds limit or (if mathematically easily detectable) signing of problematic data is requested to extract e.g. DSA keys (do not know, which other key types have similar weaknesses). This would also protect the local keys when an agent forwarding was enabled (do not know, if such protection might already be in place) and remote side starts to create signatures en masse. * Let the management process search keys/sign directly or ask the agent - minor design decision? Kind Regards, Roman -------------- next part -------------- A non-text attachment was scrubbed... Name: smime.p7s Type: application/pkcs7-signature Size: 6344 bytes Desc: not available URL: <http://lists.mindrot.org/pipermail/openssh-unix-dev/attachments/20160115/39f976e0/attachment-0001.bin>
Loganaden Velvindron
2016-Jan-15 09:30 UTC
Proposal: always handle keys in separate process
On Thu, Jan 14, 2016 at 7:12 PM, Alexander Wuerstlein <arw at cs.fau.de> wrote:> Hello, > > in light of the recent CVE-2016-0777, I came up with the following idea, > that would have lessened its impact. Feel free to ignore or flame me, > maybe its stupid or I missed something :) >Feel free to come up with a patch. In OpenSSH, it's a good idea to follow-up with a patch :)
How about using the existing OpenSSH client's PKCS#11 support to isolate keying material in a dedicated process? A similar approach, "Practical key privilege separation using Caml Crush", was discussed at FOSDEM'15 with a focus on Heatbleed [1][2] but the ideas and principles are the same. Now this is easily done using the following available components: - SoftHSM to store the crypto keys - Caml-Crush server components load the SoftHSM middleware (access the keys) in a dedicated process - SSH client loads Caml-Crush PKCS#11 middleware that connects to its daemon and allows to sign SSH exchange to authenticate No patch needed. Hope this helps, Thomas [1] https://archive.fosdem.org/2015/schedule/event/caml_crush/ [2] https://github.com/ANSSI-FR/caml-crush On Fri, Jan 15, 2016 at 9:30 AM, Loganaden Velvindron <loganaden at gmail.com> wrote:> On Thu, Jan 14, 2016 at 7:12 PM, Alexander Wuerstlein <arw at cs.fau.de> wrote: >> Hello, >> >> in light of the recent CVE-2016-0777, I came up with the following idea, >> that would have lessened its impact. Feel free to ignore or flame me, >> maybe its stupid or I missed something :) >> > > Feel free to come up with a patch. In OpenSSH, it's a good idea to > follow-up with a patch :) > _______________________________________________ > openssh-unix-dev mailing list > openssh-unix-dev at mindrot.org > https://lists.mindrot.org/mailman/listinfo/openssh-unix-dev
Alexander Wuerstlein
2016-Jan-15 11:49 UTC
Proposal: always handle keys in separate process
On 2016-01-15T09:53, Fiedler Roman <Roman.Fiedler at ait.ac.at> wrote:> > Von: openssh-unix-dev [mailto:openssh-unix-dev- > > > > Hello, > > > > in light of the recent CVE-2016-0777, I came up with the following idea, > > that would have lessened its impact. Feel free to ignore or flame me, > > maybe its stupid or I missed something :) > > What do you think of a following procedure? > > * On startup, at first management process is created. This process is > somehow privileged, as it still can execute all operating system calls > without special restrictions. This management process may connect to an > agent or launch agent process by itself (if needed) to have access to key > material. > > * From the management process, have network/terminal process forked, reexec > itself (thus get rid of any virtual memory information shared with > management process, e.g. address space layout, strings already loaded - e.g. > host name, user name, config parameters, ... thus eradicating any > information present in the management process)So, effectively you propose to also split up the ssh client into three processes. While it sounds like a good idea in general, I think one should try the easier split-up into two first. For why I think it is far easier to first separate out the ssh-agent/key-handling, see below.> * Let management process seccomp secure the network/terminal process to > allow only file descriptor read/write operations, ..., that what is really > needed but no other syscalls (especially no open/exec,.../xxxxat style of > calls). Thus the terminal process efficiently loses all capabilities to > access key material by himself, which is enforced by the OS (this will work > only on platforms, that support it, others will have to leave out this > step). > > * Use the socket from the network/terminal process to the management process > only to query (search for) keys, request signing of material.Those separations and restrictions are the really hairy part here: Pulling out the key handling is small compared to the amount of functionality that is e.g. X11-forwarding, agent-forwarding or (potentially dynamic) proxy/socket-forwarding which would need to be handled when splitting the management from the connection/terminal part. Another potential problem is the portability problem which seccomp poses, there is unfortunately no POSIX syscall filtering or sandboxing API. That makes things even more complicated.> * Let the management process suspend the terminal process and ask for key > passphrases when needed. > > * Let the management process immediately suspend the network/terminal > process if rate of key search/sign requests exceeds limit or (if > mathematically easily detectable) signing of problematic data is requested > to extract e.g. DSA keys (do not know, which other key types have similar > weaknesses). This would also protect the local keys when an agent forwarding > was enabled (do not know, if such protection might already be in place) and > remote side starts to create signatures en masse. > > * Let the management process search keys/sign directly or ask the agent - > minor design decision?That should all be possible imho. Ciao, Alexander Wuerstlein.