From ylo@ssh.fi  Tue Aug 13 09:17:13 1996
Received: from muuri.ssh.fi (ssh.fi [194.100.44.97]) by suburbia.net (8.7.4/Proff-950810) with ESMTP id JAA03253 for <best-of-security@suburbia.net>; Tue, 13 Aug 1996 09:17:01 +1000
Received: from pilari.ssh.fi (pilari.ssh.fi [192.168.2.1]) by muuri.ssh.fi (8.7.5/8.7.3) with ESMTP id CAA24039; Tue, 13 Aug 1996 02:16:33 +0300 (EET DST)
Received: (from ylo@localhost) by pilari.ssh.fi (8.7.5/8.7.3) id CAA27742; Tue, 13 Aug 1996 02:16:33 +0300 (EET DST)
Date: Tue, 13 Aug 1996 02:16:33 +0300 (EET DST)
Message-Id: <199608122316.CAA27742@pilari.ssh.fi>
From: Tatu Ylonen <ylo@ssh.fi>
To: ssh@clinet.fi, best-of-security@suburbia.net, ssh-announce@clinet.fi
CC: f-secure-ssh-support@datafellows.com, ttsalo@ssh.fi
Subject: fix for ssh security problem (users with writable home directories)
Organization: SSH Communications Security, Finland

-----BEGIN PGP SIGNED MESSAGE-----

Matt Power <mhpower@mit.edu> reported a few days ago a security
problem with SSH when you have users that have writable home
directories.  Basically, if a user has a writable home directory, any
local user can create an authorized_keys file in that directory, and
log in as that user.  It turns out that some operating systems (at
least Debian Linux and SunOS) come with such directories in the
standard distribution (for users nobody and uucp).

The patch below adds a check for the modes and ownership for RSA
authentication.  It checks
  - user's home directory
  - user's $HOME/.ssh directory
  - user's $HOME/.ssh/authorized_keys file

This closes the above security problem.  The patch will be included in
future releases.

    Tatu
- -- 
F-Secure SSH Development <f-secure-ssh-support@datafellows.com>
http://www.datafellows.com/, http://www.ssh.fi/


(Note, since this message is PGP-signed, you'll need to remove the
extra '- ' from the beginning of some lines below.)


*** ../ssh-1.2.14.orig/ssh.h	Thu Jun  6 16:47:01 1996
- --- ssh.h	Mon Aug 12 18:47:26 1996
***************
*** 341,347 ****
  /* Performs the RSA authentication dialog with the client.  This returns
     0 if the client could not be authenticated, and 1 if authentication was
     successful.  This may exit if there is a serious protocol violation. */
! int auth_rsa(struct passwd *pw, MP_INT *client_n, RandomState *state);
  
  /* Parses an RSA key (number of bits, e, n) from a string.  Moves the pointer
     over the key.  Skips any whitespace at the beginning and at end. */
- --- 341,348 ----
  /* Performs the RSA authentication dialog with the client.  This returns
     0 if the client could not be authenticated, and 1 if authentication was
     successful.  This may exit if there is a serious protocol violation. */
! int auth_rsa(struct passwd *pw, MP_INT *client_n, RandomState *state,
! 	     int strict_modes);
  
  /* Parses an RSA key (number of bits, e, n) from a string.  Moves the pointer
     over the key.  Skips any whitespace at the beginning and at end. */
*** ../ssh-1.2.14.orig/sshd.c	Thu Jun  6 16:47:07 1996
- --- sshd.c	Mon Aug 12 18:51:28 1996
***************
*** 1423,1429 ****
  	    MP_INT n;
  	    mpz_init(&n);
  	    packet_get_mp_int(&n);
! 	    if (auth_rsa(pw, &n, &sensitive_data.random_state))
  	      { 
  		/* Successful authentication. */
  		mpz_clear(&n);
- --- 1440,1447 ----
  	    MP_INT n;
  	    mpz_init(&n);
  	    packet_get_mp_int(&n);
! 	    if (auth_rsa(pw, &n, &sensitive_data.random_state,
! 			 options.strict_modes))
  	      { 
  		/* Successful authentication. */
  		mpz_clear(&n);
*** ../ssh-1.2.14.orig/userfile.c	Thu Jun  6 16:47:06 1996
- --- userfile.c	Mon Aug 12 18:23:56 1996
***************
*** 1019,1021 ****
- --- 1019,1034 ----
        return -1;
      }
  }
