[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#698102: eglibc: initgroups changes egid



Package: eglibc
Version: 2.13-37
Severity: critical
Tags: security
Justification: root security hole

Dear Maintainer,

I have found a potential security hole in the implementation of initgroups. It
sets a wrong egid on my system. Here is the necessary information:

root@client-debian:~# getent passwd
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/bin/sh
bin:x:2:2:bin:/bin:/bin/sh
sys:x:3:3:sys:/dev:/bin/sh
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/bin/sh
man:x:6:12:man:/var/cache/man:/bin/sh
lp:x:7:7:lp:/var/spool/lpd:/bin/sh
mail:x:8:8:mail:/var/mail:/bin/sh
news:x:9:9:news:/var/spool/news:/bin/sh
uucp:x:10:10:uucp:/var/spool/uucp:/bin/sh
proxy:x:13:13:proxy:/bin:/bin/sh
www-data:x:33:33:www-data:/var/www:/bin/sh
backup:x:34:34:backup:/var/backups:/bin/sh
list:x:38:38:Mailing List Manager:/var/list:/bin/sh
irc:x:39:39:ircd:/var/run/ircd:/bin/sh
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/bin/sh
nobody:x:65534:65534:nobody:/nonexistent:/bin/sh
libuuid:x:100:101::/var/lib/libuuid:/bin/sh
Debian-exim:x:101:103::/var/spool/exim4:/bin/false
messagebus:x:102:106::/var/run/dbus:/bin/false
colord:x:103:108:colord colour management daemon,,,:/var/lib/colord:/bin/false
ntp:x:104:109::/home/ntp:/bin/false
nslcd:x:105:110:nslcd name service LDAP connection
daemon,,,:/var/run/nslcd/:/bin/false
haldaemon:x:106:112:Hardware abstraction layer,,,:/var/run/hald:/bin/false
dirmngr:x:107:114::/var/cache/dirmngr:/bin/sh
memlockd:x:108:115:memlockd system account,,,:/usr/lib/memlockd:/bin/false
saned:x:109:116::/home/saned:/bin/false
kdm:x:110:65534::/home/kdm:/bin/false
sshd:x:111:65534::/var/run/sshd:/usr/sbin/nologin
michael:x:1000:1000:Michael Tsang:/home/michael:/bin/bash
mummy:x:1001:1001:Yanny Wong:/home/mummy:/bin/bash
root@client-debian:~# getent group
root:x:0:
daemon:x:1:
bin:x:2:
sys:x:3:
adm:x:4:
tty:x:5:
disk:x:6:
lp:x:7:
mail:x:8:
news:x:9:
uucp:x:10:
man:x:12:
proxy:x:13:
kmem:x:15:
dialout:x:20:
fax:x:21:
voice:x:22:
cdrom:x:24:
floppy:x:25:
tape:x:26:
sudo:x:27:michael
audio:x:29:
dip:x:30:
www-data:x:33:
backup:x:34:
operator:x:37:
list:x:38:
irc:x:39:
src:x:40:
gnats:x:41:
shadow:x:42:
utmp:x:43:
video:x:44:
sasl:x:45:
plugdev:x:46:
staff:x:50:
games:x:60:
users:x:100:
nogroup:x:65534:
libuuid:x:101:
crontab:x:102:
Debian-exim:x:103:
mlocate:x:104:
ssh:x:105:
messagebus:x:106:
scanner:x:107:saned
colord:x:108:
ntp:x:109:
nslcd:x:110:
utempter:x:111:
haldaemon:x:112:
powerdev:x:113:
dirmngr:x:114:
memlockd:x:115:
saned:x:116:
michael:*:1000:
mummy:*:1001:
root@client-debian:~# cat test.c
#include <grp.h>
#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

void call() {
        pid_t pid = fork();
        if (pid) {
                wait();
        } else {
                execl("/usr/bin/id", "id", NULL);
        }
}

int main(void) {
        struct passwd *pw = getpwnam("michael");
        printf("pw_name=%s\npw_uid=%d\npw_gid=%d\n", pw->pw_name,
(int)pw->pw_uid, (int)pw->pw_gid);
        call();
        initgroups(pw->pw_name, pw->pw_gid);
        call();
        setgid(pw->pw_gid);
        call();
        setuid(pw->pw_uid);
        call();
}
root@client-debian:~# make test
make: `test' is up to date.
root@client-debian:~# ./test
pw_name=michael
pw_uid=1000
pw_gid=1000
uid=0(root) gid=0(root) groups=0(root)
uid=0(root) gid=0(root) egid=27(sudo) groups=0(root),27(sudo),1000(michael)
uid=0(root) gid=1000(michael) groups=0(root),1000(michael)
uid=1000(michael) gid=1000(michael) groups=1000(michael)

As you can see at the above, the call to initgroups modifies the egid. This
behaviour is not documented in the man page. When combined with the following
code snipped from package shadow in libmisc/setugid.c:

int setup_groups (const struct passwd *info)
{
        /*
         * Set the real group ID to the primary group ID in the password
         * file.
         */
        if (setgid (info->pw_gid) == -1) {
                int err = errno;
                perror ("setgid");
                SYSLOG ((LOG_ERR, "bad group ID `%d' for user `%s': %s\n",
                         info->pw_gid, info->pw_name, strerror (err)));
                closelog ();
                return -1;
        }
#ifdef HAVE_INITGROUPS
        /*
         * For systems which support multiple concurrent groups, go get
         * the group set from the /etc/group file.
         */
        if (initgroups (info->pw_name, info->pw_gid) == -1) {
                int err = errno;
                perror ("initgroups");
                SYSLOG ((LOG_ERR, "initgroups failed for user `%s': %s\n",
                         info->pw_name, strerror (err)));
                closelog ();
                return -1;
        }
#endif
        return 0;
}

this behaviour would cause me to be logged in with egid != gid, which makes
bash thinks that it is run setgid and gives unintended behaviour. Also, it has
a potential security hole to the whole system by setting the egid wrongly. I
found this bug in a Debian GNU/kFreeBSD system, but not in a Debian GNU/Linux
system.

Regards,
Michael



-- System Information:
Debian Release: 7.0
  APT prefers testing
  APT policy: (500, 'testing')
Architecture: amd64 (x86_64)
Foreign Architectures: i386

Kernel: Linux 3.2.0-4-amd64 (SMP w/8 CPU cores)
Locale: LANG=en_HK.UTF-8, LC_CTYPE=en_HK.UTF-8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/dash


Reply to: