> I mailed this to a friend as a sanity check:
>
> While trying to make a user entry in the /etc/passwd file unrecognized
> so I could demonstrate the use of valid UIDs, I placed a # in front of the UID.
The problem is that when libc was built, NO_SKIP_BAD was not defined. It
appears that NO_SKIP_BAD is *not* the default value, so it's easily
overlooked (unless someone posts to bugtraq!). I don't know what POSIX
says about this, but it's not acceptable behavior for a function that
handles such a delicate situation. I think that NO_SKIP_BAD should
probably be the default.
Here's the code snippet from pwd/pwdread.c of libc-5.3.12 that does the
sanity checking:
info->p.pw_uid = (uid_t) strtol (end + 1, &end, 10);
if (*end != ':')
#ifdef NO_SKIP_BAD
return ( is_nis_entry ? &info->p : NULL );
#else
if (is_nis_entry)
return &info->p;
else
goto restart;
#endif
strtol(3) returns a NULL if it finds a non-decimal character, hence
struct passwd gets a zero in the pw_uid field.
> It seems ideal for a hard to find, back door but given that you must be root
> to write to the passwd file, I have not found a better way to really exploit it.
This is why sysadmins must be extremely careful while editing the
passwd file. Do realize that you still have to give a correct password
in order to get root access this way.
> He also noted that it works the same for GID. We have not taken the time
> to research the problem fully but have tested it on Red Hat 4.1 (2.0.27/2.0.30).
This is not a kernel issue, it's only a libc issue.
----------
Jim Trocki
Computer System and Network Engineer
Transmeta Corporation
Santa Clara, CA
trockij@transmeta.com