COMMAND
getpwnam()
SYSTEMS AFFECTED
Slackware 3.0 Linux with libc 5.3.12, 5.0.9 and libc-4.6.27
PROBLEM
This is a *very* serious hole that affects Linux-based NIS client
systems. For those that don't want to (or can't) patch and
recompile their own fixed version of libc, it is recommended the
*immediate* removal of all "stub" NIS username entries, of the
forms described in the attached message, from /etc/passwd. Credit
for this goes to Arno Schaefer.
Arno discovered a major security hole in the getpwnam() function
in the current libc (5.3.12, probably present in all previous
versions). It can be exploited if there is an entry in the form:
+username::::::
or
-username::::::
or similar in /etc/passwd (an entry to admit or exclude a single
user from the NIS passwd file).
By typing 'su +username' or 'su -- -username' resp. you become
root without being asked for a passwd.
'login' is not vulnerable, so only users with shell access to the
machine can exploit the bug.
Arno tried it on two different systems that used NIS, both running
Slackware 3.0, libc 5.3.12 and 5.0.9, resp. It can only be used if
an entry of the form described above is present, so many systems
that do not use NIS or that have only a standard '+' entry are
safe against this attack.
This apparently has been know for a long time, since the source
for 'login' reads:
/* Dirty patch to fix a gigantic security hole when using
yellow pages. This problem should be solved by the libraries,
and not by programs, but this must be fixed urgently! If the
first char of the username is '+', we avoid login success.
Feb 95 <alvaro@etsit.upm.es> */
if (username[0] == '+') {
puts("Illegal username");
badlogin(username);
sleepexit(1);
}
but probably due to bad communication it was not fixed in libc. A
similar bug in the same function was fixed over a year ago ('su +'
or 'su +@netgroup'), but strangely nobody thought about 'su
+username'.
SOLUTION
Arno gave a patch that fixes the hole - it was taken against libc
5.3.12, but should be easily adaptable to other versions.
Index: getpwnam.c
===================================================================
RCS file: /home/work/cvs/linux/libc/pwd/getpwnam.c,v
retrieving revision 1.5
diff -c -r1.5 getpwnam.c
*** getpwnam.c 1996/05/22 15:49:37 1.5
- - - --- getpwnam.c 1996/05/23 06:59:32
***************
*** 53,58 ****
- - - --- 53,63 ----
register FILE *stream;
register struct passwd *p;
+ #ifdef YP
+ if (name[0] == '-' || name[0] == '+')
+ return NULL;
+ #endif
+
if (info == NULL)
{
info = __pwdalloc();
- - - --------------63DB9C7E36AD404B638D1437--
- - ------- end -------
You should check for newer versions of libc anyway.