COMMAND

    klogd

SYSTEMS AFFECTED

    Linux with klogd 1.3-22...25...29

PROBLEM

    Michal Zalewski  found following  buffer overflow  in Linux  klogd
    daemon from sysklogd-1.3 package (up  to release 22 - affects  Red
    Hat 5.x  and Slackware  3.x, no  data about  other distributions).
    This does appear to  affect a (fairly) stock  RH5.2 box also.   In
    tests, the  supplied module  code did  cause klogd  to die...  So,
    This problem  is also  present in  klogd 1.3-25  which ships  with
    RedHat 5.2.

    Kernel messages are stored in 4 kB cyclic printk ring. Klogd reads
    this buffer  using /proc/kmsg  to 4  kB long  buffer, that's good.
    But then, data is split into lines, by copying data until '\n'  is
    reached. What a pity, line buffer  is only 1 kB long -  sometimes,
    it's not  enough... Exploitable?   Could be...   To exploit   this
    security hole, we have to generate very long kernel message (or  a
    lot  of  short  messages  with  no  '\n'  inside).   There are two
    potential ways of doing this:

    a) In kernel source (or any of installed modules), find printk not
       terminated with '\n'. There are some old, obscure messages both
       in 2.0.xx and 2.1.xxx. Yep, but what now? You have to  generate
       it :-S It's  especially easy when  poking with strange  network
       packets  (so  it's  possible  to  perform  remote  DoS attack).
       Unfortunately, DoS if probably all  you can do - enjoy  SEGV in
       klogd daemon,  or (better?),  by overwriting  fd to  /proc/kmsg
       lyingo on the stack,  increase LA and generate  enormous amount
       of  error  messages  like   'Cannot  read  /proc   filesystem',
       apparently from kernel.

    b)  ...or,  in  kernel  (2.1.xxx  is more interesting), locate any
       printk  with  %s  in  format  string,  where substituted string
       depends in  some way  on luser  (process/filename?). Then,  you
       should  be  able  to  parse  arbitrary  shellcode  into buffer,
       obtaining root privledges.

    Quick vunerability test:

    -- gcc -c -O3 test.c; insmod test; rmmod test --
    #define MODULE
    #define __KERNEL__

    #include <linux/module.h>
    #include <linux/kernel.h>
    #include <linux/types.h>
    #include <linux/string.h>
    #include <linux/malloc.h>
    #include <asm/unistd.h>
    #include <linux/version.h>
    #include <asm/string.h>

    int init_module(void) {
      printk("INSERT_ABOUT_2000_BYTES_OF_JUNK_HERE\n"); return 0;
    }

    void cleanup_module(void) {}

    Modify  this  source  by  increasing  amount of junk after printk,
    compile, insmod and watch out what happened to klogd.

SOLUTION

    This bug  was fixed  *two* years  ago, but  some Linuxes are still
    shipping vulnerable old versions.   Please upgrade.   Additionally
    the most recent stable version may also be found on SunSITE at:

        ftp://sunsite.unc/edu/pub/Linux/system/daemons/

    In klog.c, at the beginning, there are two '#define's.  First  one
    is  responsible  for  main  buffer  size  -  don't change it, 4096
    should be ok.   The next one  is line buffer  size - hmm,  replace
    1024 with 4096, for example...   Or, better, implement some  range
    checking.

    Here's some range checking that will patch to the latest versions:

    --- klogd.c.orig        Wed Nov 11 12:47:16 1998
    +++ klogd.c     Wed Nov 11 13:03:20 1998
    @@ -465,6 +465,11 @@

            if ( index == 0 )
                    memset(line, '\0', sizeof(line));
    +
    +        if (len >= sizeof(line)) {
    +                len = sizeof (line) - 1;
    +                *(ptr + len) = '\0';
    +        }

            while (len) {
                    nl = strpbrk(ptr, "\r\n"); /* Find first line terminator */

    RedHat  immediately  issued  a  "fix"  to  their  current package:
    sysklogd-1.3-26.  This  "fix" is merely  patch by Cory  Visi.  His
    patch does  not fix  the problem.   The the  bug is  fixed in  the
    latest sysklogd package  (1.3-30). In fact,  the bug was  fixed in
    1996.   What this  comes down  to is  that any  Linux distribution
    running  an  old  sysklogd  package  (namely  RedHat all versions)
    still has a potential (rather obscure) buffer overflow.  They need
    to upgrade to the latest version ASAP.