A short tutorial on setuid/setgid file permissions

http://neworder.box.sk/newsread.php?newsid=2380     

I was writing a scanner to catalog setuid/setgid binaries and when I ran into trouble, I found 
a lack of information about set(u/g)id bits around. I think most *nix newbies will find the same 
lack of information, even in most file permission texts. This is a fairly important topic, 
because some distros are filled with negative permissions that you will need to fix. Hopefully 
after you read this you'll fully understand the positives and negatives of setuid.

Setuid and setgid permissions are useful on binary files. They allow the program to with
the file owner's permissions. This ordinary file for instance:

[root@localhost setuid]# ls -l nmap
-rwxrwxr-x 1 root root 223036 Jan 2 15:30   nmap
[root@localhost setuid]# file nmap
nmap: ELF 32-bit LSB executable, Intel 80386, version 1, dynamically linked (uses
shared libs), stripped

Most linux users should be famlliar with nmap. A standard user can't use most of the
advanced options, as they require nmap to have root privlidges. So we don't screw up
any old permissions make a copy of the nmap binary. Issue these commands as root:

cp /usr/bin/nmap ~/uidnmap
chmod 4776 ~/uidnmap

The chmod set the setuid bit on the file. Now the permissions should look something like this:

# ls -l nmap
-rwsrwxr-x 1 root root 223036 Jan 2 15:30   nmap
# file nmap
nmap: setuid ELF 32-bit LSB executable, Intel 80386, version 1, dynamically linked (uses
shared libs), stripped

Notice the s in executable permission slot now. This copy of nmap will allow normal users to
perform the 90% of nmap functions that require root. If there is a buffer overflow in nmap,
it will also allow ordinary users to be able to execute whatever code they can imagine, as
root. Which is why I recommend you DON'T set the setuid bit for convenience. But try it 
out, know what it does. Here is a full list of the permissions that can be set.

---s--s--t 7000 setuid, setgid, sticky 
---s--s--- 6000 setuid, setgid
---s-----t 5000 setuid, sticky
---s------ 4000 setuid
------s--t 3000 setgid, sticky
---s------ 2000 setgid
---------t 1000 sticky
---------- 0000 none

So to set a file as setuid, setgid and readable, writable and executable by all, you would type:
chmod 6777 file

The sticky bit is of no concern to this text but I'll include this explanation since it
might have piqued your curiosity:
{ The ISVTX (the sticky bit) indicates to the system which executable files are shareable
(the default) and the system maintains the program text of the files in the swap area.
The sticky bit may only be set by the super user on shareable executable files.

If the sticky bit is set on a directory means no other user can is set on a directory, an
unprivileged user may not delete or rename files of other users in that directory. The
sticky bit may be set by any user on a directory which the user owns or has appropriate
permissions. } - From the NetBSD manpage.

Back to the topic:

Let's say G1bs0nH4c| shell with the webserver's permissions. Your don't run your webserver as 
root hopefully, so you're okay there. But he has access to the system, if only with a normal 
user's permissions. You're a lazy bum and don't like to type ./executable so you put . in your path. 
G1bs0nH4c| puts a bash script called 'ls' in some directory that makes a copy of bash, chmod 4777s it,
then deletes itself. You think ls intermittently fudged up, and think nothing of it. Now he
has root access to your system. Sure, you probably don't have a vulnerable cgi, or . in your
path. But that's only one example.

Root accounts look very suspicious in the /etc/password so a smart attacker won't rely on one
to gain access each time. Much more reliable to make a user account and use a setuid shell to
gain root privs.

You can find all the setuid and setgid files on your system by issuing the command:
/usr/bin/find / -user root -perm -4000 -o -perm -2000

Setuid programs have a wide range of consequences and powers. A world-readable, root-owned
setuid /usr/bin/less would allow any user to read any file, not a good thing. If chown was
set as setuid, anyone can do anything. That one file would allow what amounts to root access.
Try to stay away from setting files as setuid, there are almost always better ways to
accomplish your task. One bad use of setuid I've seen is in the RedHat distro and possibly
others. The gnome games are setuid. Possibly so the games can write to the root-owned high 
score files, but normal users can't. A bad security breach to protect a high score file, 
ignorant.

Some notes on setuid shells:
bash -- must be run with the -p or --posix argument to accept it's own setuid permissions,
otherwise it drops euid root.
tcsh -- Will not run if it's setuid.
ash -- Normal.
pdksh-- Normal.
sash -- Normal.

