[15129] in bugtraq
Re: more majordomo brokeness
daemon@ATHENA.MIT.EDU (Skahan, Vince)
Thu Jun 1 00:02:58 2000
Mime-Version: 1.0
Content-Type: text/plain; charset="iso-8859-1"
Message-Id: <71D105274EA7D011905700805FFECA5906B8EF9D@xch-sea-10.ca.boeing.com>
Date: Tue, 30 May 2000 07:49:52 -0700
Reply-To: "Skahan, Vince" <Vince.Skahan@PSS.BOEING.COM>
From: "Skahan, Vince" <Vince.Skahan@PSS.BOEING.COM>
X-To: BUGTRAQ@SECURITYFOCUS.COM, "Federico G. Schwindt"
<core.lists.bugtraq@CORE-SDI.COM>
To: BUGTRAQ@SECURITYFOCUS.COM
This came up in January. It's also well documented in the majordomo FAQ:
http://www.greatcircle.com/majordomo/majordomo-faq.html#wrapsec
It is easily possible to remove 'all' interactive access to all the pieces
of the majordomo software, even if you are using smrsh, without modifying
the majordomo software itself.
* set the group id in majordomo's makefile to group 'mail'
(assuming you're the same as RedHat and mail is delivered
as mail.mail on your o/s - check it with a script that runs 'id')
* remove world r-x on majordomo's home dir and its contents
* remove world r-x on the list dir and its contents
* still have the symbolic link to wrapper for smrsh to work if you
have that installed with your sendmail
Tested with majordomo 1.94-5 on RH-6.1 (sendmail8.9.3+smrsh)
--
-------- Vince.Skahan@boeing.com ------ http://bcstec.ca.boeing.com/~vds/ -------------
Boeing Shared Services Group - Technical Services
outside Boeing - http://www.halcyon.com/vince
> ----------
> From: Federico G. Schwindt[SMTP:core.lists.bugtraq@CORE-SDI.COM]
> Reply To: Federico G. Schwindt
> Sent: Tuesday, May 23, 2000 2:48 PM
> To: BUGTRAQ@SECURITYFOCUS.COM
> Subject: more majordomo brokeness
>
> Hi,
>
> Majordomo is a perl script for managing mailing lists. The package
> comes with several scripts and a program written in C (wrapper) that
> runs setuid to ensure that majordomo performs all the work with proper
> permissions (for further information you can check the FAQ that comes
> with the package under Doc/ or in
> http://www.visi.com/~barr/majordomo-faq.html).
> This wrapper is installed by default as root, mode 4755 and group as
> the one used for majordomo. What this means? If you can fool majordomo
> to run arbitrary commands, they'll be run with uid and gid equal to the
> one used for majordomo.
> Almost all of these scripts accept an optional configuration from the
> command line, which is loaded and evaluated via perl's require keyword.
> This file is nothing else than perl code, thus creating a special file
> with our commands and pointing it as the configuration of any of the
> affected scripts will result in the following (this applies to majordomo
> 1.94.5):
>
> $ cat /tmp/myconf
> system("/bin/sh");
> $ id
> uid=1000(fgsch) gid=1000(fgsch) groups=1000(fgsch), 0(wheel), 11(core)
> $ ./wrapper bounce-remind -C /tmp/myconf
> $ id
> uid=41(majordom) gid=41(majordom) groups=1000(fgsch), 0(wheel), 11(core)
>
> This is not new. The same problem has been seen in the past in the
> majordomo script shipped with the previous version, 1.94.4 (for more
> details, http://www.securityfocus.com/bid/903).
> Interesting enough, this occurs on several scripts: archive2.pl,
> bounce-remind, config-test, digest, majordomo, request-answer and
> resend; medit under bin/, and archive_mh.pl, new-list, and sequencer
> under Tools/ uses 'require' in the same way, but since the wrapper only
> executes those scripts found in the majordomo installation directory,
> they cannot be exploited.
> The obvious fix is to remove this option from all the involved
> scripts, but since it can be useful on large sites with several mailing
> lists, we've choosen instead to only allow configuration files from a
> trusted directory, removing the problem without loosing functionality.
> Diffs:
>
> --- majordomo-1.94.5/Makefile.orig Tue Jan 18 11:01:17 2000
> +++ majordomo-1.94.5/Makefile Tue May 23 07:05:24 2000
> @@ -63,7 +63,8 @@
> # passed to processes run by "wrapper"
> W_SHELL = /bin/sh
> W_PATH = /bin:/usr/bin:/usr/ucb
> -W_MAJORDOMO_CF = $(W_HOME)/majordomo.cf
> +W_MAJORDOMO_CF = majordomo.cf
> +W_MAJORDOMO_CFDIR = $(W_HOME)/config
>
> # A directory for temp files..
> TMPDIR = /usr/tmp
> @@ -77,7 +78,8 @@
>
> WRAPPER_FLAGS = -DBIN=\"$(W_HOME)\" -DPATH=\"PATH=$(W_PATH)\" > \
> -DHOME=\"HOME=$(W_HOME)\" -DSHELL=\"SHELL=$(W_SHELL)\" \
> - -DMAJORDOMO_CF=\"MAJORDOMO_CF=$(W_MAJORDOMO_CF)\" \
> + -DMAJORDOMO_CF=\"MAJORDOMO_CF=$(W_MAJORDOMO_CFDIR)/$(W_MAJORDOMO_CF)\"
> \
> + -DMAJORDOMO_CFDIR=\"MAJORDOMO_CFDIR=$(W_MAJORDOMO_CFDIR)\" \
> $(POSIX)
>
> INSTALL = ./install.sh
> --- majordomo-1.94.5/archive2.pl.orig Fri Jan 7 08:00:49 2000
> +++ majordomo-1.94.5/archive2.pl Tue May 23 07:47:09 2000
> @@ -50,7 +50,7 @@
> # Read and execute the .cf file
> $cf = $ENV{"MAJORDOMO_CF"} || "/etc/majordomo.cf";
> if ($ARGV[0] eq "-C") {
> - $cf = $ARGV[1];
> + $cf = "$ENV{'MAJORDOMO_CFDIR'}/$ARGV[1]" unless $ARGV[1] =~ /\//;
> shift(@ARGV);
> shift(@ARGV);
> }
> --- majordomo-1.94.5/contrib/archive_mh.pl.orig Mon Mar 10 12:40:41 1997
> +++ majordomo-1.94.5/contrib/archive_mh.pl Tue May 23 07:50:23 2000
> @@ -17,9 +17,9 @@
> $ENV{'PATH'} = "/bin:/usr/bin:/usr/ucb";
>
> # Read and execute the .cf file
> -$cf = $ENV{"MAJORDOMO_CF"} || "/tools/majordomo-1.56/majordomo.cf";
> +$cf = $ENV{"MAJORDOMO_CF"} || "/etc/majordomo.cf";
> if ($ARGV[0] eq "-C") {
> - $cf = $ARGV[1];
> + $cf = "$ENV{'MAJORDOMO_CFDIR'}/$ARGV[1]" unless $ARGV[1] =~ /\//;
> shift(@ARGV);
> shift(@ARGV);
> }
> --- majordomo-1.94.5/bounce-remind.orig Mon Dec 9 13:49:46 1996
> +++ majordomo-1.94.5/bounce-remind Tue May 23 07:47:27 2000
> @@ -20,7 +20,7 @@
> # Read and execute the .cf file
> $cf = $ENV{"MAJORDOMO_CF"} || "/etc/majordomo.cf";
> if ($ARGV[0] eq "-C") {
> - $cf = $ARGV[1];
> + $cf = "$ENV{'MAJORDOMO_CFDIR'}/$ARGV[1]";
> shift(@ARGV);
> shift(@ARGV);
> }
> --- majordomo-1.94.5/config-test.orig Wed Aug 27 12:17:13 1997
> +++ majordomo-1.94.5/config-test Tue May 23 16:10:05 2000
> @@ -117,6 +117,8 @@
> print "\n\tNon obvious things that cause headaches:\n\n";
> &header('');
>
> +$ARGV[0] = ($ARGV[0] && $ARGV[0] !~ /\//) ?
> + "$ENV{'MAJORDOMO_CFDIR'}/$ARGV[0]" : '';
> $cf = $ARGV[0] || $ENV{'MAJORDOMO_CF'};
>
> if (eval "require '$cf'") {
> --- majordomo-1.94.5/digest.orig Fri Jan 7 08:04:34 2000
> +++ majordomo-1.94.5/digest Tue May 23 16:02:49 2000
> @@ -322,6 +322,8 @@
> &abort("-C used without -l");
> } else {
> # Read and execute the .cf file
> + $opt_c = ($opt_c && $opt_c !~ /\//) ?
> + "$ENV{'MAJORDOMO_CFDIR'}/$opt_c" : '';
> $cf = $opt_c || $ENV{"MAJORDOMO_CF"} ||
> "/etc/majordomo.cf";
> require "$cf";
> --- majordomo-1.94.5/majordomo.orig Thu Jan 13 14:29:31 2000
> +++ majordomo-1.94.5/majordomo Tue May 23 07:48:42 2000
> @@ -29,7 +29,7 @@
>
> while ($ARGV[0]) { # parse for config file or default list
> if ($ARGV[0] =~ /^-C$/i) { # sendmail v8 clobbers case
> - $cf = $ARGV[1];
> + $cf = "$ENV{'MAJORDOMO_CFDIR'}/$ARGV[1]" unless $ARGV[1] =~
> /\//;
> shift(@ARGV);
> shift(@ARGV);
> } elsif ($ARGV[0] eq "-l") {
> --- majordomo-1.94.5/medit.orig Mon Apr 28 15:38:05 1997
> +++ majordomo-1.94.5/medit Tue May 23 07:48:55 2000
> @@ -19,7 +19,7 @@
> # Read and execute the .cf file
> $cf = $ENV{"MAJORDOMO_CF"} || "/etc/majordomo.cf";
> if ($ARGV[0] eq "-C") {
> - $cf = $ARGV[1];
> + $cf = "$ENV{'MAJORDOMO_CFDIR'}/$ARGV[1]" unless $ARGV[1] =~ /\//;
> shift(@ARGV);
> shift(@ARGV);
> }
> --- majordomo-1.94.5/contrib/new-list.orig Mon Dec 9 13:50:45 1996
> +++ majordomo-1.94.5/contrib/new-list Tue May 23 07:50:41 2000
> @@ -15,7 +15,7 @@
> # Read and execute the .cf file
> $cf = $ENV{"MAJORDOMO_CF"} || "/etc/majordomo.cf";
> if ($ARGV[0] eq "-C") {
> - $cf = $ARGV[1];
> + $cf = "$ENV{'MAJORDOMO_CFDIR'}/$ARGV[1]" unless $ARGV[1] =~ /\//;
> shift(@ARGV);
> shift(@ARGV);
> }
> --- majordomo-1.94.5/request-answer.orig Fri Jan 7 08:10:18 2000
> +++ majordomo-1.94.5/request-answer Tue May 23 07:49:10 2000
> @@ -16,7 +16,7 @@
> # Read and execute the .cf file
> $cf = $ENV{"MAJORDOMO_CF"} || "/etc/majordomo.cf";>
> if ($ARGV[0] eq "-C") {
> - $cf = $ARGV[1];
> + $cf = "$ENV{'MAJORDOMO_CFDIR'}/$ARGV[1]" unless $ARGV[1] =~ /\//;
> shift(@ARGV);
> shift(@ARGV);
> }
> --- majordomo-1.94.5/resend.orig Fri Jan 7 12:32:39 2000
> +++ majordomo-1.94.5/resend Tue May 23 16:02:37 2000
> @@ -79,6 +79,9 @@
> }
>
> # Read and execute the .cf file
> +$cfdir = $ENV{"MAJORDOMO_CFDIR"};
> +$opt_C = ($opt_C && $opt_C !~ /\//) ? "$cfdir/$opt_C" : '';
> +$opt_c = ($opt_c && $opt_c !~ /\//) ? "$cfdir/$opt_c" : '';
> $cf = $opt_C || $opt_c || $ENV{"MAJORDOMO_CF"} || "/etc/majordomo.cf";
>
> # Despite not having a place to send the remains of the body,
> --- majordomo-1.94.5/contrib/sequencer.orig Mon Dec 9 13:50:48 1996
> +++ majordomo-1.94.5/contrib/sequencer Tue May 23 07:50:58 2000
> @@ -48,7 +48,7 @@
> # Read and execute the .cf file
> $cf = $ENV{"MAJORDOMO_CF"} || "/etc/majordomo.cf";
> if ($ARGV[0] eq "-C") {
> - $cf = $ARGV[1];
> + $cf = "$ENV{'MAJORDOMO_CFDIR'}/$ARGV[1]" unless $ARGV[1] =~ /\//;
> shift(@ARGV);
> shift(@ARGV);
> }
> --- majordomo-1.94.5/wrapper.c.orig Wed Aug 27 12:01:12 1997
> +++ majordomo-1.94.5/wrapper.c Tue May 23 07:06:23 2000
> @@ -42,20 +42,27 @@
> # define SHELL "SHELL=/bin/sh"
> #endif
>
> +#ifndef MAJORDOMO_CF
> +# error "MAJORDOMO_CF not defined; edit Makefile"
> +#endif
> +
> +#ifndef MAJORDOMO_CFDIR
> +# error "MAJORDOMO_CFDIR not defined; edit Makefile"
> +#endif
> +
> char * new_env[] = {
> HOME, /* 0 */
> PATH, /* 1 */
> SHELL, /* 2 */
> -#ifdef MAJORDOMO_CF
> MAJORDOMO_CF, /* 3 */
> -#endif
> + MAJORDOMO_CFDIR, /* 4 */
> 0, /* possibly for USER or LOGNAME */
> 0, /* possible for LOGNAME */
> 0, /* possibly for timezone */
> 0
> };
>
> -int new_env_size = 7; /* to prevent overflow problems */
> +int new_env_size = 8; /* to prevent overflow problems */
>
> main(argc, argv, env)
> int argc;
> @@ -89,11 +96,7 @@
> * if they exist.
> */
>
> -#ifdef MAJORDOMO_CF
> - e = 4; /* the first unused slot in new_env[] */
> -#else
> - e = 3; /* the first unused slot in new_env[] */
> -#endif
> + e = 5; /* the first unused slot in new_env[] */
>
> for (i = 0 ; env[i] != NULL && e <= new_env_size; i++) {
> if ((strncmp(env[i], "USER=", 5) == 0) ||
> @@ -153,5 +156,6 @@
> fprintf(stderr, " PATH is %s,\n", PATH);
> fprintf(stderr, " SHELL is %s,\n", SHELL);
> fprintf(stderr, " MAJORDOMO_CF is %s\n", MAJORDOMO_CF);
> + fprintf(stderr, " MAJORDOMO_CFDIR is %s\n", MAJORDOMO_CFDIR);
> exit(EX_OSERR);
> }
>
> MAJORDOMO_CFDIR points to the trusted directory. You should store all
> the configuration files there. Be sure that is pointing to the correct
> place or majordomo won't work.
> We've also modified wrapper.c to barf if neither MAJORDOMO_CF nor
> MAJORDOMO_CFDIR are defined, since there is no point in using it
> otherwise, plus a few other minor paranoia changes... ;)
> Salute,
>
> f.-
>
> --
> Federico Schwindt - Developer fgsch@core-sdi.com
> Core SDI S.A. http://www.core-sdi.com
>
> --- For a personal reply use fgsch@core-sdi.com
>