xref: /titanic_50/usr/src/cmd/ssh/README.altprivsep (revision adc586debf12d2592024c0b8b9e44ffa104f858c)
1   Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
2   Use is subject to license terms.
3
4	Sun's Alternative "Privilege Separation" for OpenSSH
5
6
7Table of Contents
8
91.    Introduction
102.    What is "Privilege?"
113.    Analysis of the SSH Protocols
123.1.  Privileged Resources, Operations, in the SSH Protocols
134.    OpenSSH's Privilege Separation
145.    SUNWssh's Alternative Privilege Separation
156.    Comparison of the OpenSSH and SUNWssh PrivSep Models
167.    Future Directions
178.    Guide to the AltPrivSep Source Code
18A.    References
19
20
21
22
23
241.  Introduction
25
26    Implementations of SSH servers require some degree of privilege in
27    order to function properly.  Often such implementations retain such
28    privilege throughout normal operation even while users are logged
29    in.  This means that vulnerabilities in the implementation of the
30    protocols can be exploited in such ways as to escalate the privilege
31    that would normally be accorded to mer-mortal users.
32
33    The OpenSSH team introduced support for "privilege separation" in
34    the OpenSSH ssh server some years ago to minimize the extent of
35    extant, undiscovered vulnerabilities in the OpenSSH server source
36    code.  The basic concept is to have a multi-process server
37    implementation where one process, the "monitor" is privileged and
38    implements a smaller protocol than the ssh protocols, and thus is,
39    hopefully, less likely to sport exploitable security bugs.
40
41    The ssh team at Sun agrees with the basic OpenSSH privilege
42    separation concept, but disagrees with its design.
43
44    Here we present our alternative to the OpenSSH design.  We begin
45    with the question of just what is "privilege" and follow on with an
46    analysis of the SSH protocols vis-a-vis privilege.  Then we briefly
47    describe the OpenSSH model, followed by an exposition of our
48    alternative model.
49
50
512.  What is "Privilege?"
52
53    Privilege, in a traditional Unix sense, is that which the "root"
54    user can do that other users cannot directly do.  In Solaris 10
55    there is a new approach to this sort of privilege with the aim of
56    running much of the operating system with the Least Privilege
57    required; root's privilege is broken down into many privileges and
58    these are managed through privilege sets.  We won't go into the
59    details of Solaris 10's Least Privilege facility here.
60
61    But privilege is also access to data and resources that can be used
62    to escalate the privilege of those who have access to them.  For
63    example: secret, or private cryptographic keys used in
64    authentication.  Network security typically requires the use of
65    cryptographic keys for authentication.
66
67
683.  Analysis of the SSH Protocols
69
70    There are two or, rather three SSH protocols:
71
72     - version 1
73     - version 1.5
74     - version 2
75
76    Version 1 and 1.5 are much the same, from our point of view; version
77    2 is significantly different from the other two.
78
79    Familiarity by the reader with the specifications for these
80    protocols is not assumed, but would be beneficial to the reader.
81
82    Quite roughly, these protocols consist of the following:
83
84	a) initial version exchange (for protocol version negotiation)
85	b) a binary encoding of message data
86	c) message syntaxes for the protocols' messages
87	d) specifications on use of cryptography for transport
88	   privacy (encryption) and integrity protection
89	e) a key exchange protocol (which also authenticates servers to
90	   clients)
91	f) a protocol for user authentication
92	g) a session protocol
93	h) a re-keying protocol (v2-only)
94
95    Some of these parts of the ssh protocols are quite complex, some
96    quite straightforward.  Altogether implementation of the ssh
97    protocols requires a source code base of significant size.
98
99    The OpenSSH implementation relies on OpenSSL for cryptographic
100    service, on libz for compression service and miscellaneous other
101    libraries.  Besides these OpenSSH consists of several tens of
102    thousands of lines of source code in C.
103
104    SUNWssh is based on OpenSSH, so it is comparable in size and
105    complexity to OpenSSH.
106
107    There is, then, plenty of space for security bugs in the OpenSSH,
108    and, therefore, also in the SUNWssh source code bases.
109
110    The OpenSSH team designed and implemented a "privilege separation"
111    feature in their ssh server to reduce the risk that a security bug
112    in OpenSSH could be successfully exploited and an attacker's
113    privilege escalated.
114
115
1163.1.  Privileged Resources, Operations, in the SSH Protocols
117
118    What privileges does an SSH server need then?
119
120    Observation with Solaris 10's ppriv(1) and truss(1) commands as well
121    as analysis of the ssh protocols leads to conclude as follows.
122
123    No privilege or privileged resources are needed to implement the
124    parts (a)-(d) mentioned in section 3.
125
126
127    For key exchange and server authentication (e) an ssh server requires:
128
129     - Access to the host's ssh private keys.
130
131     - Access to the host's GSS-API acceptor credentials.  [SSHv2-only]
132
133
134    An ssh server requires practically all privileges for user
135    authentication (f) (at least PAM does), particularly
136    PRIV_PROC_SETID, for logging the user in.
137
138
139    Post-authentication an ssh server requires the following privileges:
140
141     - Those required for auditing a user's subsequent logout.
142
143       That is, PRIV_PROC_AUDIT.
144
145
146     - Those required for record keeping (i.e., utmpx/wtmpx logging).
147
148       That is, either open file descriptor for those files or
149       PRIV_FILE_DAC_WRITE or otherwise access to those files, perhaps
150       through a special user id or group id which would be granted
151       write access through the ACLs on those files.
152
153       Since SSHv2 allows clients to open many channels with
154       pseudo-terminals a server may need to open and close utmpx/wtmpx
155       records multiple times in the lifetime of an SSHv2 connection.
156
157
158     - Those required for accessing the host's ssh private keys for
159       SSHv2 re-keying.  [SSHv2-only]
160
161       These keys can be (and are) loaded at server startup time,
162       requiring PRIV_FILE_DAC_READ, or access through file ACLs, at
163       that time, but not thence.
164
165
166     - Those required for accessing the host's GSS-API acceptor
167       credentials for SSHv2 re-keying.
168
169       These credentials may require a large set of privileges.  The
170       Solaris 10 Kerberos V GSS-API mechanism, for example, requires
171       PRIV_FILE_DAC_READ (for access to the system keytab) and
172       PRIV_FILE_DAC_WRITE (for access to the Kerberos V replay cache).
173
174
175    It is worth pointing out that because of a wrinkle in the
176    specification of the SSHv2 protocol and various implementations,
177    access to a host's ssh private keys can allow one not only to
178    impersonate the host as a server (which is, in practice, difficult),
179    but also to impersonate the host as a client (which is quite easy to
180    do) using "hostbased" user authentication.
181
182    It is entirely possible to have one-process server implementation
183    that drops most privileges and access to privileged resources after
184    user authentication succeeds.  Such an implementation would make
185    some privileges, such as PRIV_PROC_SETID, available to any attacker
186    that successfully exploited a security bug in the ssh server.
187
188    But such an implementation would also have to retain access to
189    resources needed for authenticating the server, which, as described
190    above, can be used to impersonate the server, in some cases with
191    ease.
192
193
1944.  OpenSSH's Privilege Separation
195
196    The OpenSSH privilege separation model is quite complex.
197
198    It consists of a monitor, which retains all privileges and access to
199    privileged resources, and two processes which run with much less
200    privilege: one process running as a special user, "sshd," for
201    hosting all phases of the SSH protocols up to and including
202    authentication, and one process running as the actual user that logs
203    in and which hosts all phases of the SSH protocols post-user-
204    authentication.
205
206    The monitor and its companion processes speak a private protocol
207    over IPC.  This protocol is intended to be smaller and simpler than
208    the SSH wire protocols.
209
210    In practice the OpenSSH monitor protocols relating to user
211    authentication are neither smaller nor simpler than the SSH user
212    authentication protocols; and though they are different they also
213    transport much the same data, including RSA/DSA signatures,
214    usernames, PAM conversations, and GSS-API context and MIC tokens.
215
216    The key exchange protocols have been broken down into their
217    essentials and the monitor serves only services such as signing
218    server replies with private host keys.
219
220    Note also that the OpenSSH monitor protocol uses the same encodings
221    as the SSH protocols and uses the same implementation of those
222    encodings.
223
224
2255.  SUNWssh's Alternative Privilege Separation
226
227    The Sun Microsystems ssh team believes that the OpenSSH team has
228    reached the point of diminishing returns in attempting to separate
229    processing of the user authentication protocols and that the OpenSSH
230    approach to privilege separation of the key exchange protocols has
231    led to a situation in which the monitor acts as an oracle, willing
232    to sign anything provided by the unprivileged processes that talk to
233    it.
234
235    The Sun ssh team proposes a somewhat different privilege separation
236    implementation that shares with the OpenSSH model the goal of
237    minimizing and simplifying the protocol spoken by the monitor, but
238    little source code.
239
240    We eschew any temptation to apply the privilege separation concept
241    to the version negotiation, initial key exchange and user
242    authentication phases of the ssh protocols (but see section 7).
243
244    Instead we focus on separating processing of auditing, record
245    keeping and re-keying from processing of the session protocols.  We
246    also wish to avoid creating any oracles in the monitor.
247
248    This approach allows us to have a very simple monitor protocol.  Our
249    monitor protocol consists of the following operations:
250
251     - record a new pseudo-terminal session
252     - record the end of a pseudo-terminal session
253     - process a re-key protocol messages
254     - get keys negotiated during re-keying to the session process to it
255       can use them
256
257    Logout auditing is done when the session process dies and so does
258    not require a monitor protocol message.
259
260    By processing all re-key protocol messages in the monitor we prevent
261    the creation of oracles in the monitor.  This is so because the
262    monitor signs only material which it has generated and over which an
263    attacker would have little influence (through the attackers offered
264    DH public key, for example).
265
266    Odds and ends:
267
268     - If the monitor receives SIGHUP, SIGTERM or SIGINT it will call
269       fatal_cleanup(), and thence will forcibly shutdown(3SOCKET) the
270       ssh connection socket, causing its child to exit, and audit a
271       logout.
272
273     - The monitor does not attempt to update utmpx/wtmpx independently
274       of its child -- it depends on the child asking it to.
275
276     - The child now is unable to chown() ptys back to root.  That's Ok,
277       other services on Solaris do the same and everything still works
278       because of grantpt(3C).
279
280     - The sshd server process (the one that will become a monitor)
281       forks a child process before the key exchange starts. The reason
282       for it is that if we forked after that we would end up using
283       PKCS#11 sessions initialized in the monitor unless
284       UseOpenSSLEngine was explicitly set to 'no'. Using any existing
285       PKCS#11 sessions or object handles over fork is what the PKCS#11
286       standard explicitly prohibits. To solve that, we would have to
287       rekey before fork and then newly initialize the engine in the
288       child, together with the new crypto contexts initialized with the
289       keys produced by the key re-exchange. And, that wouldn't help in
290       situations where the client does not support rekeying which also
291       includes the whole protocol version 1. The pre-fork solution is
292       simpler and also much faster. So, the key exchange and
293       authentication is fully done in the child server process while
294       the monitor waits aside to read the authentication context that
295       is needed for further operation. The child drops privileges after
296       the authentication finishes.
297
298       With the ssh client, the situation is slightly more complicated.
299       Given the fact that the user can request to go to the background
300       during the connection using the ~& sequence we must be prepared
301       to rekey before forking, to reinitialize the engine in the child
302       after that, and then set the new crypto contexts with the new
303       keys. If the server we are communicating with does not support
304       rekeying we will not use the engine at all. We expect this
305       situation to be extremely rare and will not offer any workaround
306       for that. This also includes the protocol version 1. However,
307       this version is already considered obsolete and should not be used
308       if possible.
309
3106.  Comparison of the OpenSSH and SUNWssh PrivSep Models
311
312    The OpenSSH server involves three processes which we will term
313    "pre-session," "session" and "monitor."
314
315    The OpenSSH pre-session process implements:
316
317     - the ssh version string exchange
318     - the ssh message encoding/decoding
319     - most of the initial key exchange protocols
320     - transport protection
321     - part of the user authentication protocols
322
323    The OpenSSH session process implements:
324
325     - the ssh message encoding/decoding
326     - transport protection
327     - most of the re-keying protocols
328     - the session protocols
329
330    The OpenSSH monitor process implements:
331
332     - the ssh message encoding/decoding
333     - parts of the key exchange and re-key protocols (primarily signing
334       of server replies with host private keys)
335     - most of the user authentication protocols, specifically:
336
337        - evaluation of ~/.ssh/authorized_keys (for pubkey userauth)
338        - evaluation of known hosts files (for hostbased userauth)
339        - evaluation of .shosts/.rhosts files (for hostbased userauth)
340        - verification of signatures w/ public keys (pubkey, hostbased)
341	- PAM API calls, conversation function
342	- GSS-API calls
343
344       Note that any vulnerabilities in the parsing of authorized_keys,
345       known hosts and .shosts/rhosts files are as exploitable in the
346       monitor as in a server w/o privilege separation.
347
348       Similarly for any vulnerabilities in PAM modules and GSS-API
349       mechanisms.
350
351    The SUNWssh server involves two processes which we will term
352    "session" and "monitor."
353
354    The SUNWssh monitor process implements:
355
356     - the ssh version string exchange
357     - the ssh message encoding/decoding
358     - transport protection
359     - all of the key exchange and re-key protocols
360     - all of the user authentication protocols
361
362    The SUNWssh session process implements:
363
364     - the ssh message encoding/decoding
365     - transport protection
366     - the session protocols
367
368    Obviously all of these processes also implement their side of the
369    monitor protocols.
370
371    The OpenSSH 3.5p1 monitor protocol, on Solaris, has approximately 20
372    monitor request and corresponding response messages.
373
374    The SUNWssh monitor protocol has 5 monitor request and response
375    messages; additionally, the monitor processes standard re-key
376    messages (but note: the monitor and the session process IPC is
377    completely unencrypted), which amounts to about 14 more messages
378    altogether.
379
380    Much of the OpenSSH monitor protocol is a variation of the
381    on-the-wire ssh protocols, with some contents re-packaging.  We
382    believe this does not afford the monitor much additional, if any
383    protection from attacks in the key exchange and user authentication
384    protocols.
385
386    The re-packaging that is done in the OpenSSH monitor protocol is
387    risky business.  By separating the act of signing some blob of data
388    from computing that blob of data one can create an oracle; this is
389    exactly what happened in the OpenSSH case.
390
391    As you can see in the next section, the SUNWssh privilege separation
392    could evolve somewhat in the OpenSSH direction by saving the monitor
393    all transport protection work, but we cannot save the monitor much,
394    if any work relating to authentication or key exchange.
395
396
3977.  Future Directions
398
399    The SUNWssh server privilege separation implementation could stand
400    several improvements.
401
402    The first improvement would be to have a single system-wide monitor.
403    This would reduce resource consumption.  The work needed to
404    implement such an enhancement is very similar to the work needed to
405    produce an SSH API and library, and it is not trivial.  If this is
406    not done then at least dropping PRIV_PROC_SETID and instead setting
407    the saved-set-user-id in the monitor to that of the logged in user
408    would be nice.
409
410    The second enhancement would be to add a "none" host key algorithm
411    to SSHv2 and a corresponding option in SUNWssh to disallow re-keying
412    with any other host key algorithm.  This would allow customers to
413    configure their server and monitor so that no re-key protocol
414    messages need be processed by the monitor.
415
416    A third enhancement would be to enhance the GSS-API mechanisms to
417    require fewer privileges.  In practice this means overhauling the
418    Kerberos V mechanism's replay cache.  This would allow the monitor
419    to run with fewer privileges.
420
421    Further, even without improving the Kerberos V mechanism's replay
422    cache it should be possible to drop at least PRIV_PROC_FORK/EXEC/
423    SESSION.
424
425    A fourth enhancement would to have the unprivileged process handle
426    all transport protection and proxy to the monitor all key exchange
427    and user authentication protocol messages.  This is a variation on
428    the OpenSSH model, but without the re-packaging of ssh message
429    contents seen there.  After authentication succeeds the monitor
430    could either change the unprivileged process' credentials (as can be
431    done with ppriv(1) or the unprivileged process would, as in OpenSSH,
432    pass the session keys/IVs/keystate to the monitor which would then
433    pass them to a new process, the session process, that would then run
434    as the logged in user.
435
436
4378.  Guide to the AltPrivSep Source Code
438
439
440    First, a brief introduction to the SUNWssh/OpenSSH source code.
441
442    The source code is organized as follows:
443
444	$SRC/cmd/ssh/etc/
445	    |
446	    +-> config files
447
448	$SRC/cmd/ssh/include/
449	    |
450	    +-> header files (note: none are installed/shipped)
451
452	$SRC/cmd/ssh/libopenbsd-compat/common/
453	    |
454	    +-> misc. portability source code
455
456	$SRC/cmd/ssh/libssh/common/
457	    |
458	    +-> implementation of encoding, transport protection,
459		various wrappers around cryptography, the key exchange
460		and host authentication protocols, the session
461		protocols, and misc. other code
462
463		cipher.c
464		mac.c
465		compress.c
466		packet.c
467		    |
468		    +-> transport protocol
469
470		buffer.c
471		bufaux.c
472		    |
473		    +-> encoding
474
475		channels.c
476		nchan.c
477		    |
478		    +-> session protocol
479
480		kex.c
481		kexdh.c
482		kexgex.c
483		    |
484		    +-> key exchange/re-key code common to ssh and sshd
485
486		kexdhs.c
487		kexgexs.c
488		kexgsss.c
489		    |
490		    +-> key exchange/re-key code (server only)
491
492		kexdhc.c
493		kexgexc.c
494		kexgssc.c
495		    |
496		    +-> key exchange/re-key code (client only)
497
498		dh.c
499		rsa.c
500		mpaux.c
501		ssh-rsa.c
502		ssh-dss.c
503		ssh-gss.c
504		    |
505		    +-> crypto wrappers/utilities
506
507		log.c
508		    |
509		    +-> logging, including debug logging, on stderr or
510			syslog
511
512
513	$SRC/cmd/ssh/ssh/
514	    |
515	    +-> ssh(1)
516
517	$SRC/cmd/ssh/sshd/
518	    |
519	    +-> sshd(1M), including auditing, implementation of user
520		authentication and the OpenSSH and SUNWssh monitors
521
522		sshd.c
523		    |
524		    +-> main()
525
526		auth*.c
527		    |
528		    +-> user authentication
529
530		serverloop.c
531		session.c
532		    |
533		    +-> session protocols
534
535		bsmaudit.[ch]
536		sshlogin.c
537		loginrec.c
538		    |
539		    +-> auditing and record-keeping
540
541	$SRC/cmd/ssh/<misc commands>/
542	    |
543	    +-> scp, sftp, sftp-server, ssh-agent, ssh-add, ...
544
545
546    The SUNWssh altprivsep adds two new source files:
547
548	$SRC/cmd/ssh/include/altprivsep.h
549	$SRC/cmd/ssh/sshd/altprivsep.c
550	    |
551	    +-> monitor start routine, altprivsep_packet_*() routines
552		for communication with the monitor, routines to help
553		with key exchanges, service procedures for the monitor,
554		etc...
555
556    and modifies the following:
557
558	$SRC/cmd/ssh/include/config.h
559	    |
560	    +> adds cpp define "ALTPRIVSEP"
561
562	$SRC/cmd/ssh/include/ssh2.h
563	    |
564	    +-> adds private message type "SSH2_PRIV_MSG_ALTPRIVSEP" (254)
565
566	$SRC/cmd/ssh/include/packet.h
567	    |
568	    +-> adds prototypes for several simple utility functions,
569		some of which are specifically meant to avoid having to
570		link altprivsep.c into ssh(1)
571
572	$SRC/cmd/ssh/libssh/common/kex.c
573	$SRC/cmd/ssh/libssh/common/packet.c
574	    |
575	    +-> implements the hooks needed to proxy re-key messages
576		to/from the monitor
577
578	$SRC/cmd/ssh/sshd/Makefile
579	    |
580	    +-> adds altprivsep.o to list of objects linked into sshd(1M)
581
582	$SRC/cmd/ssh/sshd/serverloop.c
583	    |
584	    +-> adds an event loop for the monitor
585		modifies the usual event loops for SSHv2
586
587	$SRC/cmd/ssh/sshd/session.c
588	    |
589	    +-> modifies do_login() and session_pty_cleanup2() to call
590		altprivsep_record_login/logout() instead of
591		record_login/logout().
592
593		modifies do_exec_pty() so that the server waits for the
594		call to altprivsep_record_login() in child process to
595		complete before returning so that the server and the
596		child processes do not compete for monitor IPC I/O.
597
598	$SRC/cmd/ssh/include/log.h
599	$SRC/cmd/ssh/libssh/common/log.c
600	    |
601	    +-> adds an internal interface, set_log_txt_prefix() so that
602		the monitor's debug and log messages get prefixed with a
603		string ("monitor ") that indicates they are from the
604		monitor
605
606	$SRC/cmd/ssh/sshd/sshd.c
607	    |
608	    +-> modifies the body of code that follows the user
609		authentication phase of the ssh protocols so as to start
610		the monitor and move the relevant code into the monitor
611		or session processes as appropriate while dropping
612		privileges and access to privileged resources in the
613		session process
614
615    The monitor uses the packet.h interfaces to communicate with the
616    session process as though it were its ssh client peer, but always
617    uses the "none" cipher, mac and compression algorithms and installs
618    even handlers only for the relevant key exchange messages and the
619    private monitor message used for the other monitor services.
620
621    The monitor serves the following services:
622
623     - APS_MSG_NEWKEYS_REQ	-> used to obtain keys/IVs after re-keys
624     - APS_MSG_RECORD_LOGIN	-> used to update utmpx/wtmpx
625     - APS_MSG_RECORD_LOGOUT	-> used to update utmpx/wtmpx
626
627    The session and monitor processes communicate over a pipe.
628
629    All monitor IPC I/O from the session process is blocking (though the
630    pipe is set to non-blocking I/O).  The monitor protocol is entirely
631    synchronous and relies on the re-key protocols being entirely
632    synchronous also (which they are, unlike the session protocols).
633
634    The kex.c and packet.c files are minimally modified, primarily to
635    prevent the monitor from handling SSH_MSG_NEWKEYS messages as a
636    normal ssh server should, instead letting the session process
637    process SSH_MSG_NEWKEYS messages by requesting the new keys
638    negotiated with client from the monitor.
639
640    Note that for SSHv1 no on-the-wire messages are processed by the
641    monitor after authentication.  In fact, the monitor thinks it's
642    running SSHv2, even if the on-the-wire protocol is v1.
643
644
645A.  References
646
647    The IETF SECSH Working Group:
648
649	http://www.ietf.org/html.charters/secsh-charter.html
650
651    The SSHv2 architecture, assigned numbers:
652
653	http://www.ietf.org/internet-drafts/draft-ietf-secsh-architecture-16.txt
654	http://www.ietf.org/internet-drafts/draft-ietf-secsh-assignednumbers-06.txt
655
656    New cipher modes for SSHv2:
657
658	http://www.ietf.org/internet-drafts/draft-ietf-secsh-newmodes-02.txt
659
660    The SSHv2 "transport," including initial key exchange and re-key
661    protocols, but excluding negotiable DH group size and GSS-API-based
662    key exchange:
663
664	http://www.ietf.org/internet-drafts/draft-ietf-secsh-transport-18.txt
665
666    Additional key exchange protocols for SSHv2:
667
668	http://www.ietf.org/internet-drafts/draft-ietf-secsh-gsskeyex-08.txt
669	http://www.ietf.org/internet-drafts/draft-ietf-secsh-dh-group-exchange-04.txt
670
671    Base user authentication spec for SSHv2 (includes none, password,
672    pubkey and hostbased user authentication):
673
674	http://www.ietf.org/internet-drafts/draft-ietf-secsh-userauth-21.txt
675
676    SSHv2 user authentication using PAM-style prompting:
677
678	http://www.ietf.org/internet-drafts/draft-ietf-secsh-auth-kbdinteract-06.txt
679
680    SSHv2 user authentication using the GSS-API:
681
682	http://www.ietf.org/internet-drafts/draft-ietf-secsh-gsskeyex-08.txt
683
684    SSHv2 "session" protocol (i.e., the protocol used for pty sessions,
685    port forwarding, agent forwarding, X display forwarding, etc...):
686
687	http://www.ietf.org/internet-drafts/draft-ietf-secsh-connect-19.txt
688