If your changing permission on system files, you should make backups or notes so you
don't forget the good permissions. Don't forget to delete or unset anything you've set as
setuid to test it. Leaving setuid shells around is not a good practice. Following is a
shell script I wrote to catalog setuid/setgid files and compare it with that catalog on
future scans. It's fairly complete, only a few things need fixing. The part which mails
differences in the catalog and current setuid programs is not there. Also, it uses diff to
figure out what has been added removed. I can't figure out a decently easy way to remove
the hexcodes diff uses to show where in the file the differences are. The log file could
use a facelift as well. If you fix any of those things email me the fixes at
volatile@phreaker.net.

Feel free to email me to ask questions about anything in this document.

Have Fun.
------------------------------------------------------------------------------------
#!/bin/bash
#Written by volatile(volatile@phreaker.net)
#Catalogs setgid/setuid programs and catalogs them for comparison in future scans.
#Copyright (C) 2002 Patrick Jordan

#This program is free software; you can redistribute it and/or modify
#it under the terms of the GNU General Public License as published by
#the Free Software Foundation; either version 2 of the License, or
#(at your option) any later version.

#This program is distributed in the hope that it will be useful,
#but WITHOUT ANY WARRANTY; without even the implied warranty of
#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
#GNU General Public License for more details.

#You should have received a copy of the GNU General Public License
#along with this program; if not, write to the Free Software
#Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

#Run Options:
#Run with no options- On the first run it will make a new catalog
# of setuid/setgid programs on your system, subsequent runs will
# compare current setuid/setgid programs with the catalog.
#Run with 'scan' option to repress any catalogging or comparisons.
#Run with 'makecatalog' option to force it to make a new catalog.

#Config:
#Set directories for catalogs/system logs/temporary files here.
#Directory for log.
logdir="/var/log"
#catalogue directory.
siddir="/etc"
#Temporary file directory.
tmpdir="/var/tmp"


if [ "$1" = "scan" ]; then
echo -e "\\033[1;32mScanning for setuid/setgid programs and exiting.\\033[0;39m"
/usr/bin/find / \( -perm -4000 -o -perm -2000 \) 
exit
fi

if [ "$1" = "makecatalog" ]; then
echo -e "\\033[1;32mWriting a new setuid/setgid program catalog.\\033[0;39m"
/usr/bin/find / \( -perm -4000 -o -perm -2000 \) > $siddir/sids
exit
fi

if [ -f $siddir/sids ]; then

echo -e "\\033[1;32mScanning for added/removed setuid programs.\\033[0;39m"
/usr/bin/find / \( -perm -4000 -o -perm -2000 \) > $tmpdir/sidsnow.temp

sidsbefore="$siddir/sids"
sidsnow="$tmpdir/sidsnow.temp"

if diff $sidsnow $sidsbefore >> $tmpdir/sidsnew.temp; then

echo -e "\\033[1;32mNo new setuid program(s) found.\\033[0;39m"
rm $tmpdir/sidsnow.temp
exit

else

#Write Changes to log:
echo -e "\\033[1;31mAlert: new setuid program(s) found.\\033[0;39m"
date=$(date)
echo "" >> $logdir/sids.log
echo "" >> $logidr/sids.log
echo $date >> $logdir/sids.log
echo "Setuid program changes found." >> $logdir/sids.log
echo "" >> $logdir/sids.log
sed 's/ $tmpdir/sidsformat.temp
sed 's/> /Removed: /' $tmpdir/sidsformat.temp > $tmpdir/sidsnew.temp
sidsnew=`cat $tmpdir/sidsnew.temp`
echo "$sidsnew" >> $logdir/sids.log

#Write changes to stdout:
echo "$sidsnew"
echo ""
echo "If this is okay add/remove the entry to $siddir/sids, or delete $siddir/sids 
and rerun sidscan."
echo ""

#Mail changes to root:
#FIXME -- 

#Delete temp files:
rm -f $/sidsnow.temp
rm -f $tmpdir/sidsnew.temp
rm -f $tmpdir/sidsformat.temp

exit
fi

else
echo -e "\\033[1;31mNotice: /etc/sids not found writing new one.\\033[0;39m"
/usr/bin/find / \( -perm -4000 -o -perm -2000 \) > $siddir/sids
chmod 660 $siddir/sids
touch $logdir/sids.log
chmod 660 $logdir/sids.log
echo -e "\\033[1;32mCatalog written to $siddir/sids.\\033[0;39m"

exit

fi
exit 

    Source: geocities.com/pageclasses