[LWN Logo]
[Timeline]
Date:         Sat, 1 Jul 2000 01:11:09 -0400
From: "Richard E. Silverman" <slade@SHORE.NET>
Subject:      Kerberos security vulnerability in SSH-1.2.27
To: BUGTRAQ@SECURITYFOCUS.COM

I am writing to report a security bug in SSH 1.2.27.

SOFTWARE AFFECTED:

  SSH 1.2.27 with Kerberos authentication support compiled in (i.e. "configure
  --with-kerberos5").  I have contacted SSH Communicators Security
  (http://www.ssh.com) about this, and they have just released ssh-1.2.28,
  which fixes this problem.

OPERATING SYSTEMS:

  all those supported by the SSH release (many flavors of Unix)

SYNOPSIS:

When logging in a user, sshd sets the user's KRB5CCNAME environment variable
to the value "none".  If the user subsequently makes use of Kerberos in that
login session (e.g. does a kinit), Kerberos tickets will be stored in a file
named "none" in the current directory.  This is inappropriate and presents
significant risk of disclosure of the user's Kerberos tickets, via insecure
file-sharing protocols such as NFS or SMB, or other methods.

It is important to note that this bug occurs regardless of whether Kerberos
authentication is actually being used for the current session; merely
compiling in Kerberos support is sufficient to cause the problem.

DETAILS:

Kerberos tickets are sensitive information, and stealing them may allow an
attacker to impersonate the legitimate user for the lifetime of the ticket.
The ticket cache is normally kept on the local host in a directory set aside
for such usage, e.g. /tmp.  Placing the Kerberos ticket cache in the current
directory is a serious problem.  For example:

* Upon login, the current directory the user's home directory, often an
  NFS-mounted filesystem.  This means that tickets may be sent in the clear
  over the network via NFS.

* Since the pathname ("none") is relative, tickets may be placed in
  unpredictable locations, depending on the user's actions.  Even though
  Kerberos sets the protections of the ticket cache file restrictively, in
  this situation they might be placed, say, in a directory with an inherited
  ACL which gives read access to someone else, or on a removable medium.

The problem is especially bad because the user may never notice it.  As long
as he or she stays in the same directory with the cache file, Kerberos will
operate normally.  Only careful reading of the output of klist, for example,
will reveal the change.

QUICK FIX:

Change this:

  [sshd.c:4296]
  if (ticket)
    child_set_env(&env, &envsize, "KRB5CCNAME", ticket);

to this:

  if (ticket && strcmp("none",ticket))
    child_set_env(&env, &envsize, "KRB5CCNAME", ticket);

FIX EXPLANATION:

This bug arises from confusion in the source code about the value of this
variable:

  [sshd.c:547]
  char *ticket = "none\0";

This variable holds file pathname to be used on the remote side for the ticket
cache, if a forwarded Kerberos TGT has been obtained.  There appears to be
some inconsistency about how to interpret the value of this variable.  In some
places, the SSH source compares *ticket to the string "none" to determine
whether a forwarded ticket is available; e.g.:

  [sshd.c:2691]
  #ifdef KERBEROS
        /* If you forwarded a ticket you get one shot for proper
           authentication. */
        /* If tgt was passed unlink file */
        if (ticket){
            if (strcmp(ticket,"none"))
              /* ticket -> FILE:path */
              unlink(ticket + 5);
            else
              ticket = NULL;
        }
  #endif /* KERBEROS */

But, setting and testing the pointer against the NULL value is also used.  In
particular, here:

  [sshd.c:4296]
  if (ticket)
    child_set_env(&env, &envsize, "KRB5CCNAME", ticket);

It is possible for this line to be reached with the ticket variable still
pointing to the string "none", which causes the problem.

- Richard Silverman
  slade@shore.net