Vulnhub's newest VM Underdist was a great challenge for me. What follows is my walkthrough from start to root, enjoy!
Nmap scan report for Underdist (192.168.100.147) Host is up (0.015s latency). Not shown: 65533 closed ports PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 6.0p1 Debian 4+deb7u2 (protocol 2.0) 25/tcp open smtp Postfix smtpd 80/tcp open http Apache httpd 2.2.22 ((Debian)) MAC Address: 08:00:27:07:BD:56 (Cadmus Computer Systems) Service Info: Host: Underdist; OS: Linux; CPE: cpe:/o:linux:linux_kernel
Taking a look at what was available via HTTP revealed some snazzy ASCII art but otherwise nothing remarkable. Naturally, I checked the page source which revealed an HTML comment pointing to a PHP script with some base64 encoded URL parameter (Figure 1). Following the link, I was taken to another page with an ASCII art 404. A quick decode of the base64 encoded URL parameter revealed the text 'ascii1.txt'. While I was doing this, I had
dirb running in the background. The results revealed a folder structure (Figure 2), within which was the file 'ascii1.txt'! This meant that there was a potential LFI vulnerability available to me, as the URL parameter was equal to the base64 encoded value of 'ascii1.txt', which was found in
/ascii/letras/ascii1.txt. After a bit of prodding, I was able to successfully exploit the LFI vulnerability by base64 encoding the string
../../../../etc/passwd and using it as the URL parameter for the PHP script (Figure 3).
Finding a Way In
/etc/passwd, my first thing to check was weak user passwords. Users
underside both looked particularly interesting, however when attempting SSH logins to both accounts, I was denied due to a publickey error. This meant that I should probably be on the lookout for a private key somewhere on the file system.
Now with the ability to read files on the target system, I set out to identify and access any files I could to find a way in. Initially I had thought that I might be able to attempt a HTTP log poisoning vector. To accomplish this I would have to first locate and be able to read the Apache error log. After reading the Apache config files on the target I attempted to read the log files, but I was unable to do so. The next couple hours I poured over what files I did have access to to try and think of another vector.
After some time, I concluded that I might be able to leverage the open Postfix service to send an email to a user and then utilize the LFI vulnerability to render arbitrary PHP code by reading the contents of the email. Knowing that email files are kept in
/var/mail, I had to then determine valid user accounts. For this, I fired up metasploit's
smtp_enum auxiliary scanning script and pointed it at my target. After some time, I got my results (Figure 4)! After many attempts, I determined that I could send an email via Postfix to user
www-data and then read it by pointing the PHP script to
../../../../var/mail/www-data. All other attempts failed most likely because I only had access to the file system via LFI as the default web user on the system. From here, I created a simple Python script to send a reverse php meterpreter payload as an email and have it read and executed when I viewed it via the PHP script (Figure 5). I then successfully had limited user access to the target (Figure 6)!
I had limited capabilities with my PHP meterpreter session, but I had a little more freedom to navigate and view files on the target. I discovered a folder and a file whose contents contained a RSA private key - likely the very key I needed to gain SSH access to the target (Figure 7). Sure enough, passing the private key to SSH as user
cuervo, I had indeed elevated my privileges to a user on the target (Figure 8)!
There wasn't anything remarkable in cuervo's home directory, so I set out to see what else I could find. In underdist's home directory I found two files of interest (Figure 9). Aptly named,
cronping.py was a script run via cron. This script read a file
ips.txt and each entry was used as raw, unsanitized input and passed directly to
Popen, a module that executes commands on the system (Figure 10). The best part about these files were that their permissions were not set properly which then allowed me to edit
ips.txt, thus allowing me to inject arbitrary code into the cron script and get code execution as user
underdist. I created a reverse shell payload with metasploit, uploaded it to the target and added this line to
127.0.0.1;/tmp/rs. In no time, the cron job was kicked off, and my reverse shell was opened, allowing me to escalate my access on the target to user
underdist (Figure 11).
#!/usr/bin/env/python import os def ips(): f=open("ips.txt") return f def save(d): f=open("/tmp/logs", "a+") f.write(d) f.close() def command(c): p=os.popen('ping -c 1 -w 1 %s|grep received|cut -d " " -f 4' % (c), "r") return p.read() def verify(): save("- - - - - - - - - - - - - - - - - - - - - - - - -\n") for ip in ips(): ip=ip.replace("\n", "") if command(ip)=="1\n": save("Host %s Up\n" % (ip)) else: save("Host %s Down\n" % (ip)) verify()
Is There an Echo? (echo, echo, echo...)
Now that I had full user access to user
underdist I was able to explore the rest of his home directory. I discovered a hidden folder
.bin which contained a lovely binary file
echo which was owned by root and had the setuid bit set (Figure 12). This meant that this was very likely my way to root!
I loaded up gdb (and also setup peda!) and commenced fuzzing the binary to see if I could use a buffer overflow attack and control code execution. I was indeed able to elicit a buffer overflow (Figure 13), so I had my work cut out for me! I used metasploit's
pattern_offset scripts to identify where in my buffer I had control over EIP. Using peda-gdb really made the exploit development process much easier. I was able to make quick work of searching for a
jmp esp instruction (there was none!).
After some dinner and plenty of head scratching, I determined what I needed to do. If I could point EIP to the location in memory of my A's (the beginning portion of my string buffer), I could replace my 'A's with NOP instructions and get a NOP sled to some shellcode and drop into a shell. For me, this was easier said than done. I repeatedly failed at finding a suitable memory address to jump to. The theory seemed correct, I just couldn't get it. Through trial and error I finally found a memory address that got me to my NOP sled.
The next task was finding a suitable shellcode. peda does a fantastic job of streamlining this step! Builtin to peda is the ability to search shell-storm.org's shellcode repository. I pulled up a small 23 byte shellcode, adjusted my buffer of NOPs, added my shellcode and my working memory address and ran it through gdb one last time - success!! (Figure 14)
Pulling a Rabbit from My Hat
All that was left for me to do was to close gdb and run my little buffer overflow string against the binary. As expected, my exploit was a success (Figure 15)! The exploit against the setuid binary gave me
euid=root! From here, I navigated to
/root and captured my flag (Figure 16)!!