COMMAND

    ssh

SYSTEMS AFFECTED

    ssh-1.2.30

PROBLEM

    Matt Power found following.  If you use the ssh-1.2.30 ssh  client
    on Solaris  8, a  password typed  for password  authentication can
    often be partially recovered  from the client process  memory long
    afterwards, using  pcat (from  the TCT  distribution).   As far as
    known, the  problem is  that ssh  reads the  password using fgets,
    and the program happens to not subsequently overwrite the relevant
    memory locations used  by that stdio  buffer.  (It  overwrites the
    main password buffer, but not the stdio buffer.)

    Here are the results so far:  on Solaris 8, if this password  data
    is recoverable at all, the pcat output file will apparently always
    have at least  the first four  characters of the  password.  (It's
    easy to determine which  four characters come from  the password).
    Knowing  four  characters  will  sometimes  help a lot with manual
    guessing  of  the  full   password,  and  provide  a   significant
    "workfactor  reduction"  if  you're  able  to launch an exhaustive
    search attack.

    On Red  Hat Linux  6.2 i386,  in many  tries Matt  never seen  any
    obvious part of a login password in the ssh process memory.   This
    does not,  however, mean  that Linux  keeps you  safe from someone
    who  gains  root  access  and  wants  to  find  out  what login or
    encryption passwords  you typed  in the  past.   They can  instead
    sometimes  recover  passwords  from   the  portions  of   /dev/mem
    corresponding to  kernel tty->read_buf's  long after  the password
    was typed  (there might  be a  similar level  of tty-buffer  risks
    with the kernel on Solaris or other systems).

SOLUTION

    Here's a workaround that appears to address the issue for  Solaris
    8:

    *** ssh-1.2.30/readpass.c.old	Wed Jul  5 11:26:50 2000
    --- ssh-1.2.30/readpass.c	Thu Aug  3 15:46:11 2000
    ***************
    *** 94,96 ****
      {
    !   char buf[1024], *cp;
        unsigned char quoted_prompt[512];
    --- 94,96 ----
      {
    !   char buf[1024], *cp, *fs;
        unsigned char quoted_prompt[512];
    ***************
    *** 223,225 ****
        /* Read the passphrase from the terminal. */
    !   if (fgets(buf, sizeof(buf), f) == NULL)
          {
    --- 223,228 ----
        /* Read the passphrase from the terminal. */
    !   buf[0] = '\0';
    !   fs = fgets(buf, sizeof(buf), f);
    !   memset(f->_base, 0, strlen(buf));
    !   if (fs == NULL)
          {

    Note that this is  not portable.  If  you wanted to use  a similar
    approach on other systems, you might need to use  f->_IO_read_base
    rather than f->_base.  Also, you could instead modify the code  so
    that  read(2)  is   used  for  password   input,  avoiding   stdio
    completely.

    For the record, OpenSSH does  not have this problem since  it does
    not use stdio for  reading such data.   Instead it uses a  routine
    which calls read() per-character, so that proper semantics  result
    from hitting ^C and EOF on the  wire.  The code we use is  similar
    to that found in getpass(3).