COMMAND

    MajorCool (mj_key_cache)

SYSTEMS AFFECTED

    Systems running MajorCool 1.0.3 (and earlier)

PROBLEM

    mj_key_cache  program  that  comes  with  MajorCool.   1.0.3   and
    earlier writes  to /tmp/cache  without proper  checking.   Systems
    running MajorCool  1.0.3 and  below with  the mj_key_cache program
    cron'd  as  necessary  for  most  operation  are vulnerable.  This
    vulnerability allows any user on  the local system to corrupt  any
    file writable by  the user and  group mj_key_cache runs  as.  This
    is usually majordom/majordom although is set at installation.

    mj_key_cache  is  a  cron  job  for  MajorCool  that  stores  list
    information in ~majordom/lists/.majorcool_cache to be used by  the
    majordomo cgi perl script.

    The following  line from  mj_key_cache is  where the vulnerability
    is:

        open(TMP, ">/tmp/cache") || &squawk("Could not open cache");

    This can be exploited by creating a symbolic link from  /tmp/cache
    to the file that is to  be corrupted.  Credit goes to  Benjamin J.
    Stassart.

SOLUTION

    Patch the mj_key_cache program using the diff written by a  fellow
    system administrator Ash below or  upgrade to the next release  of
    MajorCool when it  becomes available.   Authors of this  have been
    in contact  with Mr.  Houle and  he said  he that will incorporate
    Ash's  changes  in  the  next  release  of MajorCool.  Ash rewrote
    mj_key_cache to avoid using a temp file altogether.

mj_key_cache diff rewritten by ash@dasb.fhda.edu
    ------------------------------------------------------------------
*** mj_key_cache        Fri May 30 17:21:48 1997
--- mj_key_cache.orig Tue May 27 20:14:45 1997
***************
*** 71,77 ****
  @lists = readdir(RD_DIR);
  closedir(RD_DIR);

! open(CACHE, "> $cache") || &squawk("Could not open cache");
  foreach (sort @lists) {
        local($list) = $_;
        $list =~ s,^.*/,,;                      # strip off leading path
--- 71,77 ----
  @lists = readdir(RD_DIR);
  closedir(RD_DIR);

! open(TMP, ">/tmp/cache") || &squawk("Could not open cache");
  foreach (sort @lists) {
        local($list) = $_;
        $list =~ s,^.*/,,;                      # strip off leading path
***************
*** 84,101 ****
        local($policy) = $config_opts{$list,'subscribe_policy'};
        local($advertise) = $config_opts{$list,'advertise'};
        local($noadvertise) = $config_opts{$list,'noadvertise'};
!       push @TMP, "$list#$owner#$policy#$desc#$advertise#$noadvertise\n";
  }
! print CACHE @TMP;
! close(CACHE);

! #if ( -s "/tmp/cache" ) {
! #     system("cp /tmp/cache $cache; rm /tmp/cache");
        printf STDERR "$main'program_name: cache complete\n" if $verbose;
! #}
! #else {
! #     &squawk("Key cache file empty: /tmp/cache");
! #}

  # free_lock is only 1.94
  &free_lock("$listdir/.cache.LOCK") if defined(&free_lock);
--- 84,100 ----
        local($policy) = $config_opts{$list,'subscribe_policy'};
        local($advertise) = $config_opts{$list,'advertise'};
        local($noadvertise) = $config_opts{$list,'noadvertise'};
!       print TMP "$list#$owner#$policy#$desc#$advertise#$noadvertise\n";
  }
! close(TMP);

! if ( -s "/tmp/cache" ) {
!       system("cp /tmp/cache $cache; rm /tmp/cache");
        printf STDERR "$main'program_name: cache complete\n" if $verbose;
! }
! else {
!       &squawk("Key cache file empty: /tmp/cache");
! }

  # free_lock is only 1.94
  &free_lock("$listdir/.cache.LOCK") if defined(&free_lock);
    ------------------------------------------------------------------
end of mj_key_cache diff