COMMAND
ccdconfig
SYSTEMS AFFECTED
FreeBSD, NetBSD, OpenBSD
PROBLEM
Niall Smart found vulnerability in ccdconfig. FreeBSD and
NetBSD's ccdconfig doesn't do proper checking of the argument to
-f:
[nsmart@ginseng ~]$ ccdconfig -U -f /dev/mem 2>&1 | strings | grep Charlie
root:iDeLeTeDiT:0:0::0:0:Charlie: No such file or directory
^C
You have to cat /etc/master.passwd in another window to get this
to work though so perhaps its not very easily exploitable, but is
worth fixing nonetheless.
Jess Kitchen added following that if you are persistent with chfn
in the background while grepping the ccdconfig output for :0: or
something similar, you will encounter chunks of /etc/master.passwd
which you can reconstruct gradually after a bit of tidying up.
It seems to be a bit hit and miss but root does eventually make an
appearance along with the majority of the other users under
FreeBSD 2.2 and 3.0.
SOLUTION
This bug was also spotted by olivier@secnet.com and fixed in
OpenBSD some time ago. Quick fix should be:
chmod g-s /sbin/ccdconfig
FreeBSD and NetBSD have been notified of the problem and have
fixed it in their source tree's (FreeBSD-current, FreeBSD-stable,
NetBSD-current). Retrieve the patched ccdconfig.c and compile
yourself a new ccdconfig. Here are the changes that applied to
FreeBSD. They are taken from the OpenBSD source base, possibly
with minor formatting tweaks, and seem to represent the work of
Theo de Raadt and oliver@secnet.com. These problems were fixed in
OpenBSD somewhere at start of 1997.
Index: ccdconfig.c
===================================================================
RCS file: /home/imp/FreeBSD/CVS/src/sbin/ccdconfig/ccdconfig.c,v
retrieving revision 1.7
diff -u -r1.7 ccdconfig.c
--- ccdconfig.c 1997/06/10 11:04:50 1.7
+++ ccdconfig.c 1997/12/30 05:08:24
@@ -161,6 +161,15 @@
if (options > 1)
usage();
+ /*
+ * Discard setgid privileges if not the running kernel so that bad
+ * guys can't print interesting stuff from kernel memory.
+ */
+ if (core != NULL || kernel != NULL || action != CCD_DUMP) {
+ setegid(getgid());
+ setgid(getgid());
+ }
+
switch (action) {
case CCD_CONFIG:
case CCD_UNCONFIG:
@@ -307,11 +316,16 @@
char line[_POSIX2_LINE_MAX];
char *cp, **argv;
int argc, rval;
+ gid_t egid;
+ egid = getegid();
+ setegid(getgid());
if ((f = fopen(ccdconf, "r")) == NULL) {
+ setegid(egid);
warn("fopen: %s", ccdconf);
return (1);
}
+ setegid(egid);
while (fgets(line, sizeof(line), f) != NULL) {
argc = 0;