[net.unix-wizards] chroot

jfw%mit-ccc@BRL.ARPA (07/07/83)

I have just tried your suggestion on MIT-CCC, which is a V7 PDP 11/45.
The program is as follows:

main()
{
	if (chroot("/usr/jfw") < 0)
		exit(perror("/usr/jfw"));
	setuid(getuid());
	execl("sh","sh",0);
}
	
In my home directory, by the way, is a copy of /bin/sh.
This program is SUID root.  What happens when I run it is the following:
I see a shell which believes that /usr/jfw is the root.  I say "ls /"
and see my files (there is a copy of ls in /usr/jfw, too).  BUT:  If I
type:
	cd ..
the kernel obligingly looks up the inode which is linked under the name ".."
and my shell lands there.  Most people call it "/usr".  I know not what
pwd would call it, but I certainly am no longer restricted to the /usr/jfw
heirarchy.  I then type "cd .." again and land in the root, which is on
another device.

As far as 4.1BSD goes:  The code for chroot(), chdir(), and chdirec() (the
underlying code of both) is character for character the same:  ERGO, 4.1
does exactly the same.  If you tried it and got the results you claim, then
you are running something which isn't standard.  If you haven't tried these
cases (nor thought about them), then I think you have overlooked something.

Summary:  REMEMBER that UNIX heirarchy reverse-links are implemented with
pointers that turn the directed acyclic graph you think you see into a
heavily-cyclic graph.  If you want to do this, I suppose that you could remove
the ".." pointer in /usr/guests, but a lot of UNIX utilities are going to
throw up their hands at that.

The only truly secure system is a personal computer locked in a room -- with
the power cord unplugged.  Undo any of those, and you've got to accept
compromises.

	John Woods, jfw%mit-ccc@Mit-MC

bob%ucla-locus@sri-unix.UUCP (07/07/83)

From:  Bob English <bob@ucla-locus>

Actually, the chroot call is not the problem.  Chroot works the
same way as chdir, but on a different incore directory.  In order
to create a secure sub-tree, you'd have to modify namei so that
it checks for the root directory when ever it follows a path "up"
the tree.

A simpler, but less complete, solution is to make the directory
above the proposed root inaccessible to anyone in the "guest"
category.  This has unfortunate side effects (pwd stops working,
users can't exec csh in the directory, etc.), but nothing that
can't be overcome.

I can't perform an experiment (chroot doesn't work to well here),
but I'd like to know what a pwd in /usr/guest yields.

--bob--

rsm%brl-bmd@sri-unix.UUCP (07/07/83)

From:      Robert S. Miles <rsm@brl-bmd>

You're both right!  The concept of each process having is own pointer
to a "root directory" introduced in UNIX Version 7 was not implemented
in a completely "secure" manner.  As you have shown, on a V7 system it
is possible to to access ".." above your root directory.  On System III,
BSD 4.1, and BSD 4.2 UNIX systems the kernel actually checks to see if
you're accessing the name ".." in the root directory, if so it just remaps
".." to be your root directory.  Therefore "/.." will always be the same
as "/" on one of these more modern systems.

					-Bob Miles, rsm@BRL

matt%ucla-locus@sri-unix.UUCP (07/07/83)

From:            Matthew J. Weinstein <matt@ucla-locus>

I believe that .. can be unlinked by the super user using the unlink() call.
At that point, a link of .. to . would leave a closed subtree.
This subtree could then be used safely... (I think).

This should probably be done only in a newly created directory, since 
some code may make assumptions about the location of .. in 
the directory (first block).

			RSVP
			- Matt

guy@rlgvax.UUCP (07/10/83)

As an earlier poster said, both sides of this argument are correct.  A short
explanation of some other points:

	As far as 4.1BSD goes:  The code for chroot(), chdir(), and chdirec()
	(the underlying code of both) is character for character the same:
	ERGO, 4.1 does exactly the same.

But the code in namei() is different, and THAT is the code that interprets
pathnames.  All chdir(), chroot(), and chdirec() do is set an inode pointer
in your u-page; namei() is the routine that is affected by changing that
pointer.

	Summary:  REMEMBER that UNIX heirarchy reverse-links are implemented
	with pointers that turn the directed acyclic graph you think you see
	into a heavily-cyclic graph.  If you want to do this, I suppose that
	you could remove the ".." pointer in /usr/guests, but a lot of UNIX
	utilities are going to throw up their hands at that.

