TUCoPS :: Linux :: Debian :: cfingerd.txt

cfingerd 1.3.2 contains a security hole that could lead to a root compromise. (Included in Debain GNU/Linux).


[ http://www.rootshell.com/ ]

Date:         Thu, 23 Jul 1998 23:48:21 -0500
From:         John Goerzen <jgoerzen@COMPLETE.ORG>
Subject:      CFINGERD root security hole

SUMMARY
-------

I have found out that cfingerd 1.3.2 contains a security hole that
could lead to easy root compromise for any user that has an account on
the local machine, but only if ALLOW_EXECUTION is set in
/etc/cfingerd/cfingerd.conf.  By default, this option is DISABLED in
Debian GNU/Linux.

DETAILS
-------

The ALLOW_EXECUTION option permits any user on the system to execute a
program when their username is fingered.  cfingerd needs to run as
root but doesn't properly throw away root permissions when it starts
up the user's script.

When it is told to invoke /usr/bin/id from a user's script, it
produces:

uid=0(root) gid=0(root) euid=65534(nobody) groups=0(root)

EXPLOIT
-------

Have it exec this:

void main(void) {
  setreuid(0, 0);
  system("/usr/bin/id");
}

Of course, system can exec any more devious command you chose -- ie,
marking a shell setuid root, etc.  (Can also be done with C calls.)
No, I am NOT going to tell you how to make a setuid shell.  If you
don't know, you shouldn't be reading this.

To test the exploit, put something like this in ~/.project:

$exec /home/jgoerzen/test

and set the ALLOW_EXECUTION to be enabled.  This will give root for
everything.

Additionally, as you can tell, it fails to relenquish group
permissions at all.  After applying the below fix, the new output is:

uid=65534(nobody) gid=65534(nogroup) groups=65534(nogroup)

Much better!

FIX
---

Debian GNU/Linux comes with cfingerd, but in its default
configuration, it is safe.  For maximum security, please install the
upgraded packages anyway.  cfingerd greater than or equal to
1.3.2-11.0 will have the fix.  I have uploaded the fixed packages to
Incoming; before they propogate to the mirrors, you may find them at
http://happy.cs.twsu.edu/~jgoerzen/cfingerd/ along with the new
sources.

374531a02be81021ca9a12059a3c4515  cfingerd_1.3.2-11.0.diff.gz
f8819601f85115c063d5cace970554d6  cfingerd_1.3.2-11.0.dsc
2f943297e0b73fe32345e932f11b6a58  cfingerd_1.3.2-11.0_i386.changes
b9df424d723da39aa9c0067171822d56  cfingerd_1.3.2-11.0_i386.deb
4a3403d2519fea6b829bdeda9026c8ad  cfingerd_1.3.2-11.0_i386.upload

Those of you not using Debian may apply the following diff.

--- cfingerd-1.3.2.orig/src/privs.h
+++ cfingerd-1.3.2/src/privs.h
@@ -29,6 +29,7 @@
 #ifndef _USE_BSD
 #define _USE_BSD 1
 #include <unistd.h>
+#include <grp.h>
 #undef _USE_BSD
 #else
 #include <unistd.h>
@@ -72,14 +73,20 @@
 extern
 #endif
 gid_t real_gid, effective_gid;
+#ifndef MAIN
+extern
+#endif
+gid_t grouplist[1];

 #define RELINQUISH_PRIVS { \
                              real_uid = getuid(); \
                              effective_uid = NOBODY_UID; \
                              real_gid = getgid(); \
                              effective_gid = NOBODY_GID; \
-                             setregid(real_gid, effective_gid); \
-                             setreuid(real_uid, effective_uid); \
+                             grouplist[0] = effective_gid; \
+                             setgroups(1, grouplist); \
+                             setregid(effective_gid, effective_gid); \
+                             setreuid(effective_uid, effective_uid); \
                          }

 #define PRIV_ROOT_START {\
@@ -87,25 +94,29 @@
                            setregid(effective_gid, real_gid); \

 #define PRIV_ROOT_END \
-                           setregid(real_gid, effective_gid); \
-                           setreuid(real_uid, effective_uid); \
+                           setregid(effective_gid, effective_gid); \
+                           setreuid(effective_uid, effective_uid); \
                        }

 #define USER_PRIVS(a,b) {\
-                       setreuid(real_uid, 0); \
-                       setregid(real_gid, 0); \
+                       setreuid(0, 0); \
+                       setregid(0, 0); \
                        effective_uid = (a); \
                        effective_gid = (b); \
-                       setregid(real_gid, effective_gid); \
-                       setreuid(real_uid, effective_uid); \
+                       grouplist[0] = effective_gid; \
+                       setgroups(1, grouplist); \
+                       setregid(effective_gid, effective_gid); \
+                       setreuid(effective_uid, effective_uid); \
                    }

 #define NOBODY_PRIVS \
-                       setreuid(real_uid, 0); \
-                       setregid(real_gid, 0); \
+                       setreuid(0, 0); \
+                       setregid(0, 0); \
                        effective_uid = NOBODY_UID; \
                        effective_gid = NOBODY_GID; \
-                       setreuid(real_uid, effective_uid); \
-                       setregid(real_gid, effective_gid);
+                       grouplist[0] = NOBODY_GID; \
+                       setgroups(1, grouplist); \
+                       setgid(NOBODY_GID); \
+                       setuid(NOBODY_UID);

 #endif  /* _PRIVS_H_ */

ADDITIONAL CREDIT goes to Jakob Bohm Jensen <jbj@image.dk>.  He
reported some other things (not these in particular) that didn't turn
out to be a hole but lead me to examine the code carefully.

--
John Goerzen   Linux, Unix consulting & programming   jgoerzen@complete.org |
Developer, Debian GNU/Linux (Free powerful OS upgrade)       www.debian.org |
----------------------------------------------------------------------------+
Visit the Air Capital Linux Users Group on the web at http://www.aclug.org


TUCoPS is optimized to look best in Firefox® on a widescreen monitor (1440x900 or better).
Site design & layout copyright © 1986-2024 AOH