Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 11 Jul 2002 12:52:14 +0200
From:      Pawel Jakub Dawidek <nick@garage.freebsd.pl>
To:        freebsd-hackers@freebsd.org
Subject:   No suid crontab(1).
Message-ID:  <20020711105214.GJ12920@garage.freebsd.pl>

next in thread | raw e-mail | index | archive | help
Hello there.

On end of this post You got diif how to remove set-uid-root bit from
crontab(1). What You think about it?

Some directory and files perms changes:

leila:root:~# ls -l /usr/bin/crontab
-r-xr-sr-x  1 root  crontab  24804 11 Lip 12:37 /usr/bin/crontab

leila:root:~# ls -ld /var/cron
drwxr-x---  3 root  crontab  512 22 Maj  2001 /var/cron

leila:root:~# ls -l /var/cron
total 3
-rw-r-----  1 root  crontab    5 11 Lip 12:33 allow
-rw-r-----  1 root  crontab    6 11 Lip 12:33 deny
drwxrwx---  2 root  crontab  512 11 Lip 12:37 tabs

leila:root:~# ls -lo /var/cron/tabs
total 3
----rw----  1 giaur  crontab  uchg 254 11 Lip 12:23 giaur
----rw----  1 nick   crontab  uchg 255 11 Lip 12:37 nick
-rw-------  1 root   crontab  uchg 274 11 Lip 12:03 root


Of course You have to have crontab group defined in Your /etc/group.

If crontab will be broken, attacker can change ONLY his own file,
cause of uchg flags on files (yes, uchg, not schg, couse of securelevel).
Attacker can't remove any files too cause of uchg too in spite of he has
gid of directory /var/cron/tabs owner.

Oke, here You got patch:

11 Lip 12:36 2002 diff -lu /usr/src/usr.sbin/cron/crontab/Makefile projects/crontab/Makefile Page 1


--- /usr/src/usr.sbin/cron/crontab/Makefile	Wed Apr 25 14:09:24 2001
+++ projects/crontab/Makefile	Thu Jul 11 12:25:06 2002
@@ -8,7 +8,8 @@
 
 BINDIR=	/usr/bin
 BINOWN=	root
-BINMODE=4555
+BINGRP=	crontab
+BINMODE=2555
 INSTALLFLAGS=-fschg
 
 .include <bsd.prog.mk>


11 Lip 12:36 2002 diff -lu /usr/src/usr.sbin/cron/crontab/crontab.c projects/crontab/crontab.c Page 1


--- /usr/src/usr.sbin/cron/crontab/crontab.c	Sat Jun 16 05:18:37 2001
+++ projects/crontab/crontab.c	Thu Jul 11 12:36:23 2002
@@ -101,7 +101,6 @@
 	setlinebuf(stderr);
 #endif
 	parse_args(argc, argv);		/* sets many globals, opens a file */
-	set_cron_uid();
 	set_cron_cwd();
 	if (!allowed(User)) {
 		warnx("you (%s) are not allowed to use this program", User);
@@ -280,7 +279,7 @@
 
 	log_it(RealUser, Pid, "DELETE", User);
 	(void) sprintf(n, CRON_TAB(User));
-	if (unlink(n)) {
+	if (chflags(n, 0) || unlink(n)) {
 		if (errno == ENOENT)
 			errx(ERROR_EXIT, "no crontab for %s", User);
 		else
@@ -328,14 +327,6 @@
 		goto fatal;
 	}
 	(void) umask(um);
-#ifdef HAS_FCHOWN
-	if (fchown(t, getuid(), getgid()) < 0) {
-#else
-	if (chown(Filename, getuid(), getgid()) < 0) {
-#endif
-		warn("fchown");
-		goto fatal;
-	}
 	if (!(NewCrontab = fdopen(t, "r+"))) {
 		warn("fdopen");
 		goto fatal;
@@ -402,8 +393,8 @@
 		goto fatal;
 	case 0:
 		/* child */
-		if (setuid(getuid()) < 0)
-			err(ERROR_EXIT, "setuid(getuid())");
+		if (setgid(getgid()) < 0)
+			err(ERROR_EXIT, "setgid(getgid())");
 		if (chdir("/tmp") < 0)
 			err(ERROR_EXIT, "chdir(/tmp)");
 		if (strlen(editor) + strlen(Filename) + 2 >= MAX_TEMPSTR)
@@ -493,7 +484,7 @@
 replace_cmd() {
 	char	n[MAX_FNAME], envstr[MAX_ENVSTR], tn[MAX_FNAME];
 	FILE	*tmp;
-	int	ch, eof;
+	int	ch, eof, perm;
 	entry	*e;
 	time_t	now = time(NULL);
 	char	**envp = env_init();
@@ -563,24 +554,18 @@
 		return (-1);


11 Lip 12:36 2002 diff -lu /usr/src/usr.sbin/cron/crontab/crontab.c projects/crontab/crontab.c Page 2


 	}
 
-#ifdef HAS_FCHOWN
-	if (fchown(fileno(tmp), ROOT_UID, -1) < OK)
-#else
-	if (chown(tn, ROOT_UID, -1) < OK)
-#endif
-	{
-		warn("chown");
-		fclose(tmp);  unlink(tn);
-		return (-2);
-	}
-
+	if (getuid() == ROOT_UID)
+		perm = 0600;
+	else
+		perm = 0060;
+	
 #ifdef HAS_FCHMOD
-	if (fchmod(fileno(tmp), 0600) < OK)
+	if (fchmod(fileno(tmp), perm) < OK)
 #else
-	if (chmod(tn, 0600) < OK)
+	if (chmod(tn, perm) < OK)
 #endif
 	{
-		warn("chown");
+		warn("chmod");
 		fclose(tmp);  unlink(tn);
 		return (-2);
 	}
@@ -592,11 +577,19 @@
 	}
 
 	(void) sprintf(n, CRON_TAB(User));
+	chflags(n, 0);
 	if (rename(tn, n)) {
 		warn("error renaming %s to %s", tn, n);
 		unlink(tn);
 		return (-2);
 	}
+	if (chflags(n, UF_IMMUTABLE) < OK)
+	{
+		warn("chflags");
+		unlink(n);
+		return (-2);
+	}
+
 	log_it(RealUser, Pid, "REPLACE", User);
 
 	poke_daemon();


-- 
Pawel Jakub Dawidek
UNIX Systems Administrator
http://garage.freebsd.pl
Am I Evil? Yes, I Am.

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-hackers" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20020711105214.GJ12920>