Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 22 Jul 2003 13:14:39 -0600 (CST)
From:      Ryan Thompson <ryan@sasknow.com>
To:        "Gerald S. Stoller" <gs_stoller@hotmail.com>
Cc:        FreeBSD Questions <freebsd-questions@freebsd.org>
Subject:   Re: set user-id
Message-ID:  <20030722123627.A21583-100000@ren.sasknow.com>
In-Reply-To: <Sea1-F1124yp8ARf3sl0001b188@hotmail.com>

next in thread | previous in thread | raw e-mail | index | archive | help

[ Please CC questions@FreeBSD.org (or "Reply to All") when replying ]

Gerald S. Stoller wrote to ryan@sasknow.com:

> >Please give complete examples. As posted, your example wouldn't run
> >without invoking sh(1) first. I'm assuming it was something like:
> >
> >     #!/bin/sh
> >     echo $USER | tee xx
>
>       You're right, sorry, I had  '#!/bin/ksh' as the first line.

Yep. Interpreted script.

> > >             How do I get set user-id to work?
>
> > Your permissions are fine, but you're hitting a more subtle problem:
> > S*id bits don't work for interpreted scripts (denoted by the
> > shebang, #!), by design. If you'd compiled the equivalent example to
> > a binary, I'd expect it to work as you intended.

> Now that you mention it, I recall finding this condition on  HP-UX
> (Hewlett-Packard Unix) where I got around it by making a small
> compiled program that invoked the script.

Well, why don't you just chmod 4755 /bin/ksh, then. :-D

> Anyway, it should be in the man pages of chmod and maybe someplace
> else.  Since it is so easy to get around, why  bother with this
> restriction?  Presume that the person who wrote the script knows what
> he is doing and don't put in special cases!!!

The main reason is you don't actually "execute" a script. If you type in
/path/to/script, the OS first ensures that you have execute permission.
If so, it checks the magic number of the file (first two bytes), which
determine the executable type. If the magic number is a "shebang" (#!),
execve(2) actually execve's the interpreter, with your script as an
argument.

Suppose you have a script executed with "./foo" with #!/bin/ksh as the
interpreter.  It'll be executed just as if you'd run /bin/ksh ./foo
Now you can see why the s*id bits on scripts don't mean anything.

It *would* be possible to alter this behaviour at the OS level, and,
although I haven't looked in a while, it would probably be a relatively
trivial change. That, combined with the fact that this is a FAQ,
suggests that there are good reasons why this "feature" hasn't been
adopted. (And FreeBSD isn't alone, either :-)

Namely, if the shell script allows for any interactive escapes, the
caller has an interactive root shell. Also, shell scripts are
particularly vulnerable to PATH modifications, if not set explicitly in
the script. There are other challenges, too. These are by no means
impossible to work around, but there are almost always stronger
solutions, in my opinion. Shells have a lot of hidden complexity, in
order to allow you to make simple scripts. I can think of one time in
the last eight or ten years that I've been tempted to make a setuid
script. I came to my senses quickly. :-)

If you *really* want to have suid scripts, your binary wrapper idea is
quite a common trick. Don't get fancy with it, though. A one-liner to
execve(2) should really be all you need. Either that, or re-code the
whole thing in C (or some other compiled language). C can introduce
insecurities of its own, but at least you'd (arguably) have put them
there yourself. :-)

- Ryan

-- 
  Ryan Thompson <ryan@sasknow.com>

  SaskNow Technologies - http://www.sasknow.com
  901-1st Avenue North - Saskatoon, SK - S7K 1Y4

        Tel: 306-664-3600   Fax: 306-244-7037   Saskatoon
  Toll-Free: 877-727-5669     (877-SASKNOW)     North America



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