[15125] in bugtraq

home help back first fref pref prev next nref lref last post

Re: more majordomo brokeness

daemon@ATHENA.MIT.EDU (Richard Trott)
Wed May 31 23:30:11 2000

Mime-Version: 1.0
Content-Type: TEXT/PLAIN; charset=US-ASCII
Message-Id:  <Pine.BSO.4.10.10005311002070.5108-100000@www>
Date:         Wed, 31 May 2000 10:04:41 -0700
Reply-To: trott@SLOWPOISONERS.COM
From: Richard Trott <trott@SLOWPOISONERS.COM>
X-To:         "Federico G. Schwindt" <core.lists.bugtraq@CORE-SDI.COM>
To: BUGTRAQ@SECURITYFOCUS.COM
In-Reply-To:  <392AE52C.8512B2CB@core-sdi.com>

Isn't this issue addressed by the recommended procedure at the very top of
the INSTALL file?  It recommends installing majordomo only on a secure
server without user logins, or else chmod 750 the majordomo home
directory.

Rich


On Tue, 23 May 2000, Federico G. Schwindt wrote:

> 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
>
>
>

home help back first fref pref prev next nref lref last post