[comp.bugs.sys5] A security hole + FIX

mikpe@senilix.liu.se (Mikael Pettersson) (03/25/88)

In article <175@pcsbst.UUCP> jh@pcsbst.UUCP (Johannes Heuft) writes:
>In article <892@cosmo.UUCP> jum@cosmo.UUCP (Jens-Uwe Mager(sysop))
>reveals the IFS trick.
> ...
>Does somebody care to comment or add to the list??

The IFS stuff can be dealt with by patching the shell. Those with source
could easily add a putenv("IFS= \t\n") (or something equivalent) in some
convenient place to stop the shell from inheriting IFS.

If you don't have source, you could do what I did on a SVR2(-like) machine
I'm administrating. Write a small program that simply does:
		putenv("IFS= \t\n");
		execv("/bin/.real-sh", argv);
and call it /bin/sh. (you mv'd /bin/sh to /bin/.real-sh before of course!).
This works Ok on my machine. Does anybody know of any reasons why somehting
like this shouldn't be done?

>The IFS problem is fixed in SVR3.

How?
-- 
Mikael Pettersson           ! Internet:mpe@ida.liu.se
Dept of Comp & Info Science ! UUCP:    mpe@liuida.uucp  -or-
University of Linkoping     !          {mcvax,munnari,uunet}!enea!liuida!mpe
Sweden                      ! ARPA:    mpe%ida.liu.se@uunet.uu.net

nevin1@ihlpf.ATT.COM (00704a-Liber) (03/31/88)

In article <766@senilix.liu.se> mikpe@senilix.liu.se (Mikael Pettersson) writes:

>If you don't have source, you could do what I did on a SVR2(-like) machine
>I'm administrating. Write a small program that simply does:
>		putenv("IFS= \t\n");
>		execv("/bin/.real-sh", argv);
>and call it /bin/sh. (you mv'd /bin/sh to /bin/.real-sh before of course!).
>This works Ok on my machine. Does anybody know of any reasons why somehting
>like this shouldn't be done?

This doesn't fix the problem.  What stops me, Joe User, from doing an

$ exec /bin/.real-sh

and bypassing your /bin/sh program??


I was thinking that if you did a setuid/setgid on the new /bin/sh, this
might be able to fix the problem.  But the only solution that I have
thought of (so far) won't work.

What I thought of doing is changing the file attributes to the following:

---x--s--x	bin	sh		sh
---x--x---	bin	sh		.real-sh

but the problem is that Joe User (uid=foo, gid=bar) would be running
.real-sh as egid=sh, not as egid=bar.  The only way that I can think of
that would fix this problem would be to modify the source of .real-sh, but
then we wouldn't need the front end to the shell in the first place.
-- 
 _ __			NEVIN J. LIBER	..!ihnp4!ihlpf!nevin1	(312) 510-6194
' )  )				"The secret compartment of my ring I fill
 /  / _ , __o  ____		 with an Underdog super-energy pill."
/  (_</_\/ <__/ / <_	These are solely MY opinions, not AT&T's, blah blah blah

mikpe@senilix.liu.se (Mikael Pettersson) (04/02/88)

In article <4210@ihlpf.ATT.COM> nevin1@ihlpf.UUCP (00704a-Liber,N.J.) writes:
>In article <766@senilix.liu.se> mikpe@senilix.liu.se (Mikael Pettersson) writes:
>
>>[ I argued that renaming /bin/sh to /bin/.real-sh and having /bin/sh be a
>>  small C program that resets IFS before exec'ing /bin/.real-sh could be
>>  a reasonable way to close down the IFS hole for non-source systems. ]
>
>This doesn't fix the problem.  What stops me, Joe User, from doing an
>
>$ exec /bin/.real-sh
>
>and bypassing your /bin/sh program??

Nothing, but that's not the problem here. The problem is the use of popen()
in set-uid programs. Ok, here's the full story:

Suppose Joe User executes /bin/mail or some other possibly set-uid program
that might need to communicate with a trusted subprocess. This subprocess
is often created with a call like popen("<full-path>/foo") with /bin or /usr
in <full-path>. To do this, popen() forks off an instance of /bin/sh(*)
giving it "<full-path>/foo" as an argument. The intention is to have the
shell(*) interpret IO-redirections and whatever shell meta-syntax we wish to
use for us. Now, suppose the malicious user had reset IFS to "/" and exported
it. This means that the shell(*) will inherit IFS="/". Now, it's easy to see
what happens: the shell(*) will strip out the /-es from <full-path>, leaving
the argument looking like "usr bin foo" instead of "/usr/bin/foo". If there
is a program called "usr" in Joe User's PATH *IT* will be executed with the
uid intended for the trusted program, i.e., Joe User is root.

How do we prevent this? We can't change popen() to reset IFS and recompile
all sources with our new C-library since most systems don't have source
to begin with. My fix will, I believe, stop all attempts to use *this* hole
with minimal changes to the system. You don't even have to wait for your
vendor to do it for you since all it takes is a small (<10 lines) C-program.
(One problem might be that not all systems have putenv() in libc.a. In those
 cases one has to improvise, but it's still just another trivial 3-4 lines.)

>I was thinking that if you did a setuid/setgid on the new /bin/sh, this
>might be able to fix the problem.

I don't think so, since then the set-uid program doing the popen() would
create a child with wrong uid, like uid=sh instead of uid=root.


> _ __			NEVIN J. LIBER	..!ihnp4!ihlpf!nevin1	(312) 510-6194
>' )  )				"The secret compartment of my ring I fill
> /  / _ , __o  ____		 with an Underdog super-energy pill."
>/  (_</_\/ <__/ / <_	These are solely MY opinions, not AT&T's, blah blah blah

-- 
Mikael Pettersson           ! Internet:mpe@ida.liu.se
Dept of Comp & Info Science ! UUCP:    mpe@liuida.uucp  -or-
University of Linkoping     !          {mcvax,munnari,uunet}!enea!liuida!mpe
Sweden                      ! ARPA:    mpe%ida.liu.se@uunet.uu.net