old-www/LDP/LG/issue67/tag/20.html

433 lines
17 KiB
HTML

<!--startcut ======================================================= -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
<html>
<head>
<META NAME="generator" CONTENT="lgazmail v1.3E.u">
<TITLE>The Answer Gang 67: RE: set userid bit question</TITLE>
</HEAD><BODY BGCOLOR="#FFFFFF" TEXT="#000000"
LINK="#3366FF" VLINK="#A000A0">
<!-- ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: -->
<P> <hr>
<CENTER>
<!-- *** BEGIN navbar *** -->
<!-- *** END navbar *** -->
</CENTER>
</p>
<P> <hr> <P>
<!-- begin tagnav ::::::::::::::::::::::::::::::::::::::::::::::::::-->
<p align="center">
<table width="100%" border="0"><tr>
<td align="right" valign="center"
><IMG ALT="" SRC="../../gx/navbar/left.jpg"
WIDTH="14" HEIGHT="45" BORDER="0" ALIGN="middle" border="0"
><A HREF="..//"
><IMG SRC="../../gx/navbar/toc.jpg" align="middle"
ALT="[ Table Of Contents ]" border="0"></A
><A HREF="../lg_answer67.html"
><IMG SRC="../../gx/dennis/answertoc.jpg" align="middle"
ALT="[ Answer Guy Current Index ]" border="0"></A></td>
<td align="center" valign="center"><A HREF="../lg_answer67.html#greeting"><img align="middle"
src="../../gx/dennis/smily.gif" alt="greetings" border="0"></A> &nbsp;
<A HREF="bios.html">bios</A> &nbsp;
<A HREF="1.html">1</A> &nbsp;
<A HREF="2.html">2</A> &nbsp;
<A HREF="3.html">3</A> &nbsp;
<A HREF="4.html">4</A> &nbsp;
<A HREF="5.html">5</A> &nbsp;
<A HREF="6.html">6</A> &nbsp;
<A HREF="7.html">7</A> &nbsp;
<A HREF="8.html">8</A> &nbsp;
<A HREF="9.html">9</A> &nbsp;
<A HREF="10.html">10</A> &nbsp;
<A HREF="12.html">12</A> &nbsp;
<A HREF="13.html">13</A> &nbsp;
<A HREF="14.html">14</A> &nbsp;
<A HREF="15.html">15</A> &nbsp;
<A HREF="16.html">16</A> &nbsp;
<A HREF="17.html">17</A> &nbsp;
<A HREF="18.html">18</A> &nbsp;
<A HREF="19.html">19</A> &nbsp;
<A HREF="20.html">20</A>
</td>
<td align="left" valign="center"><A HREF="../../tag/kb.html"
><IMG SRC="../../gx/dennis/answerpast.jpg" align="middle"
ALT="[ Index of Past Answers ]" border="0"></A
><IMG ALT="" SRC="../../gx/navbar/right.jpg" align="middle"
WIDTH="14" HEIGHT="45" BORDER="0"></td></tr></table>
</p>
<!-- end tagnav ::::::::::::::::::::::::::::::::::::::::::::::::::::-->
<!-- ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: -->
<center>
<H1><A NAME="answer">
<img src="../../gx/dennis/qbubble.gif" alt="(?)"
border="0" align="middle">
<font color="#B03060">The Answer Gang</font>
<img src="../../gx/dennis/bbubble.gif" alt="(!)"
border="0" align="middle">
</A></H1>
<BR>
<H4>By Jim Dennis, Ben Okopnik, Dan Wilder, Breen, Chris, and the Gang,
the Editors of Linux Gazette...
and You!
<br>Send questions (or interesting answers) to
<a href="mailto:linux-questions-only@ssc.com">linux-questions-only@ssc.com</a>
</H4>
<p><em><font color="#990000">There is no guarantee that your questions
here will <b>ever</b> be answered. You can be published anonymously
- just let us know!
</font></em></p>
</center>
<p><hr><p>
<!-- endcut ======================================================= -->
<!-- begin 20 -->
<H3 align="left"><img src="../../gx/dennis/qbubble.gif"
height="50" width="60" alt="(?) " border="0"
>Operation Not Permitted on SUID Program</H3>
<p><strong>From
Dann S. Washko
</strong></p>
<p align="right"><strong>Answered By
Karl-Heinz Herrmann, Jim Dennis
<br></strong></p>
<!-- sig -->
<P><STRONG>
The permissions on a file like <TT>/usr/X11R6/bin/xterm</TT> are: rws--x--x which
means the userid bit is set on execution so the process runs as root.
</STRONG></P>
<BLOCKQUOTE><IMG SRC="../../gx/dennis/bbub.gif" ALT="(!)"
HEIGHT="28" WIDTH="50" BORDER="0"
> [K.H.]
That's a C program which needs no interpreter anymore
</BLOCKQUOTE>
<BLOCKQUOTE><IMG SRC="../../gx/dennis/bbub.gif" ALT="(!)"
HEIGHT="28" WIDTH="50" BORDER="0"
> [JimD]
<br>You can write a very simple C wrapper program like:
</BLOCKQuote>
<p> *** WARNING, THIS SCRIPT HAS RISKY BUGS *** </p>
<blockquote><pre>#include &lt;unistd.h&gt;
int main (int argc, char ** argv) {
int err;
char *newenv[] = { NULL };
if ((err = execle("/usr/bin/pauseme", "pauseme", NULL, newenv)) &lt; 0 ) {
exit(err);
}
return 0; // never reached!
}
</pre></blockquote>
<p> *** risky *** risky *** risky *** risky *** risky *** </p>
<BLOCKQUOTE>
This uses one of the <tt>exec*()</tt> family of system calls, specifically the
"varargs" forms with a pointer to a new environment. We don't use
the <TT>system()</TT> or <TT>popen()</TT> library calls and we don't use any of the
forms of exec*() that search the path nor those that retain the
user's environment. These are all potentially exploitable bugs for
SUID programs. So we have to use <TT>execve()</TT> or <TT>execle()</TT> to be reasonably
secure. Additionally, I <EM>should</EM> have written a loop like:
</BLOCKQUOTE>
<blockquote><pre>{ int x; for (x = 0; x &lt; 255; x++) close(x); }
</pre></blockquote>
<BLOCKQUOTE>
To explicitly close all of my non-standard file descriptors
(there are some exploits possible when <TT>exec()</TT>'ing programs with
additional open files, becuase those persist through the system call).
</BLOCKQUOTE>
<BLOCKQUOTE>
Then I have to explicitly re-open the files or devices that I want my
program to use.
</BLOCKQUOTE>
<BLOCKQUOTE>
These and, alot of other considerations depend on the exact program
that is being invoked. For example, if your "pauseme" program
might have vulnerable signal handling, than your wrapper program might
have to do a <TT>setsid()</TT> and a <TT>fork()</TT> to detach signal propagation from
the user's shell's process group.
</BLOCKQUOTE>
<BLOCKQUOTE>
Most importantly you'll have to do your own parsing and validation
of any variable arguments and options that you want to allow the user
of your script to set. If those involve filenames, you'll have to
check those for access under the real UID (as opposed to the "effective"
UID which is set by the ownership of the wrapper binary). File paths
where <EM>any</EM> component of the patch is writable by a potentially hostile
user are subject to race conditions if you attempt to check the
ownership and permissions prior to opening it. (Generally you have to
perform go through an <TT> lstat()</TT>, save the device/inode pair, then
do your <TT> open()</TT> and use the <TT> fstat()</TT>, compare its device/inode the the
one you stored, and then perform your permissions and ownership checks).
</BLOCKQUOTE>
<BLOCKQUOTE>
In other words, there are many "gotchyas" to writing C wrappers.
Writing robust, non-exploitable C is difficult and there are whole
books on the topic.
</BLOCKQUOTE>
<P><STRONG><IMG SRC="../../gx/dennis/qbub.gif" ALT="(?)"
HEIGHT="28" WIDTH="50" BORDER="0"
>
Why is it then, if I create a script:
</STRONG></P>
<Pre><STRONG>
#!/bin/bash
pauseme
</STRONG></Pre>
<P><STRONG>
and give it the same permissions: <tt>rws--x--x</tt>
</STRONG></P>
<P><STRONG>
I get an error that the operation is not allowed if I try to execute the
file as a non-superuser?
</STRONG></P>
<BLOCKQUOTE><IMG SRC="../../gx/dennis/bbub.gif" ALT="(!)"
HEIGHT="28" WIDTH="50" BORDER="0"
> [K.H.]
When I ran into this I didn't get an error message -- the SUID bit was
simply
ignored, but anyway:
</BLOCKQUOTE>
<BLOCKQUOTE><BLOCKQuote>
A shell script needs an interpreter. Since your <TT>/usr/bin/bash</TT> or whatever
is
most probably non SUID root it refuses (or simply can't change to SUID
root)
to run a script in SUID root. You as User are effectively running
<TT>/usr/bin/bash</TT> on the script. So if <TT>/usr/bin/bash</TT> is not SUID it will run
with
your permissions and can't change to any other user.
</BLOCKQuote></BLOCKQUOTE>
<BLOCKQUOTE>
It seems most *NIX OS'es share the opinion that shell scripts are that
unsafe
that they can't be allowed to run as SUID root, so simply setting SUID
on the
script won't be enough. It's even recommended that <TT>/bin/true</TT> (or
<TT>/bin/false</TT>)
be not shell scripts with "exit(0)" but instead little compiled C programs.
</BLOCKQUOTE>
<BLOCKQUOTE><IMG SRC="../../gx/dennis/bbub.gif" ALT="(!)"
HEIGHT="28" WIDTH="50" BORDER="0"
> [JimD]
The SUID bit is ignored on shell scripts (and other #! text files)
under Linux and on many other versions of UNIX. Historically this
was due to an inherent race condition the way that the interpreter
was executed and the shell script was subsequently opened. (I think
newer versions of the Linux kernel have eliminated that race condition).
</BLOCKQUOTE>
<BLOCKQUOTE>
It is widely considered to be almost impossible to write a sufficiently
robust shell script that it could be trusted to run SUID. Therefore the
kernel's policy of ignoring the SUID/SGID bits persists.
</BLOCKQUOTE>
<BLOCKQUOTE><IMG SRC="../../gx/dennis/bbub.gif" ALT="(!)"
HEIGHT="28" WIDTH="50" BORDER="0"
> [K.H.]
I don't think there is a simple walkaround for this with bash and friends.
</BLOCKQUOTE>
<BLOCKQUOTE><IMG SRC="../../gx/dennis/bbub.gif" ALT="(!)"
HEIGHT="28" WIDTH="50" BORDER="0"
> [JimD]
Well, you <em>could</em> install sudo - I think it's by far the easiest
of our solutiions here, and probably is the most robust and secure for your
needs. It's included with most Linux distributions
and available from any good package archive. You can read about
sudo at its home page: <A HREF="http://www.courtesan.com/sudo"
>http://www.courtesan.com/sudo</A>
</BLOCKQUOTE>
<BLOCKQUOTE>
You'd install sudo, and configure it to run your command
by using the 'visudo' command to edit the <TT>/etc/sudoers</TT> file. You could
optionally specify the NOPASSWD option to allow a user or group of
users to unconditionally access a command without needing to supply
<EM>their</EM> password. sudo has been used by lots of sysadmins (it's more
popular than any similar package like super or calife) for many years.
There have been no critical bugs posted for it to my memory and only a
couple of minor bugs (affecting uncommon configurations).
</BLOCKQUOTE>
<BLOCKQUOTE>
Here's a sample sudoers file:
</BLOCKQUOTE>
<blockquote><pre># sudoers file.
# This file MUST be edited with the 'visudo' command as root.
# See the man page for details on how to write a sudoers file.
Defaults shell_noargs, set_home
%staff ALL=NOPASSWD:/bin/vi /etc/motd
</pre></blockquote>
<BLOCKQUOTE>
In this example members of the "staff" group on "ALL" systems
to which we distribute this sudoers file, can use vi to edit the
<TT>/etc/motd</TT> (Message Of The Day) file, without using their password.
</BLOCKQUOTE>
<BLOCKQUOTE>
The thing that I always get into trouble with, when I'm making new
sudoers entries is that part of about specifying which hosts this
entry applies to. Normally I use use ALL=, since I tend to have
quite limited sudoers lists, and therefore I have homogenous user/privilege
matrices. NOTE: sudo isn't actually doing anything over the network,
it isn't a remote access client/server or anything like that. This
"host specification" feature of their sudoers file is purely to allow
an admin to maintain one sudoers file and to distribute it (via some
reasonably secure means, such as rsync over ssh) to all of their hosts.
</BLOCKQUOTE>
<BLOCKQUOTE>
If I were specifying hostnames or netgroups here, then the copy of
sudo that I ran on mars.starshine.org would filter out all of the
sudoer entries that didn't apply to mars.starshine.org and only
consider giving me access to the commands that applied to my
combination of user/group and host/netgroup.
</BLOCKQUOTE>
<BLOCKQUOTE>
The one disadvantage of using sudo is that your users have to
remember to run "sudo ..." as part of their command. However,
that's easy to work around by simply creating a wrapper shell
script. This is a normal (non-SUID) shell script that simply does
something like:
</BLOCKQUOTE>
<blockquote><pre>#!/bin/sh
exec /usr/bin/sudo /some/path/to/our/target/prog "$@"
</pre></blockquote>
<BLOCKQUOTE>
(execute sudo, on the target program and pass our argument,
preserving any quoting as we specified it).
</BLOCKQUOTE>
<BLOCKQUOTE><IMG SRC="../../gx/dennis/bbub.gif" ALT="(!)"
HEIGHT="28" WIDTH="50" BORDER="0"
> [K.H.]
In perl it's handled by a special perl-version which has restricted
possibilities and will run scripts SUID root (see also "perl -T" Tainted
mode).
</BLOCKQUOTE>
<BLOCKQUOTE><IMG SRC="../../gx/dennis/bbub.gif" ALT="(!)"
HEIGHT="28" WIDTH="50" BORDER="0"
> [JimD]
You can write a wrapper in Perl too. Perl is a scripting
language, so it is subject to the same limitation as the shell. The
kernel will not grant a perl process the effective UID of the owner of
the SUID script file. However, the Perl interpreter checks the
permissions itself, and can re-execute the open shell script using the
optionally installed sperl (SUID Perl) wrapper/utility.
</BLOCKQUOTE>
<BLOCKQUOTE>
When sperl interprets a script, it performs many sanity checks.
That makes it somewhat easier to write robust SUID perl scripts than
SUID C wrappers. (Note, however, that sperl itself has had
vulnerabilities; so questions of whether to install it on your
system and which group(s) of users should be given access to the
sperl binar(y|ies) do arise). There is a perlsec man page which
focuses on the pitfalls and suggestions for writing robust Perl
code.
</BLOCKQUOTE>
<BLOCKQUOTE>
You can read more than you want to know about secure programming
for Linux and UNIX FAQs and HOWTOs at:
</BLOCKQUOTE>
<BLOCKQUOTE><DL><DT>
Shmoo's Security Links:
<DD><A HREF="http://www.shmoo.com/securecode"
>http://www.shmoo.com/securecode</A>
</DL></BLOCKQUOTE>
<BLOCKQUOTE><DL><DT>
Secure Programming for Linux and Unix HOWTO
<DD><A HREF="http://www.linuxdoc.org/HOWTO/Secure-Programs-HOWTO/index.html"
>http://www.linuxdoc.org/HOWTO/Secure-Programs-HOWTO/index.html</A>
</DL></BLOCKQUOTE>
<BLOCKQUOTE><DL><DT>
Avoiding Security Holes when Developing an Application:
<DD><A HREF="http://www.linuxfocus.org/English/January2001/article182.meta.shtml"
>http://www.linuxfocus.org/English/January2001/article182.meta.shtml</A>
</DL></BLOCKQUOTE>
<BLOCKQUOTE>
... and many others.
</BLOCKQUOTE>
<BLOCKQUOTE><IMG SRC="../../gx/dennis/bbub.gif" ALT="(!)"
HEIGHT="28" WIDTH="50" BORDER="0"
> [K.H.]
If anyone knows one or has details on where the high security risc comes in
with scripts (lets assume one which doesn't use any commandline arguments)
I'm alos quite interested.
</BLOCKQUOTE>
<!-- end 20 -->
<!--startcut ======================================================= -->
<P> <hr> </p>
<!-- *** BEGIN copyright *** -->
<H5 align="center">This page edited and maintained by the Editors
of <I>Linux Gazette</I>
<a href="http://www.linuxgazette.com/copying.html"
>Copyright &copy;</a> 2001
<BR>Published in issue 67 of <I>Linux Gazette</I> June 2001</H5>
<H6 ALIGN="center">HTML script maintained by
<A HREF="mailto:star@starshine.org">Heather Stern</a> of
Starshine Technical Services,
<A HREF="http://www.starshine.org/">http://www.starshine.org/</A>
</H6>
<!-- *** END copyright *** -->
<P> <hr>
<!-- begin tagnav ::::::::::::::::::::::::::::::::::::::::::::::::::-->
<p align="center">
<table width="100%" border="0"><tr>
<td align="right" valign="center"
><IMG ALT="" SRC="../../gx/navbar/left.jpg"
WIDTH="14" HEIGHT="45" BORDER="0" ALIGN="middle" border="0"
><A HREF="..//"
><IMG SRC="../../gx/navbar/toc.jpg" align="middle"
ALT="[ Table Of Contents ]" border="0"></A
><A HREF="../lg_answer67.html"
><IMG SRC="../../gx/dennis/answertoc.jpg" align="middle"
ALT="[ Answer Guy Current Index ]" border="0"></A></td>
<td align="center" valign="center"><A HREF="../lg_answer67.html#greeting"><img align="middle"
src="../../gx/dennis/smily.gif" alt="greetings" border="0"></A> &nbsp;
<A HREF="bios.html">bios</A> &nbsp;
<A HREF="1.html">1</A> &nbsp;
<A HREF="2.html">2</A> &nbsp;
<A HREF="3.html">3</A> &nbsp;
<A HREF="4.html">4</A> &nbsp;
<A HREF="5.html">5</A> &nbsp;
<A HREF="6.html">6</A> &nbsp;
<A HREF="7.html">7</A> &nbsp;
<A HREF="8.html">8</A> &nbsp;
<A HREF="9.html">9</A> &nbsp;
<A HREF="10.html">10</A> &nbsp;
<A HREF="12.html">12</A> &nbsp;
<A HREF="13.html">13</A> &nbsp;
<A HREF="14.html">14</A> &nbsp;
<A HREF="15.html">15</A> &nbsp;
<A HREF="16.html">16</A> &nbsp;
<A HREF="17.html">17</A> &nbsp;
<A HREF="18.html">18</A> &nbsp;
<A HREF="19.html">19</A> &nbsp;
<A HREF="20.html">20</A>
</td>
<td align="left" valign="center"><A HREF="../../tag/kb.html"
><IMG SRC="../../gx/dennis/answerpast.jpg" align="middle"
ALT="[ Index of Past Answers ]" border="0"></A
><IMG ALT="" SRC="../../gx/navbar/right.jpg" align="middle"
WIDTH="14" HEIGHT="45" BORDER="0"></td></tr></table>
</p>
<!-- end tagnav ::::::::::::::::::::::::::::::::::::::::::::::::::::-->
<P> <hr>
<CENTER>
<!-- *** BEGIN navbar *** -->
<!-- *** END navbar *** -->
</CENTER>
</p>
<!-- ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: -->
</BODY></HTML>
<!--endcut ========================================================= -->