The fix in 4.1BSD and System III causes a dynamic reinterpretation of the ".."
link, so that the tree looks different to different processes.  The ".." link
should NOT be removed, as it will upset those utilities; the fix should be put
into namei() to reinterpret that link if it points above the fake root
directory.

Conclusion: on 4.1BSD and System III (and all later releases), feel free to
use chroot().  On V7, put in the fix I posted, and then feel free to use
chroot().  If you're running a UNIX-lookalike, make sure if it has chroot()
that the hole has been plugged.  If you wrote a UNIX-lookalike with chroot(),
plug the hole.

	Guy Harris
	{seismo,mcnc,we13,brl-bmd,allegra}!rlgvax!guy

guy@rlgvax.UUCP (07/10/83)

The fix to namei() is fairly simple (3-5 lines of code, depending on whether
you format it the way Berkeley did or the way Bell did) and has been posted
to net.unix-wizards and net.bugs.v7.

A "pwd" in "/usr/guest" after chroot("/usr/guest") and chdir("/") prints "/" on
4.1BSD.  The only significant difference between the 4.1BSD "pwd" command and
the System III "pwd" command is that the 4.1BSD command does a stat("/") and
saves the dev/inumber pair of "/", and it stops backing up the directory tree
whenever it finds a directory with that dev/inumber pair.  Both versions stop
when they find a directory in which a chdir("..") leaves you in the same
directory.  I suspect the System III version will also print "/" after the
chroot().

	Guy Harris
	{seismo,mcnc,we13,brl-bmd,allegra}!rlgvax!guy

jhh@ihldt.UUCP (07/12/83)

If the process that inherits the new root can create executable
files, the checks in the code are not near enough if the user
runs as user id 0.  There are many things that they could do
to increase their permissions.  The easiest thing would be to
add a link to .. (which UID 0 can do), and change to that.
More complicated scenarios would be using the mknod system call
to create special device files, and mounting them.

Moral: ID 0 is very special to the operating system, and cannot be trusted
to someone that needs chroot'ed.

			John Haller

MCLINDEN@RUTGERS.ARPA (07/13/83)

From:  Sean McLinden <MCLINDEN@RUTGERS.ARPA>



  If there was ever a better reason for keeping this discussion public than 
  the current discussion, I don't know what it is.

  Bob English brings up a good point which shouldn't be dismissed,
  however, the solution may not be quite as complex as he stated. I am
  willing to admit that there are some difficulties with the example
  I gave IF one uses the Bourne shell. I specifically used the C-shell
  because it explicitly handles the cases of "/", "./", and ".." . I
  still maintain that if the shell that I listed (the C-shell) is called
  from a process which invokes chroot(), you can create a secure shell
  UNLESS you allow users to call programs within that heirarchy which are
  linked to programs outside that heirarchy. Furthermore, simple attempts
  such as writing a program which calls "chdir" won't work, even if you are
  the super user. Of course, I don't expect that users of the restricted
  shell will be able to do everything a non-restricted user can. But
  then I was speaking on the case of the casual user, such as student
  running Lisp or (God forbid), FORTRAN, who doesn't need to use programs
  which setuid 0 or  read kmem. I'd be the first to admit you can't have
  your cake and eat it too. And besides,  I wanted to talk about something
  besides passwords.

  [Bring on the lions!]

  Sean
-------

berry@fortune.UUCP (07/15/83)

#R:sri-arpa:-285600:fortune:11600026:000:613
fortune!berry    Jul 14 20:10:00 1983

-------------------
	Does anyone know why chroot() is protected?
	What harm can be done by a user who restricts himself to
	a part of the file-tree?
-------------------


	What about the following procedure?

	link /bin/login to .../me/bin/login
	link /bin/csh   to .../me/bin/csh
	edit .../my/etc/passwd to contain a root entry with no password
	chroot .../me
	login root
	#

	I now have a root shell.  Granted I can only play in this filesystem
for now, but what is to keep me from creating files setuid root that merely
exec /bin/csh...



	David W. Berry
	amd70!fortune!berry
	cbosgd!...
	harpo!...
	hpda!...

Michael.Young@cmu-cs-g@sri-unix.UUCP (07/15/83)

