Date: Thu, 24 Dec 1998 18:02:03 +0300 From: Savochkin Andrey Vladimirovich <saw@MSU.RU> Subject: Re: Linux PAM (up to 0.64-2) local root compromise To: BUGTRAQ@NETSPACE.ORG --UlVJffcvxoiEqYs2 Content-Type: text/plain; charset=us-ascii On Wed, Dec 23, 1998 at 01:12:45PM +0100, Michal Zalewski wrote: > As someone said, "Never make any mistaeks." > > Latest release of Linux Pluggable Authentication Modules (pam-0.64-2, as > well as previous ones), has huge security flaw in pam_unix_passwd.so > module, which can be exploited to gain read/write permissions to > /etc/shadow file. > [snip] > Default password change routine in pam_unix_passwd.so module, called > from passwd utility, creates temporary file /etc/nshadow using fopen(). > Unfortunately, process umask isn't changed. After approx. 3 syscalls, > chmod is called to set proper mode on this file (0600). But, for these > 3 syscalls, file permissions are equal to 0666 ~ umask. If umask of > current process (which is inherited from parent process, of course) > is set to 0, we have /etc/nshadow file with permissions 0666. Then, > after all, it's moved using rename() to /etc/shadow. Cute. Thank you for the report. The attached patch takes care of file creation permissions in pam_unix_passwd and pam_tally modules. I should warn people that the patch isn't well tested. pam_unix_passwd module can't be tested on my system. It doesn't work at all because of a glibc bug. Best regards Andrey V. Savochkin --UlVJffcvxoiEqYs2 Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="pam-0.65-umask.patch" diff -ru Linux-PAM-0.65.orig/modules/pam_tally/pam_tally.c Linux-PAM-0.65/modules/pam_tally/pam_tally.c --- Linux-PAM-0.65.orig/modules/pam_tally/pam_tally.c Thu Jan 15 01:08:33 1998 +++ Linux-PAM-0.65/modules/pam_tally/pam_tally.c Thu Dec 24 17:12:21 1998 @@ -137,13 +137,16 @@ int lstat_ret = lstat(filename,&fileinfo); if ( lstat_ret && *tally!=TALLY_HI ) { - if ( ( *TALLY=fopen(filename, "a") ) ) { - /* Create file, or append-open in pathological case. */ + int oldmask = umask(077); + *TALLY=fopen(filename, "a"); + /* Create file, or append-open in pathological case. */ + umask(oldmask); + if ( !*TALLY ) { _pam_log(LOG_ALERT, "Couldn't create %s",filename); return PAM_AUTH_ERR; } + lstat_ret = fstat(fileno(*TALLY),&fileinfo); fclose(*TALLY); - lstat_ret = lstat(filename,&fileinfo); } if ( lstat_ret ) { @@ -563,6 +566,8 @@ *argv); exit(0); } + + umask(077); /* * Major difference between individual user and all users: diff -ru Linux-PAM-0.65.orig/modules/pam_unix/pam_unix_passwd.c Linux-PAM-0.65/modules/pam_unix/pam_unix_passwd.c --- Linux-PAM-0.65.orig/modules/pam_unix/pam_unix_passwd.c Thu Oct 9 06:59:04 1997 +++ Linux-PAM-0.65/modules/pam_unix/pam_unix_passwd.c Thu Dec 24 16:53:30 1998 @@ -554,6 +554,7 @@ int err = 0; #ifdef HAVE_SHADOW_H struct spwd *spwdent=NULL, *stmpent=NULL; + int oldmask; #endif if(flags & PPW_SHADOW) { retval |= PPW_SHADOW; } gettimeofday(&time1, NULL); @@ -583,7 +584,9 @@ return PPW_NOSUCHUSER; spwdent->sp_pwdp = towhat; spwdent->sp_lstchg = time(NULL)/(60*60*24); + oldmask = umask(077); pwfile = fopen(SH_TMPFILE,"w"); + umask(oldmask); opwfile = fopen("/etc/shadow","r"); if(pwfile == NULL || opwfile == NULL) return PPW_ERROR; @@ -623,7 +626,9 @@ unlink(SH_TMPFILE); } else { pwd->pw_passwd = towhat; + oldmask = umask(077); pwfile = fopen(PW_TMPFILE,"w"); + umask(oldmask); opwfile = fopen("/etc/passwd","r"); if(pwfile == NULL || opwfile == NULL) return PPW_ERROR; @@ -659,7 +664,9 @@ } #else pwd->pw_passwd = towhat; + oldmask = umask(077); pwfile = fopen(PW_TMPFILE,"w"); + umask(oldmask); opwfile = fopen("/etc/passwd","r"); if(pwfile == NULL || opwfile == NULL) return PPW_ERROR; --UlVJffcvxoiEqYs2--