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