Well, some utilities like to find some files in well-known places
(from the root of the filesystem, that is).
If you were able to, for example, link some setuid utility
from /usr/xxx to your subtree (which is often possible on systems
where /usr/foo is 'foo's home directory, and is on the same
filesystem as /usr/bin, etc.), and then chroot there, you could
fool it into thinking your version of a system file is real.
A good example would be 'su' (if you could link to it, that is).
All you'd have to do is make your own password file, and you could
be anyone.

			Michael

P.S.	It still should be possible for utilities to determine that
	the current "root" directory is actually a filesystem root,
	and react accordingly, but none do.  Plus, you couldn't
	tell mounted filesystems from the main one.  Assuring that
	an /etc/, and other similar directories, couldn't be
	created on any mounted filesystem would help in this regard,
	but making chroot privileged is just a lot easier.

mash@whuxlb.UUCP (07/16/83)

chroot() must be protected lest programs that trust the sanctity of
certain files (/like /etc/passwd) be faked out by dummies:
1) create a small directory structure with a dummy /etc/passwd
2) make a copy of /bin/su & /bin/sh where they can be gotten.
3) chroot
4) su, then make the copy of sh setuid-root for later use.
[sad tosay, many systems have readable setuid-root pgms lying around].
-mashey

pdl@root44.UUCP (Dave Lukes) (07/18/83)

Lessons in non-logic, Part 1:

    As far as 4.1BSD goes:  The code for chroot(), chdir(), and chdirec() (the
    underlying code of both) is character for character the same:  ERGO, 4.1
    does exactly the same.

So what if the code for chroot(), chdir(), and chdirec() is the same ?
The code for nami() (the underlying code for ALL file naming) is NOT
character for character the same:  ERGO, 4.1 DOESN'T do exactly the same.

(What happened to experimentation: why not TRY it before you say it next time ?)