+ 
+ int userfile_check_owner_permissions(struct passwd *pw, const char *path)
+ {
+   struct stat st;
+   if (userfile_stat(pw->pw_uid, path, &st) < 0)
+     return 0;
+ 
+   if ((st.st_uid != 0 && st.st_uid != pw->pw_uid) ||
+       (st.st_mode & 022) != 0)
+     return 0;
+   else
+     return 1;
+ }
*** ../ssh-1.2.14.orig/userfile.h	Thu Jun  6 16:47:01 1996
- --- userfile.h	Mon Aug 12 18:24:02 1996
***************
*** 102,105 ****
- --- 102,110 ----
  /* Performs pclose() on the given uid.  Returns <0 if an error occurs. */
  int userfile_pclose(UserFile uf);
  
+ /* Check owner and permissions of a given file/directory.
+    Permissions ----w--w- must not exist and owner must be either
+    pw->pw_uid or root. Return value: 0 = not ok, 1 = ok */
+ int userfile_check_owner_permissions(struct passwd *pw, const char *path);
+ 
  #endif /* USERFILE_H */
*** ../ssh-1.2.14.orig/auth-rsa.c	Thu Jun  6 16:47:06 1996
- --- auth-rsa.c	Mon Aug 12 18:52:29 1996
***************
*** 143,149 ****
     0 if the client could not be authenticated, and 1 if authentication was
     successful.  This may exit if there is a serious protocol violation. */
  
! int auth_rsa(struct passwd *pw, MP_INT *client_n, RandomState *state)
  {
    char line[8192];
    int authenticated;
- --- 143,150 ----
     0 if the client could not be authenticated, and 1 if authentication was
     successful.  This may exit if there is a serious protocol violation. */
  
! int auth_rsa(struct passwd *pw, MP_INT *client_n, RandomState *state,
! 	     int strict_modes)
  {
    char line[8192];
    int authenticated;
***************
*** 153,161 ****
    unsigned long linenum = 0;
    struct stat st;
  
!   /* Open the file containing the authorized keys. */
!   sprintf(line, "%.500s/%.100s", pw->pw_dir, SSH_USER_PERMITTED_KEYS);
    
    if (userfile_stat(pw->pw_uid, line, &st) < 0)
      return 0;
  
- --- 154,191 ----
    unsigned long linenum = 0;
    struct stat st;
  
!   /* Check permissions & owner of user's home directory */
!   if (strict_modes && !userfile_check_owner_permissions(pw, pw->pw_dir))
!     {
!       log("Rsa authentication refused for %.100s: bad modes for %.200s",
! 	  pw->pw_name, pw->pw_dir);
!       packet_send_debug("Bad file modes for %.200s", pw->pw_dir);
!       return 0;
!     }
! 
!   /* Check permissions & owner of user's .ssh directory */
!   sprintf(line, "%.500s/%.100s", pw->pw_dir, SSH_USER_DIR);
! 
!   if (strict_modes && !userfile_check_owner_permissions(pw, line))
!     {
!       log("Rsa authentication refused for %.100s: bad modes for %.200s",
! 	  pw->pw_name, line);
!       packet_send_debug("Bad file modes for %.200s", line);
!       return 0;
!     }
    
+   /* Check permissions & owner of user's authorized keys file */
+   sprintf(line, "%.500s/%.100s", pw->pw_dir, SSH_USER_PERMITTED_KEYS);
+ 
+   if (strict_modes && !userfile_check_owner_permissions(pw, line))
+     {
+       log("Rsa authentication refused for %.100s: bad modes for %.200s",
+ 	  pw->pw_name, line);
+       packet_send_debug("Bad file modes for %.200s", line);
+       return 0;
+     }
+ 
+   /* Open the file containing the authorized keys. */
    if (userfile_stat(pw->pw_uid, line, &st) < 0)
      return 0;

-----BEGIN PGP SIGNATURE-----
Version: 2.6.3i
Charset: latin1
Comment: Processed by Mailcrypt 3.4, an Emacs/PGP interface

iQCVAwUBMg+6zakZxfGWH0o1AQHiMwP/TF+6dlo3pGWHBb8ogeKQEchjPZed6c1t
c5/ME035p9VTJbScaiIc83ibUT86keoKrsJ/mdrFb7VM9d+iyFL7EK/bgf2FpkwH
BagXolGhDNk77InIkPOuKL/C5Lo/Yi3l1KUnE58eoFrZJeK6X+7Y1rVCoZUFeJEA
ZQ3KGz8goSM=
=zfbk
-----END PGP SIGNATURE-----

