suid shell scripts – setting “the SUID bit”

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 (127.0.0.1) 56(84) bytes of data.
64 bytes from localhost (127.0.0.1): 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 www.google.com” 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.

12 Responses to suid shell scripts – setting “the SUID bit”

  1. Andre Miller says:

    You seem to be confusing the SUID bit with the Sticky bit in this article. They mean two different things. Sticky bit is the ‘t’ flag, (chmod +t), which means something different to what you are explaining here.

    Take a look here for the full explanation of the sticky bit: http://en.wikipedia.org/wiki/Sticky_bit

  2. unixshell says:

    Thanks, good point. Not sure why I got that mixed up. Yes, the “Sticky” bit is indeed the “+t” flag. Article updated.

  3. agrion says:

    Good article

  4. Corrector says:

    So, how is a SUID script dangerous? You forgot to tell!

    Also, how is C programming “safe”, especially for C beginners, especially those knowing mostly shell (most likely to just call ‘system’ or ‘popen’), especially for the Unix-illiterates?

  5. unixshell says:

    SUID anything can be dangerous – scripts can be a problem in that they must be readable by the user who executes them, so any small bug in the script can be exploited – eg, if the script just does “echo hello”, then a non-priviliged user could alias “echo” to “rm -rf /” and run the script.

    A SUID C program is safer in that the binary can be set with execute permissions but not read permissions, so you can run it but not disassemble it. Of course, the C program may run the system() system call and be exploitable in many other ways too. It would be less easy for a regular user to find out what to exploit, though. Any use of SUID should be avoided where possible.

    Finally – a C-illiterate, Unix-illiterate programmer would write very poor C code for Unix. A new driver would be very likely to crash a Ferrari, but that does not make Ferraris inherently unsafe.

  6. […] suid shell scripts – setting “the SUID bit” April 20075 comments 4 […]

  7. Name Required says:

    If security-through-obscurity is that valuable, why isn’t your system’s /bin/ping set unreadable? (It’s clearly world readable in your listings in the article.) You’re doing a disservice to readers by confusing this issue: it is not the readability of shell scripts that makes them unsuitable for SUID. Re-read the article linked in the first sentence.

  8. Steve Parker says:

    At the risk of feeding a troll, the previous comment was not advocating security-through-obscurity as an end in itself, which was clear from the original blog post, and the faqs.org article which it linked. As you presumably know, the reason for ping being suid is because parts of its functionality require root privileges on most implementations of *nix. The examples on the faqs.org page assume that the attacker knows the next characters after #! in order to exploit them – if /bin/sh then use -i, for example.

    But enough troll-feeding for now.

  9. Ekevoo says:

    So, how is a SUID script dangerous? You forgot to tell!

  10. unixshell says:

    SUID is dangerous because any user can run it with “root” privileges. Any program granted SUID privileges must be thoroughly inspected and totally trusted.

    Shell scripts – being readable as well as executable, and particularly being in plain-text also – are especially vulnerable to attack, as an attacker can see how their input will be treated before even attempting to exploit the script. Anything they get the script to run, will be run with superuser privileges.

  11. #!/bin/bash says:

    this is exactly what we all want.. always funny when lamers talks “dangerous”..

Leave a reply to #!/bin/bash Cancel reply