HTB - Academy
HTB - Academy
HTB - Academy
Difficulty: Easy
Classification: Official
Synopsis
Academy is an easy difficulty Linux machine that features an Apache server hosting a PHP
website. The website is found to be the HTB Academy learning platform. Capturing the user
registration request in Burp reveals that we are able to modify the Role ID, which allows us to
access an admin portal. This reveals a vhost, that is found to be running on Laravel. Laravel
debug mode is enabled, the exposed API Key and vulnerable version of Laravel allow us carry out
a deserialization attack that results in Remote Code Execution. Examination of the Laravel .env
file for another application reveals a password that is found to work for the cry0l1t3 user, who
is a member of the adm group. This allows us to read system logs, and the TTY input audit logs
reveals the password for the mrb3n user. mrb3n has been granted permission to execute
composer as root using sudo , which we can leverage in order to escalate our privileges.
Skills Required
Web Enumeration
Linux Enumeration
Skills Learned
Laravel Token Deserialization
Composer
pam_tty_audit
Enumeration
ports=$(nmap -p- --min-rate=1000 -T4 10.10.10.215 | grep ^[0-9] | cut -d '/' -f
1 | tr '\n' ',' | sed s/,$//)
nmap -p$ports -sC -sV 10.10.10.215
Nmap reveals that an OpenSSH Server is running at port 22 and the banner reveals that this is a
Ubuntu Linux server. An Apache server is running at port 80 hosting a site with the title "Hack
The Box Academy". We also have a MySQL server running on port 33060. Let's enumerate the
website on port 80.
Upon registering, the website redirects us to a welcome page before redirecting back to the login
page. Let's login with our credential.
The website displays modules from Hack The Box Academy, but there doesn't seem to be any
additional functionality available that we could exploit. Let's enumerate for hidden directories
and files. We will be using dirsearch, but feel free to use other directory brute force tools.
Dirsearch comes with its own wordlists which can be found in the db/ folder.
Dirsearch reveals a lots of PHP files of which admin.php is the most interesting. Browsing to
/admin reveals a login page. Attempting to login with our registered user fails. Let's try to
register a new account again, examine the request in Burp Suite and see if we can bypass the
login.
Documentation to help configure Burp Suite is available here. Let's enable intercept mode and
register a new user.
uid=testuser2&password=password123%40&confirm=password123%40&roleid=0
We see a POST request sent to register.php with uid as the username, password as the
password and the parameter roleid , which is set to 0. Maybe this parameter is being used to
control application permissions? Lets change it from 0 to 1 and see if anything changes.
uid=testuser2&password=password123%40&confirm=password123%40&roleid=1
Logging into login.php with our new credentials doesn't provide us with any additional
functionality, but this time we are able to login at /admin.php .
After logging on we're greeted with an "Academy Launch Planner". There are several items that
have been completed, but the last item is still pending (Fix issue with dev-staging-
01.academy.htb). Let's add this host to our hosts file, disable the proxy and browse to it.
The first line of the readme.md states that Ignition is a beautiful and customizable error
page for Laravel applications running on Laravel 5.5 and newer. The debug UI on the
machine is different to this, so we can assume that it's running an older version, possibly around
Laravel 5x. Laravel in debug mode can also return sensitive information such as the API Key or
MySQL credentials, which can be found on scrolling down to the "Environment Variables" section.
Foothold
Searching online for Laravel 5.X exploit , we come across this Exploit-DB page. The exploit
explains that it's possible to get remote code execution when the Laravel API key is leaked. We
can run any code we want via the HTTP X-XSRF-TOKEN header because it makes an insecure
unserialize call to Illuminate/Encryption/Encrypter.php . In order to understand the
impact of compromised Laravel API, we have to understand how Laravel session cookies work.
Let's look at this Laravel session.
'laravel_session=eyJpdiI6IlpIVnRiWGtnWkdGMFlRbz0iLCJ2YWx1ZSI6IlptOXlYM1JsYzNScGJ
tY0s9IiwibWFjIjoiMTgwOWY4Y2MyM2JkOWQyZWRjYTEyOGZjODQ1NTQzNzcyZGEyYWY2ZDlhZjJhOWN
iODlkMDA5NDQzNjQwYTBhZiIsImFsZyI6IkhTMjU2In0.e30.OKPz-
dlTXA5jE7Iy5SKTK4FpJi3Grbd85bIBv6tYofQ'
Laravel sessions are JSON objects, which can be decoded using jwt.io.
In this JSON Object we have an iv (initialization vector), which is randomly generated data.
value is an encrypted value, and mac stands for message authentication code. Laravel
calculates these values using PHP OpenSSL. There are two functions inside Encrypter.php ,
encrypt and decrypt. Let's examine them.
In this encrypt function of Laravel, it generates the iv and value using OpenSSL and serializes
them. It also generates a mac using iv and value , before returning JSON encoded object as
output. Let's now take a look at the decrypt function.
In this function, it's getting the iv and value in order to decrypt the data before unserializing
the decrypted variable. If we provide it with a valid JSON object it will attempt to unserialize it
and should allow us to execute any command we want. There is a Python exploit for this
vulnerability. Let's see how this exploit works.
wget https://raw.githubusercontent.com/aljavier/exploit_laravel_cve-2018-
15133/main/pwn_laravel.py
It has three main functions: generate_payload , encrypt and exploit . We'll examine them one
by one.
def generate_payload(cmd, key, method=1):
# Porting phpgcc thing for Laravel RCE php objects - code mostly borrowed
from Metasploit's exploit
if method == 1: # Laravel RCE1
payload_decoded = 'O:40:"Illuminate\\Broadcasting\\PendingBroadcast":2:
{s:9:"' + "\x00" + '*' + "\x00" + 'events";O:15:"Faker\\Generator":1:{s:13:"' +
"\x00" + '*' + "\x00" + 'formatters";a:1:{s:8:"dispatch";s:6:"system";}}s:8:"' +
"\x00" + '*' + "\x00" + 'event";s:' + str(len(cmd)) + ':"' + cmd + '";}'
<SNIP>
value = base64.b64encode(payload_decoded.encode()).decode('utf-8')
key = base64.b64decode(key)
return encrypt(value, key)
This function has contains payload data that contains a cmd variable. This data is base64-
encoded and assigned to the value variable. It then base64-decodes the leaked Laravel API key
and assigns this value to the variable key . At the end, it calls the encrypt function, passing those
two variables. Let's take a look at the encrypt function.
This function uses the cipher module to encrypt the mac , vi and value . The data { 'iv':
iv_base64, 'value': payload, 'mac': hashed_mac} is base64-encoded and returned as
output.
The exploit function takes in the payload and makes a POST request to web application with
the X-XSRF-TOKEN header. Now we understand what it's doing, let's run the exploit and attempt
to get a reverse shell. We are providing the URL and leaked APP_KEY as a positional argument,
and specify interactive mode.
cat /var/www/html/academy/.env
Attempting to login into MySQL using the mysql client with these credentials fails. However,
password reuse is very common, let's enumerate the system users and see if any of them use the
same password. We can read /etc/passwd in order to get all users on this system, this file
contains an entry for all users including their UID, home directory and default shell.
cat /etc/passwd
The password is found to work with the cry0l1t3 user. We can login as cry0l1t3 with the
password mySup3rP4s5w0rd!! using su.
su cry0l1t3
The id command reveals that this user is a member of adm group. The adm group allows users
to read system logs. In Linux all logs are located inside the /var/log folder. Lets change the
directory to /var/log and list the log files.
There are lots of logs but the most interesting one is audit . Let's search online and learn more
about it.
The Linux kernel logs a lot of things but by default it doesn't log TTY input. The audit log allows
sysadmins to log this. If logging of TTY input is enabled, any input including passwords are stored
hex-encoded inside /var/log/audit/audit.log . We can decode these values manually or use
the aureport utility to query and retrieve records of TTY input. To learn more about PAM TTY see
this page. Let's query all TTY logs.
aureport --tty
The TTY report reveals that the mrb3n user logged in with the password mrb3n_Ac@d3my! using
su . Let's do the same.
su mrb3n
Privilege Escalation
Running sudo -l with correct password reveals that mrb3n has a sudo entry allowing them to
run composer as root.
sudo -l
There is an entry on GTFOBins for composer. It involves creating a composer.json file with a
"scripts" property. Composer allow users to execute system command using script options. We
can learn more about it here.
After inputting these commands, we successfully obtain a shell as root and can access the
root.txt.
TF=$(mktemp -d)
echo '{"scripts":{"x":"/bin/sh -i 0<&3 1>&3 2>&3"}}' >$TF/composer.json
sudo composer --working-dir=$TF run-script x