I'm a human being. And sometimes I believe I understand something. And I don't. That's the case of the setuid bit. I've read dozens of times how it works, but I didn't fully understand it until today.

The definition of the setuid bits is pretty straightforward: setuid and setgid (short for "set user ID upon execution" and "set group ID upon execution", respectively) are Unix access rights flags that allow users to run an executable with the permissions of the executable's owner or group respectively.

Is it clear, right? If you want to see an example of a program with the setuid on you can do:

$ ls -l /bin/ping

-rwsr-xr-x 1 root root 36136 Apr 12  2011 /bin/ping

You will see the user execution flag with an "s". That means that is you run this command, the executing will be done by root. In this case PING needs to be root in order to send ICMP packets to the network, utility that only can be used by root. Setting up this flag to the ping command allows everybody to use it. You could do exactly the same with adduser command, and any user would be able to create as many users as he wanted. Of course is not a good idea, as far as setting up the setuid to rm or dd commands is the closest thing to shoot yourself in the foot.

BUUUUUT (there is always a "but") setuid doesn't work on shell scripts, for security reasons.

I didn't know that, an that's why all my test trying to use the setuid failed miserably, because I always tried it with bash scripts and not with "real" programs.

What is you want to execute a shell script with the setuid on? You can't. But you can create a binary that will have the setuid on, and this binary will run you shell script as root. Let's see an example:

$ echo "touch /opt/foo" >> script.sh  
$ echo "rm /opt/foo" >> script.sh

$ chown root.root script.sh

$ chmod 4755 script.sh

$ ls -l script.sh

-rwsr-xr-x 1 root root 27 Jan 28 17:13 script.sh

$ ./script.sh

touch: cannot touch `/opt/foo': Permission denied  
rm: cannot remove `/opt/foo': No such file or directory

As you can see this shell script has the setuid, but it doesn't seems to work. We can create a binary that will do the work for us. Open a file called "execute.c" and copy the following code:

#include <stdio.h>  
#include <stdlib.h>  
#include <sys/types.h>  
#include <unistd.h>

int main()  
{  
setuid(0);  
system("./script.sh");  
return 0;  
}

And compile and execute the code using the following commands:

$ gcc execute.c -o execute  
$ sudo chown root.root execute  
$ sudo chmod 4755 execute  
$ ./execute

And now it works (no error given)! The setuid works for compiled file, and this file can execute others files as root.

More information in Unix - Frequently Asked Questions