Linux Privilege Escalation
Do you use Hacktricks every day? Did you find the book very useful? Would you like to receive extra help with cybersecurity questions? Would you like to find more and higher quality content on Hacktricks? Support Hacktricks through github sponsors so we can dedicate more time to it and also get access to the Hacktricks private group where you will get the help you need and much more!
If you want to know about my latest modifications/additions or you have any suggestion for HackTricks or PEASS, join the 💬telegram group, or follow me on Twitter 🐦@carlospolopm. If you want to share some tricks with the community you can also submit pull requests to https://github.com/carlospolop/hacktricks that will be reflected in this book and don't forget to give ⭐ on github to motivate me to continue developing this book.
System Information
OS info
Let's starting gaining some knowledge of the OS running
Path
If you have write permissions on any folder inside the PATH
variable you may be able to hijacking some libraries or binaries:
Env info
Interesting information, passwords or API keys in the environment variables?
Kernel exploits
Check the kernel version and if there is some exploit that can be used to escalate privileges
You can find a good vulnerable kernel list and some already compiled exploits here: https://github.com/lucyoa/kernel-exploits and exploitdb sploits. Other sites where you can find some compiled exploits: https://github.com/bwbwbwbw/linux-exploit-binaries, https://github.com/Kabot/Unix-Privilege-Escalation-Exploits-Pack
To extract all the vulnerable kernel versions from that web you can do:
Tools that could help searching for kernel exploits are:
linux-exploit-suggester.sh linux-exploit-suggester2.pl linuxprivchecker.py (execute IN victim,only checks exploits for kernel 2.x)
Always search the kernel version in Google, maybe your kernel version is wrote in some kernel exploit and then you will be sure that this exploit is valid.
CVE-2016-5195 (DirtyCow)
Linux Privilege Escalation - Linux Kernel <= 3.19.0-73.8
Sudo version
Based on the vulnerable sudo versions that appear in:
You can check if the sudo version is vulnerable using this grep.
sudo <= v1.28
From @sickrov
Dmesg signature verification failed
Check smasher2 box of HTB for an example of how this vuln could be exploited
More system enumeration
Enumerate possible defenses
AppArmor
Grsecurity
PaX
Execshield
SElinux
ASLR
Docker Breakout
If you are inside a docker container you can try to escape from it:
Drives
Check what is mounted and unmounted, where and why. If anything is unmounted you could try to mount it and check for private info
Installed Software
Useful software
Enumerate useful binaries
Also, check if any compiler is installed. This is useful if you need to use some kernel exploit as it's recommended to compile it in the machine where you are going to use it (or in one similar)
Vulnerable Software Installed
Check for the version of the installed packages and services. Maybe there is some old Nagios version (for example) that could be exploited for escalating privileges… It is recommended to check manually the version of the more suspicious installed software.
If you have SSH access to the machine you could also use openVAS to check for outdated and vulnerable software installed inside the machine.
Note that these commands will show a lot of information that will mostly be useless, therefore it's recommended some application like OpenVAS or similar that will check if any installed software version is vulnerable to known exploits
Processes
Take a look to what processes are being executed and check if any process has more privileges than it should (maybe a tomcat being executed by root?)
Always check for possible electron/cef/chromium debuggers running, you could abuse it to escalate privileges. Linpeas detect those by checking the --inspect
parameter inside the command line of the process.
Also check your privileges over the processes binaries, maybe you can overwrite someone.
Process monitoring
You can use tools like pspy to monitor processes. This can be very useful to identify vulnerable processes being executed frequently or when a set of requirements are met.
Process memory
Some services of a server save credentials in clear text inside the memory. Normally you will need root privileges to read the memory of processes that belong to other users, therefore this is usually more useful when you are already root and want to discover more credentials. However, remember that as a regular user you can read the memory of the processes you own.
GDB
If you have access to the memory of a FTP service (for example) you could get the Heap and search inside of it the credentials.
GDB Script
/proc/$pid/maps & /proc/$pid/mem
For a given process ID, maps shows how memory is mapped within that processes' virtual address space; it also shows the permissions of each mapped region. The mem pseudo file exposes the processes memory itself. From the maps file we know which memory regions are readable and their offsets. We use this information to seek into the mem file and dump all readable regions to a file.
/dev/mem
/dev/mem
provides access to the system's physical memory, not the virtual memory. The kernels virtual address space can be accessed using /dev/kmem.
Typically, /dev/mem
is only readable by root and kmem group.
Tools
To dump a process memory you could use:
https://github.com/hajzer/bash-memory-dump (root) - You can manually remove root requirements and dump process owned by you
Script A.5 from https://www.delaat.net/rp/2016-2017/p97/report.pdf (root is required)
Credentials from Process Memory
Manual example
If you find that the authenticator process is running:
You can dump the process (see before sections to find different ways to dump the memory of a process) and search for credentials inside the memory:
mimipenguin
The tool https://github.com/huntergregal/mimipenguin will steal clear text credentials from memory and from some well known files. It requires root privileges to work properly.
Feature
Process Name
GDM password (Kali Desktop, Debian Desktop)
gdm-password
Gnome Keyring (Ubuntu Desktop, ArchLinux Desktop)
gnome-keyring-daemon
LightDM (Ubuntu Desktop)
lightdm
VSFTPd (Active FTP Connections)
vsftpd
Apache2 (Active HTTP Basic Auth Sessions)
apache2
OpenSSH (Active SSH Sessions - Sudo Usage)
sshd:
Scheduled/Cron jobs
Check if any scheduled job is vulnerable. Maybe you can take advantage of a script being executed by root (wildcard vuln? can modify files that root uses? use symlinks? create specific files in the directory that root uses?).
Cron path
For example, inside /etc/crontab you can find the PATH: PATH=/home/user:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
(Note how the user "user" has writing privileges over /home/user)
If inside this crontab the root user tries to execute some command or script without setting the path. For example: * * * * root overwrite.sh Then, you can get a root shell by using:
Cron using a script with a wildcard (Wildcard Injection)
If a script being executed by root has a “*” inside a command, you could exploit this to make unexpected things (like privesc). Example:
If the wildcard is preceded of a path like /some/path/* , it's not vulnerable (even ./* is not).
Read the following page for more wildcard exploitation tricks:
Cron script overwriting and symlink
If you can modify a cron script executed by root, you can get a shell very easily:
If the script executed by root uses a directory where you have full access, maybe it could be useful to delete that folder and create a symlink folder to another one serving a script controlled by you
Frequent cron jobs
You can monitor the processes to search for processes that are being executed every 1,2 or 5 minutes. Maybe you can take advantage of it and escalate privileges.
For example, to monitor every 0.1s during 1 minute, sort by less executed commands and deleting the commands that have beeing executed all the time, you can do:
You can also use pspy (this will monitor and list every process that start).
Invisible cron jobs
It's possible to create a cronjob putting a carriage return after a comment (without new line character), and the cron job will work. Example (note the carriege return char):
Services
Writable .service files
Check if you can write any .service
file, if you can, you could modify it so it executes your backdoor when the service is started, restarted or stopped (maybe you will need to wait until the machine is rebooted).
For example create your backdoor inside the .service file with ExecStart=/tmp/script.sh
Writable service binaries
Keep in mid that if you have write permissions over binaries being executed by services, you can change them for backdoors so when the services get re-executed the backdoors will be executed.
systemd PATH - Relative Paths
You can see the PATH used by systemd with:
If you find that you can write in any of the folders of the path you may be able to escalate privileges. You need to search for relative paths being used on service configurations files like:
Then, create a executable with the same name as the relative path binary inside the systemd PATH folder you can write, and when the service is asked to execute the vulnerable action (Start, Stop, Reload), your backdoor will be executed (unprivileged users usually cannot start/stop services but check if you can using sudo -l
).
Learn more about services with man systemd.service
.
Timers
Timers are systemd unit files whose name ends in . timer that control . service files or events. Timers can be used as an alternative to cron. Timers have built-in support for calendar time events, monotonic time events, and can be run asynchronously.
You can enumerate all the timers doing:
Writable timers
If you can modify a timer you can make it execute some existent systemd.unit (like a .service
or a .target
)
In the documentation you can read what the Unit is:
The unit to activate when this timer elapses. The argument is a unit name, whose suffix is not ".timer". If not specified, this value defaults to a service that has the same name as the timer unit, except for the suffix. (See above.) It is recommended that the unit name that is activated and the unit name of the timer unit are named identically, except for the suffix.
Therefore, in order to abuse this permissions you would need to:
Find some systemd unit (like a
.service
) that is executing a writable binaryFind some systemd unit that is executing a relative path and you have writable privileges over the systemd PATH (to impersonate that executable)
Learn more about timers with man systemd.timer
.
Enabling Timer
In order to enable a timer you need root privileges and to execute:
Note the timer is activated by creating a symlink to it on /etc/systemd/system/<WantedBy_section>.wants/<name>.timer
Sockets
In brief, a Unix Socket (technically, the correct name is Unix domain socket, UDS) allows communication between two different processes on either the same machine or different machines in client-server application frameworks. To be more precise, it’s a way of communicating among computers using a standard Unix descriptors file. (From here).
Sockets can be configured using .socket
files.
Learn more about sockets with man systemd.socket
. Inside this file some several interesting parameters can be configured:
ListenStream
,ListenDatagram
,ListenSequentialPacket
,ListenFIFO
,ListenSpecial
,ListenNetlink
,ListenMessageQueue
,ListenUSBFunction
: This options are different but as summary as used to indicate where is going to listen the socket (the path of the AF_UNIX socket file, the IPv4/6 and/or port number to listen...).Accept
: Takes a boolean argument. If true, a service instance is spawned for each incoming connection and only the connection socket is passed to it. If false, all listening sockets themselves are passed to the started service unit, and only one service unit is spawned for all connections. This value is ignored for datagram sockets and FIFOs where a single service unit unconditionally handles all incoming traffic. Defaults to false. For performance reasons, it is recommended to write new daemons only in a way that is suitable forAccept=no
.ExecStartPre
,ExecStartPost
: Takes one or more command lines, which are executed before or after the listening sockets/FIFOs are created and bound, respectively. The first token of the command line must be an absolute filename, then followed by arguments for the process.ExecStopPre
,ExecStopPost
: Additional commands that are executed before or after the listening sockets/FIFOs are closed and removed, respectively.Service
: Specifies the service unit name to activate on incoming traffic. This setting is only allowed for sockets with Accept=no. It defaults to the service that bears the same name as the socket (with the suffix replaced). In most cases, it should not be necessary to use this option.
Writable .socket files
If you find a writable .socket
file you can add at the beginning of the [Socket]
section something like: ExecStartPre=/home/kali/sys/backdoor
and the backdoor will be executed before the socket is created. Therefore, you will probably need to wait until the machine is rebooted.
Note that the system must be using that socket file configuration or the backdoor won't be executed
Writable sockets
If you identify any writable socket (now where are talking about Unix Sockets, not about the config .socket
files), then, you can communicate with that socket and maybe exploit a vulnerability.
Enumerate Unix Sockets
Raw connection
Exploitation example:
HTTP sockets
Note that there may be some sockets listening for HTTP requests (I'm not talking about .socket files but about the files acting as unix sockets). You can check this with:
If the socket respond with a HTTP request, then you can communicate with it and maybe exploit some vulnerability.
Writable Docker Socket
The docker socket is typically located at /var/run/docker.sock
and is only writable by root
user and docker
group.
If for some reason you have write permissions over that socket you can escalate privileges.
The following commands can be used to escalate privileges:
Use docker web API from socket without docker package
If you have access to docker socket but you can't use the docker binary (maybe it isn't even installed), you can use directly the web API with curl
.
The following commands are a example to create a docker container that mount the root of the host system and use socat
to execute commands into the new docker.
The last step is to use socat
to initiate a connection to the container, sending an attach request
Now, you can execute commands on the container from this socat
connection.
Others
Note that if you have write permissions over the docker socket because you are inside the group docker
you have more ways to escalate privileges. If the docker API is listening in a port you can also be able to compromise it.
Containerd (ctr) privilege escalation
If you find that you can use the ctr
command read the following page as you may be able to abuse it to escalate privileges:
RunC privilege escalation
If you find that you can use the runc
command read the following page as you may be able to abuse it to escalate privileges:
D-Bus
D-BUS is an inter-process communication (IPC) system, providing a simple yet powerful mechanism allowing applications to talk to one another, communicate information and request services. D-BUS was designed from scratch to fulfil the needs of a modern Linux system.
D-BUS, as a full-featured IPC and object system, has several intended uses. First, D-BUS can perform basic application IPC, allowing one process to shuttle data to another—think UNIX domain sockets on steroids. Second, D-BUS can facilitate sending events, or signals, through the system, allowing different components in the system to communicate and ultimately to integrate better. For example, a Bluetooth dæmon can send an incoming call signal that your music player can intercept, muting the volume until the call ends. Finally, D-BUS implements a remote object system, letting one application request services and invoke methods from a different object—think CORBA without the complications. **(From here).
D-Bus uses an allow/deny model, where each message (method call, signal emission, etc.) can be allowed or denied according to the sum of all policy rules which match it. Each or rule in the policy should have the own
, send_destination
or receive_sender
attribute set.
Part of the policy of /etc/dbus-1/system.d/wpa_supplicant.conf
:
Therefore, if a policy is allowing your user in anyway to interact with the bus, you could be able to exploit it to escalate privileges (maybe just listing for some passwords?).
Note that a policy that doesn't specify any user or group affects everyone (<policy>
).
Policies to the context "default" affects everyone not affected by other policies (<policy context="default"
).
Learn how to enumerate and exploit a D-Bus communication here:
Network
It's always interesting to enumerate the network and figure out the position of the machine.
Generic enumeration
Open ports
Always check network services running on the machine that you wasn't able to interact with before accessing to it:
Sniffing
Check if you can sniff traffic. If you can, you could be able to grab some credentials.
Users
Generic Enumeration
Check who you are, which privileges do you have, which users are in the systems, which ones can login and which ones have root privileges:
Big UID
Some Linux versions were affected by a bug that allow users with UID > INT_MAX to escalate privileges. More info: here, here and here.
Exploit it using: systemd-run -t /bin/bash
Groups
Check if you are a member of some group that could grant you root privileges:
Clipboard
Check if anything interesting is located inside the clipboard (if possible)
Password Policy
Known passwords
If you know any password of the environment try to login as each user using the password.
Su Brute
If don't mind about doing a lot of noise and su
and timeout
binaries are present on the computer you can try to brute-force user using su-bruteforce.
Linpeas with -a
parameter also try to brute-force users.
Writable PATH abuses
$PATH
If you find that you can write inside some folder of the $PATH you may be able to escalate privileges by creating a backdoor inside the writable folder with the name of some command that is going to be executed by a different user (root ideally) and that is not loaded from a folder that is located previous to your writable folder in $PATH.
SUDO and SUID
You could be allowed to execute some command using sudo or they could have the suid bit. Check it using:
Some unexpected commands allows you to read and/or write files or even execute command. For example:
NOPASSWD
Sudo configuration might allow a user to execute some command with another user privileges without knowing the password.
In this example the user demo
can run vim
as root
, it is now trivial to get a shell by adding an ssh key into the root directory or by calling sh
.
SETENV
This directive allows the user to set an environment variable while executing something:
This example, based on HTB machine Admirer, was vulnerable to PYTHONPATH hijacking in order to load an arbitrary python library while executing the script as root:
Sudo execution bypassing paths
Jump to read other files or use symlinks. For example in sudeores file: hacker10 ALL= (root) /bin/less /var/log/*
If a wilcard is used (*), it is even easier:
Countermeasures: https://blog.compass-security.com/2012/10/dangerous-sudoers-entries-part-5-recapitulation/
Sudo command/SUID binary without command path
If the sudo permission is given to a single command without specifying the path: hacker10 ALL= (root) less you can exploit it by changing the PATH variable
This technique can also be used if a suid binary executes another command without specifying the path to it (always check with strings the content of a weird SUID binary).
SUID binary with command path
If the suid binary executes another command specifying the path, then, you can try to export a function named as the command that the suid file is calling.
For example, if a suid binary calls /usr/sbin/service apache2 start you have to try to create the function and export it:
Then, when you call the suid binary, this function will be executed
LD_PRELOAD
LD_PRELOAD is an optional environmental variable containing one or more paths to shared libraries, or shared objects, that the loader will load before any other shared library including the C runtime library (libc.so) This is called preloading a library.
To avoid this mechanism being used as an attack vector for suid/sgid executable binaries, the loader ignores LD_PRELOAD if ruid != euid. For such binaries, only libraries in standard paths that are also suid/sgid will be preloaded.
If you find inside the output of sudo -l
the sentence: env_keep+=LD_PRELOAD and you can call some command with sudo, you can escalate privileges.
Save as /tmp/pe.c
Then compile it using:
Finally, escalate privileges running