Bugtraq mailing list archives

recovering ssh passwords from memory


From: Matt Power <mhpower () MIT EDU>
Date: Thu, 3 Aug 2000 18:04:54 -0400

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 I know, 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'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.

Here are the results I have 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, so I
don't think I need to outline that here.) 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. I don't have a general model of process
memory use/reuse that explains why only four characters are present.

On Red Hat Linux 6.2 i386, in many tries I've 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; I
haven't checked). To prevent this, you can modify the kernel -- I
happen to put a "memset(tty->read_buf, 0, N_TTY_BUF_SIZE);" before the
"return retval;" line in the function read_chan in
linux/drivers/char/n_tty.c, along with some heuristic conditional
logic for when that memset statement will be executed. Also, nothing
is present in a tty->read_buf for passwords entered using a non-tty X
application such as ssh-askpass, and in many tries I've not been able
to recover ssh-askpass passwords from /dev/mem after the ssh-askpass
process exits. You can use ssh-askpass for non-ssh tasks, e.g.,
"ssh-askpass | gpg --passphrase-fd 0 -aest -r mhpower () mit edu file"
(this is not a good idea if your X setup provides any possible way for
an unauthorized person to grab your keystrokes).

Matt Power
mhpower () mit edu


Current thread: