Understand the setuid and setgid permissions to improve security

Understanding how the setuid and setgid permissions work on a Unix-like system is important, in part to know why they are used sometimes, but more importantly, to avoid misusing them.

The 16 November article, Understand basic Unix file permissions, discussed why understanding how the basic Unix permissions system works is important for security purposes, and hopefully helped some readers learn how it works and ties in with the general Unix privilege separation model. As a follow-up to it, an 18 November article covered managing default Unix file permissions with adduser and umask. There is still more you can learn about the Unix file permissions system to help ensure you keep your systems as secure as reasonably possible.

Two permissions that deserve special mention when discussing advanced Unix file permission management are the setuid and setgid permissions. These are of particular interest because they can enhance security if used appropriately, but they very much conform to the Unix philosophy of assuming the system administrator knows what he or she is doing, and not trying to protect the user from himself or herself. They can be very dangerous for security if used carelessly or in ignorance of their potential for trouble.

Every process has two different ways to classify its UID. One is its "real" UID, and the other is its "effective" UID. The real UID is the UID of the user account that starts the process. The effective UID is the UID of the user account whose privileges attach to the process. In the general case, the real and effective UIDs are the same, setuid and setgid permissions allow you to alter that behavior.

The key lies in the fact that the user account used to execute a program, thus spawning a new process, "owns" that process and thus imparts its UID as the process' real UID. The program file that is executed to create this process may itself be owned by a different user account, however. For example, if the root user owns the executable file for a command line utility called ls, that file may have permissions that allow other user accounts to execute the program as well, and yield the following output for the ls -l command:

> ls -l /bin/ls

-r-xr-xr-x 1 root wheel 25312 May 1 2009 /bin/ls

As explained in the "Understand basic Unix file permissions" article cited above, this shows that root is the user account owner of ls, and wheel is the group owner of ls. It also shows that r-x is the permission setting for the user account owner, the group owner, and all other user accounts. This means that user foo can both read and execute the ls command as well. When foo executes it, the owner of the process is foo, even though the file that was executed to create that process is owned by root.

Setting the above permissions via the chmod command uses three numbers:

> chmod 555 /bin/ls

(Note: You should probably not change the permissions of the ls command on your system. They are set that way for a reason.)

This simplifies the most common cases for setting file permissions. An additional number can be used at the beginning of that string of three of them to set other permissions, however. The number 4 would set the setuid permission. Making that change to the permissions of the ls command would be ill-advised, even if it is one of the less dangerous root-owned tools to which you could make this change, but for illustration purposes the operation might look like this:

> chmod 4555 /bin/ls

The end result would be that using ls -l to see these permissions would show something like this:

> ls -l /bin/ls

-r-sr-xr-x 1 root wheel 25312 May 1 2009 /bin/ls

The setgid permission is set in the same way, but uses the number 2 instead of the number 4:

> chmod 2555 /bin/ls

This would give you the following permissions, because it does the same thing as the setuid permission, but for the group owner instead of the user account owner:

> ls -l /bin/ls

-r-xr-sr-x 1 root wheel 25312 May 1 2009 /bin/ls

If you want to undo setting the setuid or setgid permission, you can use the number 0 there:

> chmod 0555 /bin/ls

Be careful when doing this, though; if the file or directory whose permissions you are changing is supposed to have the "sticky bit" set, you should not use 0 to remove setuid and setgid permissions. If you see a t in the last position when using ls -l to check file permissions, you have a file with the sticky bit set:

> ls -l / | grep tmp

drwxrwxrwt 18 root wheel 4096 Dec 16 00:00 tmp

While the sticky bit is outside the scope of this article, you should be aware that keeping the sticky bit while eliminating any setuid or setgid permissions requires using the number 1 where you might instead use the number 0. In this example the result would be the above indicated permissions for ls -l:

> chmod 1777 /tmp

Good security

As explained in an earlier article, The "insecure memory" FAQ, setuid can be used to improve security in certain circumstances. In the case of the GnuPG encryption utility, it is employed in some cases to ensure that the application uses secure memory, because an unprivileged UID cannot access secure memory. Using secure memory can make it more difficult for a malicious security cracker to harvest your GnuPG password from RAM after you have had to encrypt, decrypt, or digitally sign a file.

In other cases, certain server applications that need root-level privileges to set up their operating environment may need to have the setuid permission set so they start out with those privileges, but then drop those privileges and assume a less-privileged UID after the initial startup operations are complete. This can allow a server process to ensure it has its operating environment set up the way it needs it, but then assume a less privileged UID so that if a vulnerability is exploited by a malicious security cracker the server process will not be able to do anything with those root privileges it gave up. It is, in some respects, like still having your cake after you have already eaten it.

In most cases, however, you should not have to manually set any setuid or setgid permissions. The few applications most of us use that require these permissions for best security when used tend to have their setuid permissions set automatically during the install process -- which is made possible when installation is performed with the privileges of the root account. It is only in a very rare case that one must make a conscious decision to set a setuid or setgid permission, and it should be done only with great care.

Bad security

It is possible for some minor security vulnerability to be introduced by setting the setuid bit for almost any program. For instance, with the setuid permission set for ls, one might be able to read the contents of a directory to which one's current user account is not supposed to have access.

Things can get much worse from there, however. For instance, applications that have the ability to alter the filesystem in arbitrary ways can be used to alter any part of the filesystem if they are run with root privileges. Very important files may be deleted, moved, or copied to places they should not be copied if a vulnerability in a program with such capabilities is exploited when the program file is setuid root.

Still worse is the case of programs that can actually be used to execute arbitrary commands. For instance, the Vim text editor has the ability to execute shell commands. If Vim is setuid root, then even when it is being used by the lowliest unprivileged user one could execute commands from within Vim as if logged in at the shell as the root user account. At that point, you may as well just save a file named root_password.txt in the home directories of every single user account that has the ability to run the vim command, as long as you have Vim open to create or edit text files anyway.

It is for reasons like this that, most of the time that someone might think it is a good idea to use setuid and setgid permissions, a better idea is to find a different way to achieve the same effect.

Rule of thumb

The general rule of thumb for setuid and setgid should always be, "Don't Do It." It is only in rare cases that it is a good idea to use either of these file permissions, especially when many programs might have surprising capabilities that, combined with setuid or setgid permissions, could result in shockingly bad security. In those rare cases, though, the setuid and setgid permissions can be used to improve security, when used properly.