Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

setuid scripts wrapper (RFC, proposal)

1 view
Skip to first unread message

Sply Splyeff

unread,
Apr 5, 2006, 4:29:27 PM4/5/06
to
There are some security problems with kernel-level script
setuid execution which discourage from using it. The standard
recommendation is to write a binary setuid wrapper for
each script needed. But maybe it's better to use one simple,
well reviewed and verified setuid wrapper for all common tasks?
And to use it in the distribution or at least, as a package.

I've tried to set up the stanard wrapper for our systems
which does following:
- verifies if scipt's file system allowed to run setuid
scrits
- clears all environment variables, or pass only desired,
or set to values from hash-line in the script
- closes all file descriptros > 2 if -c options is set
- checks if script file is write permission for anyone

http://suidscript.sply.org/suidscript/suidscript.c
http://suidscript.sply.org/suidscript/suidscriptperl
http://suidscript.sply.org/suidscript/test_perl
http://suidscript.sply.org/

Is it strong enough? Maybe there is any slippery ground
left?
_______________________________________________
freebsd...@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
To unsubscribe, send any mail to "freebsd-hacke...@freebsd.org"

Peter Jeremy

unread,
Apr 6, 2006, 5:26:28 AM4/6/06
to
On Thu, 2006-Apr-06 00:29:27 +0400, Sply Splyeff wrote:
>There are some security problems with kernel-level script
>setuid execution which discourage from using it.

The biggest problem is a race condition between the kernel setting up
the set[gu]id() environment and opening the script to find the
interpreter and the interpreter opening the script to execute it.
This can only be fixed withing the kernel (by passing the script to
the interpreter as a pre-opened FD).

>Is it strong enough? Maybe there is any slippery ground
>left?

The biggest problem is its failure to check the sanity of the input
parameters - that a particular argument actually exists before
referencing it.

Other issues I noticed:
- strncpy() is virtually always the wrong function. You already do
validation so you could just use strcpy()
- strncpy(penvd + penvsz, "=", 1); could be penvd[penvsz] = '=';
- No error if number of environment variables too great.

--
Peter Jeremy

Sply Splyeff

unread,
Apr 6, 2006, 6:49:25 AM4/6/06
to
> The biggest problem is its failure to check the sanity of the input
> parameters - that a particular argument actually exists before
> referencing it.

Do you mean that evil Bob can substitue Alice's script between stat() and execve() calls?
Yes, I've missed this point.

We can use realpath and check if all nodes are writable only by file owner or by root.
Yes, that's a big limitation, but in most common tasks it would be acceptable. And it
saves from race conditions, am I right?

And there are another ways but more slowly or complex - own sub-wrapper for each
interpreter with passes script as file descriptor as you wrote at beginning; hardlink or
copy files to safe directory; fork child and ptrace him for watching if the files it
opens are really the same. Too confusing.

But if the first way is ok, maybe it'sbetter to stay on it.

> Other issues I noticed:
> - strncpy() is virtually always the wrong function. You already do
> validation so you could just use strcpy()

ok. i've replace to memcpy as len is already known

> - strncpy(penvd + penvsz, "=", 1); could be penvd[penvsz] = '=';

sure, it was done only for hold in one style all string operations

> - No error if number of environment variables too great.

fixed

Peter Jeremy

unread,
Apr 6, 2006, 3:00:04 PM4/6/06
to
On Thu, 2006-Apr-06 14:49:25 +0400, Sply Splyeff wrote:
>> The biggest problem is its failure to check the sanity of the input
>> parameters - that a particular argument actually exists before
>> referencing it.
>
>Do you mean that evil Bob can substitue Alice's script between stat() and execve() calls?
>Yes, I've missed this point.

Actually Bob can replace the script anytime between the initial statfs() call
in your script and the interpreter opening the script sometime after the
execve() call. You should be able to get around this by opening the script
first, using fstatfs() and fstat() and passing the script as /dev/fd/N to
the interpreter.

What I was actually referring to was your use of argv[1], argv[2], argv[3]
and argv[4] without checking argc or otherwise validating them.

--
Peter Jeremy

li...@sply.org

unread,
Apr 6, 2006, 3:40:15 PM4/6/06
to
> You should be able to get around this by opening the script
> first, using fstatfs() and fstat() and passing the script as /dev/fd/N to
> the interpreter.

Great idea. Thank you very much.


> What I was actually referring to was your use of argv[1], argv[2], argv[3]
> and argv[4] without checking argc or otherwise validating them.

Oops, I did it.

Sply Splyeff

unread,
Apr 11, 2006, 11:18:43 AM4/11/06
to
I've uploaded suidscript.c with updates:
http://suidscript.sply.org/suidscript/suidscript.c
http://suidscript.sply.org/suidscript.tgz

Current implementation checks the safety of an interpreter path and of a script path - all nodes required to be owned by root or script owner and writable only by owner. It's a big limitation, but it works in most cases.

I've tried /dev/fd/ way, but it requires fdescfs mounted which is not common for different freebsd versions and sometimes seems a little buggy. I've included suidscript_fdesc.c which implements /dev/fd/*, but I haven't evere tested it because mount_fdescfs crashes.

0 new messages