433 lines
17 KiB
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>
|
|
<A HREF="bios.html">bios</A>
|
|
<A HREF="1.html">1</A>
|
|
<A HREF="2.html">2</A>
|
|
<A HREF="3.html">3</A>
|
|
<A HREF="4.html">4</A>
|
|
<A HREF="5.html">5</A>
|
|
<A HREF="6.html">6</A>
|
|
<A HREF="7.html">7</A>
|
|
<A HREF="8.html">8</A>
|
|
<A HREF="9.html">9</A>
|
|
<A HREF="10.html">10</A>
|
|
<A HREF="12.html">12</A>
|
|
<A HREF="13.html">13</A>
|
|
<A HREF="14.html">14</A>
|
|
<A HREF="15.html">15</A>
|
|
<A HREF="16.html">16</A>
|
|
<A HREF="17.html">17</A>
|
|
<A HREF="18.html">18</A>
|
|
<A HREF="19.html">19</A>
|
|
<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 <unistd.h>
|
|
int main (int argc, char ** argv) {
|
|
|
|
int err;
|
|
char *newenv[] = { NULL };
|
|
|
|
if ((err = execle("/usr/bin/pauseme", "pauseme", NULL, newenv)) < 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 < 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 ©</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>
|
|
<A HREF="bios.html">bios</A>
|
|
<A HREF="1.html">1</A>
|
|
<A HREF="2.html">2</A>
|
|
<A HREF="3.html">3</A>
|
|
<A HREF="4.html">4</A>
|
|
<A HREF="5.html">5</A>
|
|
<A HREF="6.html">6</A>
|
|
<A HREF="7.html">7</A>
|
|
<A HREF="8.html">8</A>
|
|
<A HREF="9.html">9</A>
|
|
<A HREF="10.html">10</A>
|
|
<A HREF="12.html">12</A>
|
|
<A HREF="13.html">13</A>
|
|
<A HREF="14.html">14</A>
|
|
<A HREF="15.html">15</A>
|
|
<A HREF="16.html">16</A>
|
|
<A HREF="17.html">17</A>
|
|
<A HREF="18.html">18</A>
|
|
<A HREF="19.html">19</A>
|
|
<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 ========================================================= -->
|