suid shell scripts – setting “the SUID bit”

April 21, 2007

I just found an excellent explanation of why suid shell scripts are a very bad idea.

So just be glad that most modern OSes don’t allow it. You really don’t want to do it, in the first place.

Yes, yes, yes. I know. You do want to do it, and you’re really really sure (really really really sure) that it will all be nice and secure; you’ve got a firewall, completely trusted users, regular password changes, and all the rest of it.

You still don’t want to do it.

Do it in C – you could even get away with a C wrapper, if you must.

But – and let me be quite clear on this:

Don’t do it. It really isn’t worth it, however much it seems, right now, to be a good idea.

What is the “SUID bit”?

The suid bit, is what you get from a “chmod u+s” command, which will set the permissions to “-rwsr-xr-x”, or similar (note the “s” replacing the usual “x”). That means that you can run certain commands with the permissions of a different user (typically root). This is very useful -for example, a normal user under Linux can’t open an ICMP socket (see footnote), so they can’t run the ping command. As a fix, it’s suid root:

$ ls -l /bin/ping
-rwsr-xr-x 1 root root 30848 2007-03-05 04:25 /bin/ping

okay, it’s owned by “root”, and the SUID bit is set. It will work fine, because ping itself has root permissions:

$ /bin/ping -c 1 localhost
PING localhost ( 56(84) bytes of data.
64 bytes from localhost ( icmp_seq=1 ttl=64 time=0.060 ms
--- localhost ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.060/0.060/0.060/0.000 ms

Good stuff. Now, what if we make a copy? That copy will be owned by a normal user (“steve”, in this example), so it won’t have root permissions:

$ cp /bin/ping /tmp/
$ ls -l /tmp/ping
-rwsr-xr-x 1 steve steve 30848 2007-04-22 00:46 /tmp/ping
$ /tmp/ping localhost
ping: icmp open socket: Operation not permitted

It still had the SUID bit set, it’s just the owner that changed. Let’s just confirm that it’s the “suid + root” that mattered:

$ chmod 755 /tmp/ping
$ ls -l /tmp/ping
-rwxr-xr-x 1 steve steve 30848 2007-04-22 00:46 /tmp/ping
$ /tmp/ping localhost
ping: icmp open socket: Operation not permitted

And what if it’s owned by root?:

$ sudo chown root:root /tmp/ping
$ ls -l /tmp/ping
-rwxr-xr-x 1 root root 30848 2007-04-22 00:46 /tmp/ping
$ /tmp/ping localhost
ping: icmp open socket: Operation not permitted
[footnote]: Why can’t I “ping”?

The reason that Linux ping has to be run as root, isn’t because ping itself is inherently dangerous, but the things that it does (open network connections, sends data over the network to other machines, and receives data back from them) are potentially dangerous. Therefore, those functions are restricted to the root user. So ping can be seen as a special subset of commands which – whilst they do these potentially dangerous things, do them in a safe and secure manner. This means that the ping command can be elevated to superuser status by the “SUID bit”: It’s a trusted user of certain potentially dangerous commands.

A taxi cab is a useful thing, but it could be used for a ram-raid. The taxi cab, in this case, is like the network protocol. The taxi driver is ping. We trust ping to do the Good Stuff, and not the Bad Stuff. So, we don’t let anyone get in and start driving the taxi, but we do let anyone get in and ask the taxi driver to take them somewhere. The command “ping DoS attack” will not work – although another network utility, with the same permissions, may well perform a DoS attach. Similarly, getting into a taxi and telling the driver to “drive into that electronics store front window, wait for me to pile the car up with goods, and take me to my hiding place” is not likely to work. If you had a car (had root access) yourself, you could do it, but you can’t (well, should not be able to) convince these trusted services to do nasty stuff on your behalf.

For that reason, we need to be very picky about what code gets the “SUID bit” promotion – the restrictions are there for a reason, so any program with a SUID bit must be able to prove that it will “only use its powers for good, and not for evil”, in the good old melodramatic cliche.

Black-hat hackers will spend a lot more time looking at a suid program like ping than at they will at a normal program like cat, even though cat is far more flexible. If mkdir had the SUID bit set, all kinds of mayhem would ensue.

For shell scripts, where security-through-obscurity is not even possible (chmod permissions of r-x are required, at a minimum, so everyone who can run the script, can read exactly how it was written), suid is always to be avoided.