Linux Privilege Escalation
Linux Privilege Escalation
Linux Privilege Escalation
Brief Contents
Why is it important?
It's rare when performing a real-world penetration test to be able to gain a foothold (initial
access) that gives you direct administrative access. Privilege escalation is crucial because it
lets you gain system administrator levels of access, which allows you to perform actions such
as:
• Resetting passwords
• Bypassing access controls to compromise protected data
• Editing software configurations
• Enabling persistence
• Changing the privilege of existing (or new) users
• Execute any administrative command
Enumeration is the first step you have to take once you gain access to any system. You
may have accessed the system by exploiting a critical vulnerability that resulted in root-level
access or just found a way to send commands using a low privileged account. Penetration
testing engagements, unlike CTF machines, don't end once you gain access to a specific
system or user privilege level. As you will see, enumeration is as important during the post-
compromise phase as it is before.
hostname
The hostname command will return the hostname of the target machine. Although this
value can easily be changed or have a relatively meaningless string (e.g. Ubuntu-
3487340239), in some cases, it can provide information about the target system’s role within
the corporate network (e.g. SQL-PROD-01 for a production SQL server).
Page |3
uname -a
Will print system information giving us additional detail about the kernel used by the system.
This will be useful when searching for any potential kernel vulnerabilities that could lead to
privilege escalation.
/proc/version
The proc filesystem (procfs) provides information about the target system processes. You will
find proc on many different Linux flavours, making it an essential tool to have in your
arsenal.
Looking at /proc/version may give you information on the kernel version and additional data
such as whether a compiler (e.g. GCC) is installed.
/etc/issue
Systems can also be identified by looking at the /etc/issue file. This file usually contains
some information about the operating system but can easily be customized or changed.
While on the subject, any file containing system information can be customized or changed.
For a clearer understanding of the system, it is always good to look at all of these.
ps Command
The ps command is an effective way to see the running processes on a Linux system.
Typing ps on your terminal will show processes for the current shell.
The output of the ps (Process Status) will show the following;
• PID: The process ID (unique to the process)
• TTY: Terminal type used by the user
• Time: Amount of CPU time used by the process (this is NOT the time this process has
been running for)
• CMD: The command or executable running (will NOT display any command line
parameter)
The “ps” command provides a few useful options.
• ps -A: View all running processes
• ps axjf: View process tree (see the tree formation until ps axjf is run below)
Page |4
• ps aux: The aux option will show processes for all users (a), display the user that
launched the process (u), and show processes that are not attached to a terminal (x).
Looking at the ps aux command output, we can have a better understanding of the
system and potential vulnerabilities.
env
The env command will show environmental variables.
The PATH variable may have a compiler or a scripting language (e.g. Python) that could be
used to run code on the target system or leveraged for privilege escalation.
sudo -l
The target system may be configured to allow users to run some (or all) commands with root
privileges. The sudo -l command can be used to list all commands your user can run
using sudo.
Page |5
ls
One of the common commands used in Linux is probably ls.
While looking for potential privilege escalation vectors, please remember to always use
the ls command with the -la parameter. The example below shows how the “secret.txt” file
can easily be missed using the ls or ls -l commands.
Id
The id command will provide a general overview of the user’s privilege level and group
memberships.
It is worth remembering that the id command can also be used to obtain the same
information for another user as seen below.
/etc/passwd
Reading the /etc/passwd file can be an easy way to discover users on the system.
Page |6
While the output can be long and a bit intimidating, it can easily be cut and converted to a
useful list for brute-force attacks.
Remember that this will return all users, some of which are system or service users that
would not be very useful. Another approach could be to grep for “home” as real users will
most likely have their folders under the “home” directory.
Page |7
history
Looking at earlier commands with the history command can give us some idea about the
target system and, albeit rarely, have stored information such as passwords or usernames.
ifconfig
The target system may be a pivoting point to another network. The ifconfig command will
give us information about the network interfaces of the system. The example below shows
the target system has three interfaces (eth0, tun0, and tun1). Our attacking machine can
reach the eth0 interface but can not directly access the two other networks.
This can be confirmed using the ip route command to see which network routes exist.
Page |8
netstat
Following an initial check for existing interfaces and network routes, it is worth looking into
existing communications. The netstat command can be used with several different options
to gather information on existing connections.
• netstat -s: list network usage statistics by protocol (below) This can also be used with
the -t or -u options to limit the output to a specific protocol.
Page |9
• netstat -tp: list connections with the service name and PID information.
This can also be used with the -l option to list listening ports (below)
P a g e | 10
We can see the “PID/Program name” column is empty as this process is owned by another
user.
Below is the same command run with root privileges and reveals this information as 2641/nc
(netcat)
• netstat -i: Shows interface statistics. We see below that “eth0” and “tun0” are more
active than “tun1”.
The netstat usage you will probably see most often in blog posts, write-ups, and courses
is netstat -ano which could be broken down as follows;
• -a: Display all sockets
• -n: Do not resolve names
• -o: Display timers
P a g e | 11
find Command
Searching the target system for important information and potential privilege escalation
vectors can be fruitful. The built-in “find” command is useful and worth keeping in your
arsenal.
Below are some useful examples for the “find” command.
Find files:
• find . -name flag1.txt: find the file named “flag1.txt” in the current directory
• find /home -name flag1.txt: find the file names “flag1.txt” in the /home directory
• find / -type d -name config: find the directory named config under “/”
• find / -type f -perm 0777: find files with the 777 permissions (files readable,
writable, and executable by all users)
• find / -perm a=x: find executable files
• find /home -user frank: find all files for user “frank” under “/home”
• find / -mtime 10: find files that were modified in the last 10 days
• find / -atime 10: find files that were accessed in the last 10 day
• find / -cmin -60: find files changed within the last hour (60 minutes)
• find / -amin -60: find files accesses within the last hour (60 minutes)
• find / -size 50M: find files with a 50 MB size
This command can also be used with (+) and (-) signs to specify a file that is larger or smaller
than the given size.
The example above returns files that are larger than 100 MB. It is important to note that the
“find” command tends to generate errors which sometimes makes the output hard to read.
P a g e | 12
This is why it would be wise to use the “find” command with “-type f 2>/dev/null” to
redirect errors to “/dev/null” and have a cleaner output (below).
Several tools can help you save time during the enumeration process. These tools should
only be used to save time knowing they may miss some privilege escalation vectors. Below is
a list of popular Linux enumeration tools with links to their respective Github repositories.
The target system’s environment will influence the tool you will be able to use. For example,
you will not be able to run a tool written in Python if it is not installed on the target system.
This is why it would be better to be familiar with a few rather than having a single go-to tool.
• LinPeas: https://github.com/carlospolop/privilege-escalation-awesome-scripts-
suite/tree/master/linPEAS
• LinEnum: https://github.com/rebootuser/LinEnum
• LES (Linux Exploit Suggester): https://github.com/mzet-/linux-exploit-suggester
• Linux Smart Enumeration: https://github.com/diego-treitos/linux-smart-
enumeration
• Linux Priv Checker: https://github.com/linted/linuxprivchecker
P a g e | 15
Privilege escalation ideally leads to root privileges. This can sometimes be achieved simply
by exploiting an existing vulnerability, or in some cases by accessing another user account
that has more privileges, information, or access.
Unless a single vulnerability leads to a root shell, the privilege escalation process will rely on
misconfigurations and lax permissions.
The kernel on Linux systems manages the communication between components such as the
memory on the system and applications. This critical function requires the kernel to have
specific privileges; thus, a successful exploit will potentially lead to root privileges.
The Kernel exploit methodology is simple;
1. Identify the kernel version
2. Search and find an exploit code for the kernel version of the target system
3. Run the exploit
Although it looks simple, please remember that a failed kernel exploit can lead to a system
crash. Make sure this potential outcome is acceptable within the scope of your penetration
testing engagement before attempting a kernel exploit.
Research sources:
1. Based on your findings, you can use Google to search for an existing exploit code.
2. Sources such as https://www.cvedetails.com/ can also be useful.
3. Another alternative would be to use a script like LES (Linux Exploit Suggester) but
remember that these tools can generate false positives (report a kernel vulnerability
that does not affect the target system) or false negatives (not report any kernel
vulnerabilities although the kernel is vulnerable).
Hints/Notes:
1. Being too specific about the kernel version when searching for exploits on Google,
Exploit-db, or searchsploit
2. Be sure you understand how the exploit code works BEFORE you launch it. Some
exploit codes can make changes on the operating system that would make them
unsecured in further use or make irreversible changes to the system, creating
problems later. Of course, these may not be great concerns within a lab or CTF
P a g e | 16
environment, but these are absolute no-nos during a real penetration testing
engagement.
3. Some exploits may require further interaction once they are run. Read all comments
and instructions provided with the exploit code.
4. You can transfer the exploit code from your machine to the target system using
the SimpleHTTPServer Python module and wget respectively.
P a g e | 17
The sudo command, by default, allows you to run a program with root privileges. Under
some conditions, system administrators may need to give regular users some flexibility on
their privileges. For example, a junior SOC analyst may need to use Nmap regularly but
would not be cleared for full root access. In this situation, the system administrator can
allow this user to only run Nmap with root privileges while keeping its regular privilege level
throughout the rest of the system.
Any user can check its current situation related to root privileges using the sudo -
l command.
https://gtfobins.github.io/ is a valuable source that provides information on how any
program, on which you may have sudo rights, can be used.
Leverage application functions
Some applications will not have a known exploit within this context. Such an application you
may see is the Apache2 server.
In this case, we can use a "hack" to leak information leveraging a function of the application.
As you can see below, Apache2 has an option that supports loading alternative configuration
files (-f : specify an alternate ServerConfigFile).
Loading the /etc/shadow file using this option will result in an error message that includes
the first line of the /etc/shadow file.
Leverage LD_PRELOAD
On some systems, you may see the LD_PRELOAD environment option.
P a g e | 18
LD_PRELOAD is a function that allows any program to use shared libraries. This blog post will
give you an idea about the capabilities of LD_PRELOAD. If the "env_keep" option is enabled
we can generate a shared library which will be loaded and executed before the program is
run. Please note the LD_PRELOAD option will be ignored if the real user ID is different from
the effective user ID.
The steps of this privilege escalation vector can be summarized as follows;
1. Check for LD_PRELOAD (with the env_keep option)
2. Write a simple C code compiled as a share object (.so extension) file
3. Run the program with sudo rights and the LD_PRELOAD option pointing to our .so file
The C code will simply spawn a root shell and can be written as follows;
#include <stdio.h>
#include <sys/types.h>
#include <stdlib.h>
void _init() {
unsetenv("LD_PRELOAD");
setgid(0);
setuid(0);
system("/bin/bash");
}
We can save this code as shell.c and compile it using gcc into a shared object file using the
following parameters;
gcc -fPIC -shared -o shell.so shell.c -nostartfiles
P a g e | 19
We can now use this shared object file when launching any program our user can run with
sudo. In our case, Apache2, find, or almost any of the programs we can run with sudo can be
used.
We need to run the program by specifying the LD_PRELOAD option, as follows;
sudo LD_PRELOAD=/home/user/ldpreload/shell.so find
This will result in a shell spawn with root privileges.
P a g e | 20
Much of Linux privilege controls rely on controlling the users and files interactions. This is
done with permissions. By now, you know that files can have read, write, and execute
permissions. These are given to users within their privilege levels. This changes with SUID
(Set-user Identification) and SGID (Set-group Identification). These allow files to be executed
with the permission level of the file owner or the group owner, respectively.
You will notice these files have an “s” bit set showing their special permission level.
find / -type f -perm -04000 -ls 2>/dev/null will list files that have SUID or SGID bits set.
The SUID bit set for the nano text editor allows us to create, edit and read files using the file
owner’s privilege. Nano is owned by root, which probably means that we can read and edit
files at a higher privilege level than our current user has. At this stage, we have two basic
options for privilege escalation: reading the /etc/shadow file or adding our user
to /etc/passwd.
Below are simple steps using both vectors.
reading the /etc/shadow file
We see that the nano text editor has the SUID bit set by running the find / -type f -perm -
04000 -ls 2>/dev/null command.
nano /etc/shadow will print the contents of the /etc/shadow file. We can now use the
unshadow tool to create a file crackable by John the Ripper. To achieve this, unshadow
needs both the /etc/shadow and /etc/passwd files.
P a g e | 22
With the correct wordlist and a little luck, John the Ripper can return one or several
passwords in cleartext. For a more detailed room on John the Ripper, you can
visit https://tryhackme.com/room/johntheripper0
The other option would be to add a new user that has root privileges. This would help us
circumvent the tedious process of password cracking. Below is an easy way to do it:
We will need the hash value of the password we want the new user to have. This can be
done quickly using the openssl tool on Kali Linux.
We will then add this password with a username to the /etc/passwd file.
P a g e | 23
Once our user is added (please note how root:/bin/bash was used to provide a root shell)
we will need to switch to this user and hopefully should have root privileges.
P a g e | 24
Another method system administrators can use to increase the privilege level of a process or
binary is “Capabilities”. Capabilities help manage privileges at a more granular level. For
example, if the SOC analyst needs to use a tool that needs to initiate socket connections, a
regular user would not be able to do that. If the system administrator does not want to give
this user higher privileges, they can change the capabilities of the binary. As a result, the
binary would get through its task without needing a higher privilege user.
The capabilities man page provides detailed information on its usage and options.
When run as an unprivileged user, getcap -r / will generate a huge number of errors, so it is
good practice to redirect the error messages to /dev/null.
Now you have a question that, why /dev/null is used so much in privilege escalation
in linux?
• Suppressing Output
• Attackers often use /dev/null to hide the output of commands or scripts they are
running to avoid detection.
• Example:
bash
Copy code
sudo some-command > /dev/null 2>&1
This redirects both stdout and stderr to /dev/null, silencing any logs or errors.
• Bypassing Restrictions
• Example:
bash
Copy code
su root < /dev/null
• Privileged scripts or cron jobs might redirect their output to /dev/null to suppress
logging. Attackers can exploit this in misconfigured systems where they can
manipulate cron jobs, using /dev/null as part of their payload to avoid raising
suspicion.
• Privilege escalation techniques like overwriting files or exploiting path traversal bugs
sometimes involve /dev/null to control or clear unwanted content in file
operations.
Please note that neither vim nor its copy has the SUID bit set. This privilege escalation vector
is therefore not discoverable when enumerating files looking for SUID.
GTFObins has a good list of binaries that can be leveraged for privilege escalation if we find
any set capabilities.
We notice that vim can be used with the following command and payload:
P a g e | 26
Cron jobs are used to run scripts or binaries at specific times. By default, they run with the
privilege of their owners and not the current user. While properly configured cron jobs are
not inherently vulnerable, they can provide a privilege escalation vector under some
conditions.
The idea is quite simple; if there is a scheduled task that runs with root privileges and we can
change the script that will be run, then our script will run with root privileges.
Cron job configurations are stored as crontabs (cron tables) to see the next time and date
the task will run.
Each user on the system have their crontab file and can run specific tasks whether they are
logged in or not. As you can expect, our goal will be to find a cron job set by root and have it
run our script, ideally a shell.
Any user can read the file keeping system-wide cron jobs under /etc/crontab
While CTF machines can have cron jobs running every minute or every 5 minutes, you will
more often see tasks that run daily, weekly or monthly in penetration test engagements.
You can see the backup.sh script was configured to run every minute. The content of the file
shows a simple script that creates a backup of the prices.xls file.
P a g e | 28
As our current user can access this script, we can easily modify it to create a reverse shell,
hopefully with root privileges.
The script will use the tools available on the target system to launch a reverse shell.
Two points to note;
1. The command syntax will vary depending on the available tools. (e.g. nc will probably
not support the -e option you may have seen used in other cases)
2. We should always prefer to start reverse shells, as we not want to compromise the
system integrity during a real penetration testing engagement.
The file should look like this;
We will now run a listener on our attacking machine to receive the incoming connection.
Crontab is always worth checking as it can sometimes lead to easy privilege escalation
vectors. The following scenario is not uncommon in companies that do not have a certain
cyber security maturity level:
P a g e | 29
The example above shows a similar situation where the antivirus.sh script was deleted, but
the cron job still exists.
If the full path of the script is not defined (as it was done for the backup.sh script), cron will
refer to the paths listed under the PATH variable in the /etc/crontab file. In this case, we
should be able to create a script named “antivirus.sh” under our user’s home folder and it
should be run by the cron job.
The file on the target system should look familiar:
P a g e | 30
In the odd event you find an existing script or task attached to a cron job, it is always worth
spending time to understand the function of the script and how any tool is used within the
context. For example, tar, 7z, rsync, etc., can be exploited using their wildcard feature.
P a g e | 31
If a folder for which your user has write permission is located in the path, you could
potentially hijack an application to run a script. PATH in Linux is an environmental variable
that tells the operating system where to search for executables. For any command that is not
built into the shell or that is not defined with an absolute path, Linux will start searching in
folders defined under PATH. (PATH is the environmental variable we're talking about here;
path is the location of a file).
If we type “thm” to the command line, these are the locations Linux will look in for an
executable called thm. The scenario below will give you a better idea of how this can be
leveraged to increase our privilege level. As you will see, this depends entirely on the
existing configuration of the target system, so be sure you can answer the questions below
before trying this.
1. What folders are located under $PATH
2. Does your current user have write privileges for any of these folders?
3. Can you modify $PATH?
4. Is there a script/application you can start that will be affected by this vulnerability?
For demo purposes, we will use the script below:
This script tries to launch a system binary called “thm” but the example can easily be
replicated with any binary.
P a g e | 32
Our user now has access to the “path” script with SUID bit set.
Once executed “path” will look for an executable named “thm” inside folders listed under
PATH.
If any writable folder is listed under PATH, we could create a binary named thm under that
directory and have our “path” script run it. As the SUID bit is set, this binary will run with
root privilege
A simple search for writable folders can done using the “find / -writable 2>/dev/null”
command. The output of this command can be cleaned using a simple cut and sort
sequence.
P a g e | 33
Some CTF scenarios can present different folders but a regular system would output
something like we see above.
Comparing this with PATH will help us find folders we could use.
We see a number of folders under /usr, thus it could be easier to run our writable folder
search once more to cover subfolders.
The folder that will be easier to write to is probably /tmp. At this point because /tmp is not
present in PATH so we will need to add it. As we can see below, the “export
PATH=/tmp:$PATH” command accomplishes this.
P a g e | 34
At this point the path script will also look under the /tmp folder for an executable named
“thm”.
Creating this command is fairly easy by copying /bin/bash as “thm” under the /tmp folder.
We have given executable rights to our copy of /bin/bash, please note that at this point it
will run with our user’s right. What makes a privilege escalation possible within this context
is that the path script runs with root privileges.
P a g e | 35
Privilege escalation vectors are not confined to internal access. Shared folders and remote
management interfaces such as SSH and Telnet can also help you gain root access on the
target system. Some cases will also require using both vectors, e.g. finding a root SSH private
key on the target system and connecting via SSH with root privileges instead of trying to
increase your current user’s privilege level.
Another vector that is more relevant to CTFs and exams is a misconfigured network shell.
This vector can sometimes be seen during penetration testing engagements when a network
backup system is present.
NFS (Network File Sharing) configuration is kept in the /etc/exports file. This file is created
during the NFS server installation and can usually be read by users.
The critical element for this privilege escalation vector is the “no_root_squash” option you
can see above. By default, NFS will change the root user to nfsnobody and strip any file from
operating with root privileges. If the “no_root_squash” option is present on a writable share,
we can create an executable with SUID bit set and run it on the target system.
We will mount one of the “no_root_squash” shares to our attacking machine and start
building our executable.
As we can set SUID bits, a simple executable that will run /bin/bash on the target system will
do the job.
You will see below that both files (nfs.c and nfs are present on the target system. We have
worked on the mounted share so there was no need to transfer them).
Notice the nfs executable has the SUID bit set on the target system and runs with root
privileges.
P a g e | 38
Capstone Challenge
After that, let's see what type of privileges we have via the whoami and id commands.
Okay, let's see what we can find using the find / -type f -perm -04000 -ls
2>/dev/null command (we used this before). Remember in the SUID section when we used
base64 to unshadow our /shadow and /passwd data? Let's do that again.
On your Desktop, create a SUID folder with two files: passwd.txt and shadow.txt.
P a g e | 39
In Leonard's terminal, run thebase64 /etc/shadow | base64 -d command and copy Missy's
value into the shadow.txt file.
Then, run thebase64 /etc/passwd | base64 -d command and copy Missy's value into the
passwd.txt file.
P a g e | 40
Now, in our attacker terminal, we can use John the Ripper to crack the password.
Remember, cd /Desktop/SUID first, then run the sudo unshadow passwd.txt shadow.txt >
cracked.txt command to create the cracked.txt file.
Now, back in Leonard's terminal, let's log in as Missy. Run the su missy command and enter
her password.
The sudo -l command will reveal that missy needs no password to access data.
Now we can go ahead and access our flag1.txt file. First, we need to find it via the sudo find /
-name "flag1.txt" command.
To read the flag, simply run cat /home/missy/Documents/flag1.txt. Our flag is revealed!
P a g e | 41
let's see if we can find the flag2.txt file via the sudo find / -name "flag2.txt" command. We
can see we need root access to access it.
Conclusion
I hope this helped somewhat as this lab really challenged me, but it was so much fun and it
felt good to complete it. Anyway, I got through it and now, so have you!