The SUID bit is a flag on a file which states that whoever runs the file will have the privileges of the owner of the file. So, if you are
student and the file is owned by
root, then when you run that executable, the code runs with the permissions of the
root user. The SUID bit only works on Linux ELF executables, meaning it does nothing if it’s set on a Bash shell script, a Python script file, etc.
We can identify that an executable has been set with SUID by looking at the file’s permissions with
ls -la. If there is an
s instead of an
x in the user permissions, then that file has the SUID bit set.
This is necessary in many system files. For example, if you want to change your password with the passwd utility, then that utility must have permissions to change system files, such as
Since normal users do not have those permissions, the utility is configured to have the SUID bit set, and because it is owned by the root user, it has root privileges.
Of course, if you’re able to trick the program with malicious input somehow, then the consequences can be incredibly dangerous.
Finding SUID executables
By using the following command you can enumerate all binaries having SUID permissions:
find / -perm -u=s -type f 2>/dev/null
/denotes that we will start from the top (root) of the file system and find every directory
-permdenotes that we will search for the permissions that follow:
-u=sdenotes that we will look for files which are owned by the root user
-typestates the type of file we are looking for
fdenotes a regular file, excluding directories and special files
2>/dev/nullmeans we will redirect all errors to /dev/null. In other words, we will ignore all errors.
You will find certain SUID executables in almost all Linux systems, such as:
gpasswd, etc. These are there by default and are most likely secure. They will turn up in your search, but we should recognize and ignore them. We want to look for custom SUID executables.
If you aren’t sure which SUID executables are there by default and which are custom, then an easy way is to look for all SUID executables on another (preferably very similar) system. Then you can spot which SUID files exist on the target system, but not on other systems.
Exploitation with command execution
There are numerous programs out there which enable you to execute commands for one reason or another. If the program is owned by root and has the SUID bit enabled, then that makes it trivial to exploit. Since you’re already running the program with root privileges, the commands you run will also be executed with root privileges.
Here are two examples:
This will execute
echo hello for every file it finds in the current directory:
find . -exec echo hello \;
You can run system commands inside vim.
vim to start the program
:!echo hello to run the command
Many other text editors offer similar functionality (nano, less, more, etc)
Exploitation with file writing
If there is a SUID executable which is owned by root and which allows you to write to a file in some way, then it’s possible to get root privileges.
One way to gain a root shell is by adding a new user to /etc/passwd who has the UID 0. Any user with UID 0 is effectively root. We can do this by adding the following line to the passwd file:
Breaking it down:
root2is the username
WVLY0mgH0RtUIis the encrypted password we want him to have. Unencrypted, the password is
mrcake, in this case
0:0means the user id and group id are both 0
rootis a comment field
/rootis the home directory
/bin/bashis the default shell
Even if the executable didn’t overwrite files, we would easily be able to get a root shell by creating a cron task which will execute any code we want it to. This is achieved by writing a file in
/etc/cron.d, though you must ensure it is in the correct format.
Using symlinks alongside the file write exploit
A symlink functions as a shortcut to a destination file or directory. When a program writes to a symlink, then the text will appear in the file which the symlink points to. When a program opens a symlink as a directory, then it reads the contents of the destination directory. If we can use this to our advantage and write to
/etc/passwd, for example, then we can escalate our privileges to root.
Let’s say we have a SUID program which copies (and overwrites, if already exists) the contents of one directory to another. Therefore, our plan should be to create a source directory with a malicious
passwd file and a destination directory, which is a symlink to
/etc. That would allow us to overwrite
/etc/passwd with our malicious file.
Create the malicious passwd file
Continuing with our example of a SUID program which copies directories, let’s see how to exploit it.
First let’s create a
source directory which will hold our malicious passwd file, which we will use for overwriting
Now, create the malicious passwd file, which has an additional UID0 user:
cp /etc/passwd source/passwd echo 'root2:WVLY0mgH0RtUI:0:0:root:/root:/bin/bash' >> source/passwd
The password for this new
root2 user will be
Create the symlink
We should now create a symlink to the
/etc folder. We will call it
ln -s /etc destination
Now we can simply run the program with our crafted source and destination directories.
/etc/passwd will be overwritten and we will be able to gain root access by doing
Exploitation with the PATH variable
Introduction to the PATH variable
PATH is an environment variable in Linux and other Unix-like operating systems. If a full path to an executable is not supplied when running a command, then the PATH is used to determine in which directories the executable should be searched. It increases the convenience of such operating systems.
What this means is that when a program does not specify a full path to an externally called executable, then you are in control of where the executable is searched for. When you combine this with a SUID executable, then the results can be dangerous.
It is assumed that the SUID program sets its own UID (user id) and GID (group id) to 0 (root) before calling the external program. Otherwise, the external program will be called with the privileges of the normal user and the exploit won’t work.
setuid(0); setgid(0); system("whoami"); // root, but only because we set UID to 0
If a SUID executable calls another program without a full path set (
ps instead of
/bin/ps), then the PATH variable is used to decide where to search for the program. So, if we change the PATH variable and point it to a directory we own, and we put a malicious program there, then we can trick the SUID executable into running our malicious code as the superuser.
Let’s use the same code snippet as an example. Let’s say the program is called
vulnerable-program, with the following content:
setuid(0); setgid(0); system("whoami");
Creating a file which spawns a shell when executed:
echo "/bin/bash" > /tmp/whoami
Allowing other users to execute the file:
chmod 777 /tmp/whoami
Adding our malicious program’s directory to the PATH variable so our malicious file gets located first:
If you want to, you can check the contents of the PATH variable like this:
Now all we have to do is run the vulnerable SUID executable, and we will have root!
This does not work if the full path is supplied! For example:
Sidenote: SGID bit
It would also be helpful to know about the SGID flag. SGID stands for set group id. It functions just like SUID, except it gives you the group permissions of the file.
We can recognize it by the
s character in the
group section of a file’s permissions.
Symlinks and the sticky bit
The third and final flag you should be aware of is the sticky bit. It’s also called the ‘restricted deletion bit’ because that’s what it does - when it’s set on a directory, then only the owner of the file is allowed to delete a given file.
This is often useful on directories with
777 (everyone is allowed to read and write/delete) permissions. For example, it is set on the
We can recognize it by the
t character in the
others section of the permission set.
It is worth knowing about the sticky flag because it can throw a wrench into our plans. In the past, there were often vulnerabilities where a program would write or read files in
/tmp. An attacker would quickly swap out the file with a symlink, making the program instead write to any place he wants (like
/etc/passwd). To overcome this, the sticky bit was given a special extra restriction:
In directories with the sticky bit set, a program can follow a symlink only if the user of the symlink is the same as the user of the program.
We must keep this in mind when using symlinks for exploitation, as this restriction can stop us dead in our tracks.
We must be especially careful when making custom SUID executables, as one forgotten check or overlooked detail can mean privilege escalation. It should be considered beforehand if there’s any other way to accomplish the task besides crafting a SUID executable.
Additionally, we should know not to give SUID permissions to programs (
find) which weren’t designed to be secure when run with the SUID bit.