Recipe 9.9 Finding setuid (or setgid) Programs

9.9.1 Problem

You want to check for potentially insecure setuid (or setgid) programs.

9.9.2 Solution

To list all setuid or setgid files (programs and scripts):

$ find /dir -xdev -type f -perm +ug=s -print

To list only setuid or setgid scripts:

$ find /dir -xdev -type f -perm +ug=s -print0 | \
perl -0ne 'chomp;
               open(FILE, $_);
               read(FILE, $magic, 2);
               print $_, "\n" if $magic eq "#!";

To remove setuid or setgid bits from a file:

$ chmod u-s file                    Remove the setuid bit
$ chmod g-s file                    Remove the setgid bit

To find and interactively fix setuid and setgid programs:

$ find /dir -xdev -type f \
        \(  -perm +u=s -printf "setuid: %p\n" -ok chmod -v u-s {} \; , \
            -perm +g=s -printf "setgid: %p\n" -ok chmod -v g-s {} \;   \)

To ignore the setuid or setgid attributes for executables in a filesystem, mount it with the nosuid option. To prohibit executables entirely, use the noexec mount option. These options can appear on the command line:

# mount -o nosuid ...
# mount -o noexec ...

or in /etc/fstab:

/dev/hdd3   /home   ext2    rw,nosuid   1 2
/dev/hdd7   /data   ext2    rw,noexec   1 3

Be aware of the important options and limitations of find, so you don't inadvertently overlook important files. [Recipe 9.8]

9.9.3 Discussion

If your system has been compromised, it is quite likely that an intruder has installed backdoors. A common ploy is to hide a setuid root program in one of your filesystems.

The setuid permission bit changes the effective user ID to the owner of the file (even root) when a program is executed; the setgid bit performs the same function for the group. These two attributes are independent: either or both may be set.

Programs (and especially scripts) that use setuid or setgid bits must be written very carefully to avoid security holes. Whether you are searching for backdoors or auditing your own programs, be aware of any activity that involves these bits.

Many setuid and setgid programs are legitimately included in standard Linux distributions, so do not panic if you detect them while searching directories like /usr. You can maintain a list of known setuid and setgid programs, and then compare the list with results from more recent filesystem scans. Tripwire (Chapter 1) is an even better tool for keeping track of such changes.

Our recipe uses find to detect the setuid and setgid bits. By restricting attention to regular files (with -type f), we avoid false matches for directories, which use the setgid bit for an unrelated purpose. In addition, our short Perl program identifies scripts, which contain "#!" in the first two bytes (the magic number).

The chmod command removes setuid or setgid bits (or both) for individual files. We can also combine detection with interactive repair using find: our recipe tests each bit separately, prints a message if it is found, asks (using -ok) if a chmod command should be run to remove the bit, and finally confirms each repair with chmod -v. Commands run by find -ok (or -exec) must be terminated with a "\;" argument, and the "{}" argument is replaced by the filename for each invocation. The separate "," (comma) argument causes find to perform the tests and actions for the setuid and setgid bits independently.

Finally, mount options can offer some protection against misuse of setuid or setgid programs. The nosuid option prevents recognition of either bit, which might be appropriate for network filesystems mounted from a less trusted server, or for local filesystems like /home or /tmp.[3] The even more restrictive noexec option prevents execution of any programs on the filesystem, which might be useful for filesystems that should contain only data files.

[3] Note that Perl's suidperl program does not honor the nosuid option for filesystems that contain setuid Perl scripts.

9.9.4 See Also

find(1), xargs(1), chmod(1), perlsec(1).

    Chapter 9. Testing and Monitoring