Quickly check for potential root-exploitable programs and backdoors.
One potential way for a user to escalate her privileges on a system
is to exploit a vulnerability in an
SUID or SGID program. SUID and SGID are
legitimately used when programs need special permissions above and
beyond those that are available to the user who is running them. One
such program is passwd
.
Simultaneously allowing a user to change her password while not
allowing any user to modify the system password file means that the
passwd
program must be run with root privileges.
Thus the program has its SUID bit set, which causes it to be executed
with the privileges of the program file’s owner.
Similarly, when the SGID bit is set, the program is executed with the
privileges of the file’s group owner.
Running ls -l
on a binary that has its SUID bit set
should look like this:
-r-s--x--x 1 root root 16336 Feb 13 2003 /usr/bin/passwd
Notice that instead of an execute bit (x
) for the
owner bits, it has an s
. This signifies an SUID
file.
Unfortunately, a poorly written SUID or SGID binary can be used to quickly and easily escalate a user’s privileges. Also, an attacker who has already gained root access may hide SUID binaries throughout your system in order to leave a backdoor for future access. This leads us to the need for scanning systems for SUID and SGID binaries. This is a simple process and can be done with the following command:
# find / \( -perm -4000 -o -perm -2000 \) -type f -exec ls -la {} \;
One important thing to consider is whether an SUID program is in fact
a shell script rather than an executable, since
it’s trivial for someone to change an otherwise
innocuous script into a backdoor. Most operating systems will ignore
any SUID or SGID bits on a shell script, but if you want to find all
SUID or SGID scripts on a system, change the argument to the
-exec
option in the last command and add a pipe so
that the command reads:
#find / \( -perm -4000 -o -perm -2000 \) \
-type f -exec file {} \; | grep -v ELF
Now every time an SUID or SGID file is encountered, the
file
command will run and determine what
type of file is being examined. If it’s an
executable, grep
will filter it out; otherwise, it
will be printed to the screen with some information about what kind
of file it is. Most operating systems use ELF-format executables, but
if you’re running an operating system that
doesn’t (older versions of
Linux used a.out
, and
AIX uses XCOFF
), you’ll need to
replace the ELF
in the previous
grep
command with the binary format used by your
operating system and architecture. If you’re unsure
of what to look for, run the file
command on any
binary executable, and it will report the string
you’re looking for.
For example, here’s an example of running
file
on a binary in Mac OS X:
$ file /bin/sh
/bin/sh: Mach-O executable ppc
To go one step further, you could even queue the command to run once
a day using cron
and have it redirect the output
to a file. For instance, this crontab entry would scan for files that
have either the SUID or SGID bits set, compare the current list to
the one from the day before, and then email the differences to the
owner of the crontab (make sure this is all on one line):
0 4 * * * find / \( -perm -4000 -o -perm -2000 \) -type f \ > /var/log/sidlog.new && diff /var/log/sidlog.new /var/log/sidlog && mv /var/log/sidlog.new /var/log/sidlog
This example will also leave a current list of SUID and SGID files in
/var/log/sidlog
.
Get Network Security Hacks now with the O’Reilly learning platform.
O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.