(As far as I am aware, NO post-V7 UN*X has got that mis-feature about `..'.)
 
			Yours empirically
				Dave Lukes (...!vax135!ukc!root44!pdl)

P.S. Would it be possible for people to stop arguing about this now ?
It's all been said several times over now.

jack@vu44.UUCP (07/21/83)

Does anyone know why chroot() is protected?
What harm can be done by a user who restricts himself to
a part of the file-tree?

		Jack Jansen, VU Amsterdam.
		(mcvax!vu44!jack)

olson@fortune.UUCP (04/03/84)

#N:fortune:11600081:000:1487
fortune!olson    Apr  3 10:20:00 1984

I am in the process of setting up some restricted logins (using
chroot(2), a modified login, etc.).  (This is on a V7/4.1 BSD hybrid)
I have just run into an annoying problem, and would appreciate any
solutions you can suggest.

The problem is that (for space reasons) I am setting up the restricted
root on a different device than the root pack.  For most programs,
this is not a problem.  However, any program which uses ttyname(3) can
not get the tty name.  The problem is that ttyname checks NOT the real
device number, but the device number AND the inode number OF THE FILE
/dev/tty*.  Why did they not simply check for the REAL device number?

Since my root is on a different device, the inode numbers of the tty's
are different, and hence, ttyname(), and the programs which use it
(tty(1), who am i (1), etc.) all come back with 'not a tty', or '??',
etc.

While this is certainly not fatal, it is annoying.  Does anyone have
any ideas, other than fixing ttyname(), and recompiling everything
that uses it?

Parenthetically, does anyone know why ttyname was written this way,
given the fact that chroot(2) has been around in one form or another
for quite a while?  (I suspect the main reason was so a tty device
could have several names (NOT links!) and have the correct one
reported.  If this was the case, it appears that the impact of chroot()
was not thought through.

	Dave Olson, Fortune Systems
	UUCP: {ihnp4,ucbvax!amd70}!fortune!olson
	ARPA: amd70!fortune!olson@BERKELEY

mbr@aoa.UUCP (Mark Rosenthal) (04/22/86)

As part of a solution to the Trojan Horse shar file problem, I suggested:
>> Another idea.  Don't just run it in an empty subdirectory.  Chroot to that
>> subdirectory.

In article <1451@homxb.UUCP> os848@homxb.UUCP (M.AJEMIAN) responds:
>chroot will require that all programs that the shar uses be accessible, meaning
>you'll have to create a bin directory in the area where you want to create
>incoming files and link in cat, mkdir, sed, the shell, etc.  Also, note that
>not all UNIX ports either have chroot() or implement it properly.  I'm not sure,
>but someone tells me that the old Zilog Zeus ports of Sys III allow you to use
>../../anything to get out of the new root directory.  Anyone know if this is
>true or not?
>
>Pat Wood
>Pipeline Associates, Inc.
>{ihnp4, attunix} !whuxn!phw5!phw

I thought that chroot() caused open()s and creat()s and the like to use the
new root, but didn't affect the interpretation of root for exec().  Anybody
know for certain?

Also, does anybody know if there are brain-damaged implementations of chroot()
out there?

I have added net.unix-wizards to the newsgroup list for this article.  If you
post a non-technical followup, please remove net.unix-wizards from the list.
-- 

	Mark of the Valley of Roses
	...!{decvax,linus,ima,ihnp4}!bbncca!aoa!mbr
	...!{wjh12,mit-vax}!biomed!aoa!mbr

parris@itcatl.UUCP (Parris Hughes) (09/25/86)

Could some wizard out there please clue me in as to why the chroot(2) call
is only available to the super-user?  I'm probably missing something here,
but I don't see any potential security problems with it.  Please E-mail your
response.  Thanks.

Parris				{akgua|ihnp4}!gatech!itcatl!parris

apn@nonvon.UUCP (apn) (09/29/86)

In article <158@itcatl.UUCP>, parris@itcatl.UUCP (Parris Hughes) writes:
> Could some wizard out there please clue me in as to why the chroot(2) call
> is only available to the super-user?  I'm probably missing something here,
> but I don't see any potential security problems with it.  Please E-mail your
> response.  Thanks.
> 
> Parris				{akgua|ihnp4}!gatech!itcatl!parris

	Let's do an experiment:

	Pretend that chroot can be executed by any user, then
	it follows that one could do the following:

	cd to your home directory ( or any directory you have write permission)
	(we will pretend it is /mnt33/user/test)

	make a subdirectory called "etc" in you directory
	(this is now /mnt33/user/test/etc)

	copy /etc/passwd to /mt33/user/test/etc/passwd

	edit out the passwd for root

	write a program that changes the root directory to
	/mnt23/user/test
	and then procedes to exec /bin/login

	run the program and log in as the su.


	Get the idea ?


	-alex p novickis

ballou@brahms.BERKELEY.EDU (Kenneth R. Ballou) (10/01/86)

In article <113@nonvon.UUCP> apn@nonvon.UUCP (apn) writes:
>In article <158@itcatl.UUCP>, parris@itcatl.UUCP (Parris Hughes) writes:
>> Could some wizard out there please clue me in as to why the chroot(2) call
>> is only available to the super-user?  I'm probably missing something here,
>> but I don't see any potential security problems with it.  Please E-mail your
>> response.  Thanks.
>> 
>> Parris				{akgua|ihnp4}!gatech!itcatl!parris
>
>	Let's do an experiment:
>
>	Pretend that chroot can be executed by any user, then
>	it follows that one could do the following:
>
>	cd to your home directory ( or any directory you have write permission)
>	(we will pretend it is /mnt33/user/test)
>
>	make a subdirectory called "etc" in you directory
>	(this is now /mnt33/user/test/etc)
>
>	copy /etc/passwd to /mt33/user/test/etc/passwd
>
>	edit out the passwd for root
>
>	write a program that changes the root directory to
>	/mnt23/user/test
>	and then procedes to exec /bin/login

Wait a minute, now it's *my* turn to be missing something here.  *Which*
/bin/login?  If the root directory is now actually /mnt23/user/test, then
presumably we would be trying to execute /mnt23/user/test/bin/login, not
the /bin/login that is setuid root and which is able to log a user in.

>	run the program and log in as the su.

>	-alex p novickis

--------------
Kenneth R. Ballou			...!ucbvax!ucbbrahms!ballou
Dept. of Mathematics
Evans Hall
University of California
Berkeley, California  94720

stuart@BMS-AT.UUCP (Stuart D. Gathman) (10/02/86)

In article <113@nonvon.UUCP>, apn@nonvon.UUCP (apn) writes:

> 	write a program that changes the root directory to /mnt23/user/test
> 	and then procedes to exec /bin/login

	On our system, login only has execute permission for root.
But, one can link in the 'su' command! Even if the /bin directory is
execute only!  The resulting superuser process could then *modify* the
su program to allow a special root password after leaving the chroot process.
(Otherwise, even the root process could not access anything below the new
root directory.)

I believe that 'su' is the only problem.  Take away 'su' and you can give
them 'chroot'.  ('newgrp' is similar but not as bad.)
-- 
Stuart D. Gathman	<..!seismo!{vrdxhq|dgis}!BMS-AT!stuart>

jim@aob.uucp (Jim Anderson) (10/03/86)

In article <15879@ucbvax.BERKELEY.EDU> ballou@brahms.UUCP (Kenneth R. Ballou) writes:
>In article <113@nonvon.UUCP> apn@nonvon.UUCP (apn) writes:
>>In article <158@itcatl.UUCP>, parris@itcatl.UUCP (Parris Hughes) writes:
>>> Could some wizard out there please clue me in as to why the chroot(2) call
>>> is only available to the super-user? 
>>> 
>>		... chroot to 
>>	/mnt23/user/test
>>	and then procedes to exec /bin/login
>
>Wait a minute, now it's *my* turn to be missing something here.  *Which*
>/bin/login?  If the root directory is now actually /mnt23/user/test, then
>presumably we would be trying to execute /mnt23/user/test/bin/login, not
>the /bin/login that is setuid root and which is able to log a user in.

But you could start by doing a link from /bin/login to
/mnt23/user/test/bin/login.  Then, even though you don't have any special
permissions with respect to your linked bin/login, you can still execute
it from your login directory.
When you are done, and you want to get rid of the /bin/login in your
directory, rm will probably mention that you don't have write permission
on a file that you don't own, but since you do have write permission on
your bin directory, it will let you remove the file (ie you CAN still
clean up your trail).

	Jim Anderson

jrw@hropus.UUCP (Jim Webb) (10/03/86)

> In article <113@nonvon.UUCP>, apn@nonvon.UUCP (apn) writes:
> 
> > 	write a program that changes the root directory to /mnt23/user/test
> > 	and then procedes to exec /bin/login
> 
> 	On our system, login only has execute permission for root.

True here as well, but some sites setuid root login so that people can
say "exec login" to come in as another user w/o problems.  Who nows why
one would want to, though...

> But, one can link in the 'su' command! Even if the /bin directory is
> execute only!

As an aside, if /bin were not readable, no one could use PATH to find anything
in it, not tooo cool, if you ask me...

>                The resulting superuser process could then *modify* the
> su program to allow a special root password after leaving the chroot process.
> (Otherwise, even the root process could not access anything below the new
> root directory.)

It is even easier.  Assume for a moment that /tmp is actually in root instead
of being its on filesystem.  Now, make an etc and bin directory in /tmp.
ln the real /etc/passwd into /tmp/etc/realpasswd and make a /tmp/etc/passwd
with a passwdless root entry.  ln in /bin/su into /tmp/bin/su and copy /bin/sh
there too, although you could link it as well.  Make sure to do the same for
/bin/ed.  (I guess you would need some /dev entries, too.) Now chroot to /tmp
to run su and edit /etc/realpasswd.  When it is written out, you could have
added in a new root entry.
-- 
Jim Webb             "Out of phase--get help"          ...!ihnp4!hropus!jrw

jdh@bu-cs.BU.EDU (Jason Heirtzler) (10/04/86)

In article <233@BMS-AT.UUCP> stuart@BMS-AT.UUCP (Stuart D. Gathman) writes:
>In article <113@nonvon.UUCP>, apn@nonvon.UUCP (apn) writes:
>
>> 	write a program that changes the root directory to /mnt23/user/test
>> 	and then procedes to exec /bin/login
>
>	On our system, login only has execute permission for root.
>But, one can link in the 'su' command! Even if the /bin directory is
>execute only!  The resulting superuser process could then *modify* the
>su program to allow a special root password after leaving the chroot process.
>(Otherwise, even the root process could not access anything below the new
>root directory.)
>
>I believe that 'su' is the only problem.  Take away 'su' and you can give
>them 'chroot'.  ('newgrp' is similar but not as bad.)
>-- 
>Stuart D. Gathman	<..!seismo!{vrdxhq|dgis}!BMS-AT!stuart>

"Taking away" su(1) really won't help the problem at all.
Note that on other Unix systems (BSD 4.2 and SUN 3.0 for instance),
/bin/login is executable by everyone.

Modifying the executable image of su(1), isn't necessary to create
a loop hole. An unscrupulus user that could use chroot could put HIS
copy of /etc/passwd in /mnt23/user/test/etc/passwd, and also make a
hard link from /mnt23/user/test/bin/login to /bin/login; then execve(2)
(the calling process would inherit the process's root directory)
to (the link of) the login program.. or the exact same thing could be
done for /bin/su in place of /bin/login. You'd probably need other stuff
like a link to /bin/csh and maybe a link to / (to get out of the whole
mess, yourself). You get the idea.

The point of all of this being that the fundamental reason chroot(2)
can't be patched to allow everyone to use it is that hard links 
(though not soft links) are the real cause of the security loop
hole with chroot.


---------
Jason Heirtzler

Csnet: jdh@bu-cs              Bitnet: csce1mc@bostonu
Uucp:  ...harvard!bu-cs!jdh   Arpa:   jdh@bu-cs.bu.edu

dpw@rayssd.UUCP (Darryl P. Wagoner) (10/04/86)

> >
> >	copy /etc/passwd to /mt33/user/test/etc/passwd
> >
> >	edit out the passwd for root
> >
> >	write a program that changes the root directory to
> >	/mnt23/user/test
> >	and then procedes to exec /bin/login
> 
> Wait a minute, now it's *my* turn to be missing something here.  *Which*
> /bin/login?  If the root directory is now actually /mnt23/user/test, then
> presumably we would be trying to execute /mnt23/user/test/bin/login, not
> the /bin/login that is setuid root and which is able to log a user in.
> 
> >	run the program and log in as the su.

I think the part that was missed was the link from /bin/login and/or /bin/su
to /mnt23/user/test/bin/login or /mnt23/user/test/bin/su.  This would work
only if /mnt23 was in the same file system as /bin.  The trick is to make
a suid to root program .

-- 
Darryl Wagoner	Raytheon Co.; Portsmouth RI; (401)-847-8000 x4089

best path             {allegra|gatech|mirror|raybed2}  -----\
next best             {linus|ihnp4|cci632} ------------------>!rayssd!dpw

campbell@maynard.UUCP (Larry Campbell) (10/04/86)

In article <1669@bucsd.bu-cs.BU.EDU> jdh@bucsd.UUCP (Jason Heirtzler) writes:

>Modifying the executable image of su(1), isn't necessary to create
>a loop hole. An unscrupulus user that could use chroot could put HIS
>copy of /etc/passwd in /mnt23/user/test/etc/passwd, and also make a
>hard link from /mnt23/user/test/bin/login to /bin/login; then execve(2)
>(the calling process would inherit the process's root directory)
>to (the link of) the login program...

>The point of all of this being that the fundamental reason chroot(2)
>can't be patched to allow everyone to use it is that hard links 
>(though not soft links) are the real cause of the security loop
>hole with chroot.

This only works if /bin and /mnt23/user/test/bin are on the same
filesystem.  Most of the systems I know put user files and /bin on
different filesystems.  It seems to me that if /mnt23, say, is on
a filesystem on which no suid programs exist, you're safe.
-- 
Larry Campbell                             The Boston Software Works, Inc.
ARPA: campbell%maynard.uucp@harvard.ARPA   120 Fulton Street, Boston MA 02109
UUCP: {alliant,wjh12}!maynard!campbell     (617) 367-6846

marcus@ihlpl.UUCP (Hall) (10/04/86)

In article <113@nonvon.UUCP>, apn@nonvon.UUCP (apn) writes:

> 	write a program that changes the root directory to /mnt23/user/test
> 	and then procedes to exec /bin/login

Which would really execute /mnt23/user/test/bin/login.  So what?

What you have to do is to find some writable directory in the same filesystem
as /bin.  If you find such a filesystem, it would be possible to create a
subdirectory, say /writable/dir/etc which contains a fake passwd file that
has a known password for root.  Then, create a hard link from /bin/login
to /writable/dir/login, chroot to /writable/dir, and execute /login which
is really /writable/dir/login, which is linked to /bin/login.  This would
let you log in as root, create a SUID shell in /writeable/dir/... .  Next,
get back to where you started (before the chroot), execute the SUID shell,
and there you go!

The best security in this case would to be sure that there are no writable
directories in the root filesystem, or for /bin/login to make sure that it
is SUID root and has only 1 link (I'm not sure if this could be gotten
around or not).

At any rate, programs on /usr (usually /usr/bin, /usr/local, etc.) have
problems because /usr/tmp and somewhere in /usr/spool is usually writable.

In BSD systems, where SUID shells work, explicitly specified paths for
commands would become questionable, which would present a real hazard.

Marcus Hall
..!ihnp4!ihlpl!marcus

guy@sun.uucp (Guy Harris) (10/05/86)

> As an aside, if /bin were not readable, no one could use PATH to find
> anything in it, not tooo cool, if you ask me...

To be precise, if "/bin" were searchable but not readable, no one *using the
C shell* could use PATH to find anything in it, presumably because "rehash"
scans the directories in the PATH; neither the Bourne shell nor the Korn
shell, whose similar hashing mechanisms add items to their tables only when
a command is actually run, have any problem.
-- 
	Guy Harris
	{ihnp4, decvax, seismo, decwrl, ...}!sun!guy
	guy@sun.com (or guy@sun.arpa)

mwm@cuuxb.UUCP (Marc W. Mengel) (10/06/86)

>In article <113@nonvon.UUCP>, apn@nonvon.UUCP (apn) writes:
>
>I believe that 'su' is the only problem.  Take away 'su' and you can give
>them 'chroot'.  ('newgrp' is similar but not as bad.)

Actually, you need to get rid of almost *every* setuid program on the
system; at least any one that exec's another program via an absolute
path name.  Let's say (hypothetically) that ps had a -s option that
sorted its listing by uid, and that to do that, it wrote its usual
output in /tmp, and ran sort on it.  Now create a new root, with a
/bin/sort that actually gives you a shell, rather than sorting a file.
Now you do a ps -s and get a shell.  Get the idea?  the holes are many,
and well hidden.

I'm not even sure that ones that don't exec another program are safe, that's
just the few I can think of.  Setuid programs are the classic place to find
security problems;  they are only as secure as their own logic, which often
assumes (and rightfully so) that "/" is the real filesystem root.  Giving
normal users chroot will make this assumption invalid, and you will probably
find security problems coming out of the woodwork for years to come if you
allow chroots with out careful thought.
-- 
 Marc Mengel
 ...!ihnp4!cuuxb!mwm

tony@nswitgould.OZ (Tony McGrath) (10/07/86)

In article <15879@ucbvax.BERKELEY.EDU>, ballou@brahms.BERKELEY.EDU (Kenneth R. Ballou) writes:
> Wait a minute, now it's *my* turn to be missing something here.  *Which*
> /bin/login?  If the root directory is now actually /mnt23/user/test, then
> presumably we would be trying to execute /mnt23/user/test/bin/login, not
> the /bin/login that is setuid root and which is able to log a user in.

This is essentially correct, however all is not quite as it seems.

Chroot changes the interpretation of what file paths starting with / will
actually refer to. This makes life interesting, to be sure.

If you chroot to /mnt23/user/test, then that becomes the root for your
program and for any of its children, and that includes execs. You cannot
chroot back to anything below /mnt23/user/test as you cannot reference a
file below the current root using a full pathname.

There is, however, one interesting feature of chroot. It doesn't change
your current working directory. Thus you can still access files relative
to the current working directory that your program had, either by chdir
before the chroot, or by inheriting from the shell.

Therefore the following scenario would be interesting.

1. Create a temporary directory (/mnt23/user/temp).

2. Create two sub-directories (/mnt23/user/temp/etc & /mnt23/user/temp/bin)

3. Create a dummy password file in /mnt23/user/temp/etc/passwd.

4. Copy over /bin/sh to /mnt23/user/temp/bin/sh (for login).

5. Create a program to chroot("/mnt23/user/temp") and 
   then execl("../../../bin/login", "login", 0).

6. Wait for the shell, and voila!, SuperUser!!!

This, however, doesn't seem to work on our system. Execl fails to start
login and the whole scenario fails spectacularly.

I tried some other chroot programs. I put a copy of ls and sh in my home
directory and then ran a chroot program to exec sh. The shell
starts in my home directory, as ls will verify (the chroot was into
/tmp) and it is possible to ls into .., ../.. etc. It is also possible
to run programs relative from my home directory. Once a chdir is done
there is no turning back, as it appears (from the shell) to go to the
root directory (/tmp).

One experiment that did work was the following:

1. Create /mnt23/user/temp and other files as in 1..4 above.

2. Copy /bin/sh into /mnt23/user/sh and cd there.

3. Compile a program that does
	a. chroot("/mnt23/user/temp");
	b. execl("sh", "sh", 0);

   This gives you a shell in /mnt23/user, rooted in /mnt23/user/temp.

4. Try ../../bin/login.

   This starts login, rooted in /mnt23/user/temp, using the file
   /mnt23/user/temp/etc/passwd as its /etc/passwd and likewise
   using /mnt23/user/temp/bin/sh as /bin/sh.

5. You are now the SuperUser, TRAPPED IN /mnt23/user/temp!!!

6. If you are clever, you would have stolen chown and chmod before
   you started this little escapade, but we all learn from our mistakes :-)

It would be fairly easy to abuse chroot in this way, hence the requirement
for SuperUser privileges for use. Of course, to do any of above one
needs to be the SuperUser ;-)

However, chroot can be useful, and the relative addressing will stop
at the chroot'ed directory once you do a chdir. I have used this as
the basis of a security area for our student population. It is wasteful
in terms of file space and system resources (as /bin/sh and /student/bin/sh
are seen to be different programs by 4.2BSD's text sharing), but it
effectively limits students to their own universe. (Now if I could only
find a way to stop them from getting access to staff logins ... :-)

Tony McGrath
New South Wales Institute of Technology

ACSnet: tony@nswitgould.oz
UUCP:	...!seismo!munnari!nswitgould!tony  (I think!)

I can't think of anything to say!

stevesu@copper.UUCP (10/09/86)

In article <358@maynard.UUCP>, campbell@maynard.UUCP (Larry Campbell) writes:
> It seems to me that if /mnt23, say, is on
> a filesystem on which no suid programs exist, you're safe.

Disclaimer: I am about to make sweeping generalities.
Nit-pickers sign off now.

"There is no such thing as a small change to a large system."
Unix is a large system; it is virtually impossible to correctly
predict all of the ramifications which might ensue from making a
fundamental change, such as making chroot() world-executable.

This is because, over time, any number of assumptions may have
been made based on the system's behavior at the time (in this
case, the fact that chroot has historically required root
privilege).  Many of the assumptions are implicit; nobody
realized that they were depending on something; things happened
to work, so nobody worried about it.

Let me illustrate with a simple example:  chown() is also only
executable by root.  The man page explains that this is
"because if users were able to give files away, they could defeat
the file-space accounting procedures."  (Actually, it said this
even before there were file-space accounting procedures.)
The implication is that if you don't care about file-space
accounting, it's safe to allow anyone to invoke chown().  WRONG!
The file-space accounting problem may have been the only problem
with giving files away the day chroot() was conceived, but over
the years, other reasons have developed.  For instance, if your
version of Unix lets me give files away (and there are versions
of Unix that do) but additional security precautions haven't been
added to the _a_t command, I can break security in a hurry.

A similar problem exists with respect to a kernel change which
doesn't even appear at first to concern security: symbolic links.
I won't go into the details, because the hole I'm thinking of
exists in many versions of Unix today ("fixed in 4.3").

If someone claims that a proposed major change is safe, don't
believe him.  If he claims that it's safe "with these
restrictions," or "as long as you also do this," believe him even
less -- where there's one exception, there's bound to be another
one (or another ten) that you haven't thought of yet.

Security on Unix is a particularly hard problem because trying to
prove that Unix is secure is like trying to prove that all crows
are black.  To prove that Unix is safe, you have to inspect every
setuid program, every directory directly or indirectly containing
programs ever exec'ed by root, every... (the list goes on and on).
The hacker has it much easier: to prove that Unix isn't secure, he
only has to find one loophole (like finding one purple crow).

Once (you think) you've proved Unix secure, if you make even one
little change anywhere near a security feature, you have to go
through the entire proof again, and there are probably more
setuid programs than there were last time.  What's "anywhere near
a security feature"?  Unfortunately, that's hard to pin down.
Any system call that says it's only executable by root is
obviously suspect, but (as the symbolic link issue points out)
the list doesn't end there.

                                         Steve Summit
                                         tektronix!copper!stevesu

jrw@hropus.UUCP (Jim Webb) (10/09/86)

> There is, however, one interesting feature of chroot. It doesn't change
> your current working directory. Thus you can still access files relative
> to the current working directory that your program had, either by chdir
> before the chroot, or by inheriting from the shell.

True, which is why the chroot command does a chdir() to the new root.  Why,
for you could still use .., right?  Wrong.  The kernel interprets .. in the
root directory as the root directory itself, so, for an example, ls -l /..
-- 
Jim Webb             "Out of phase--get help"          ...!ihnp4!hropus!jrw