Schooled is a medium rated box on hackthebox created by TheCyberGeek. It involves some amount of enumeration to discover a vhost, XSS to get to a privileged user and CVE in moodle to get a foothold on the machine. For the root part we will find credentials in a database which we crack with hashcat. Finally we will create our own malicious FreeBSD package to escalate to the root user.
User
Nmap
As usual we start our enumeration off with a nmap scan for a first recon on the machine. The scan shows ports 22, 80 and 33060 open against which we run an additional script and version detection scan.
All ports
1 |
|
Script and version
1 |
|
schooled.htb
Going to port 80 we can see a website for a school which seems to be completly static so it is not of much use to us. However there is a possible vhost name at the botton of the page.
moodle.schooled.htb
Teacher
Since there doesn’t seem to be much of an attack surface on the initial page and we discovered a vhost, we fuzz with ffuf for additional vhosts in the next step. This gets us the page moodle.schooled.htb
.
1 |
|
Adding it to our /etc/hosts
file and going to the page there is a moodle installation running. Moodle is a popular school software.
Going over to the login page we are can see that we are able to create a new account.
Trying to signup we get an error message stating we need a student.schooled.htb
email address.
Exchanging our email domain from a.com
to student.schooled.htb
we are able to successfully create an account.
Going over to Site home
and the mathematics course, we see that we can self enroll into it and that no enrolment key is required.
After enrolling we go over to announcements and the Reminder for joining students
contains some interesting information. New students are required to set their MoodleNet profile
and the teacher seems to be checking this. This means if we find a XSS vulnerability on the profile page we might be able to steal the teachers cookie and impersonate him.
Looking for vulnerabilties in the MoodleNet field in the user profile we find a possible stored XSS vulnerability in CVE-2020-25627, which seems to be just what we need to advance right now. Also the HttpOnly
flag for the session cookie is not set which promises success.
To exploit it we put this payload in the MoodleNet profile, editing the profile of the user we created.
We choose a payload that includes a javascript file hosted by use to have more room to work with.
1 |
|
After that we standup a python webserver on port 80, hosting a script with the following content and update the profile containing our payload.
a.js
1 |
|
1 |
|
The teacher looks every two minutes at the users profiles, so we get a hit on our webserver back relatively quick with the teachers session id.
1 |
|
Switching his session id with ours in the browser we are now logged in as Manuel Phillips and have some additional rights.
Manager
Going over to a course we can now click on the Moodle Docs for this page
link, which takes us to the corresponding Documentation of the running moodle version.
Having the version identified as 3.9 we can now look for additional CVE’s for this Version and find one in CVE-2020-14321. Following this PoC video on youtube and this github repository we are able to gain RCE on the server. The first step for this exploit is to find a user with the manager role assigned, which we then can in impersonate in a following step.
This user turns out to be Lianne. We navigate to the Participants menu in the mathematics course, click on enrol users and select Lianne.
Then we intercept the request in burp and send it to repeater. Following the video we turn off intercepting and switch the userlist parameter in the request to the profile id of Manuel which is 24, we also change the roletoassign
parameter to 1 and send the request in repeater. We can also assign additional roles to the user by changing the roletoassign
parameter to different values.
Only the manager role is important but we can proof to add about any role to the user repeating the process with different numbers.
Refreshing the participants page we see a lot of additional roles assigned to the teacher. Clicking on Lianne Carter we can log in as her due to our manager
role.
After logging in we see she has site administration privileges.
Following the PoC we browse to Site administration
=> Users
=> Define roles
=> Manager
=> Edit
to give ourselves the most permissions possible.
We set intercept in burp and click on save changes. In the request we change the permission for the ones listed in README.md of the earlier mentioned github repository. This gives us most possible access on the moodle installation.
RCE
Following the PoC we go to Site administration
=> Plugins
=> Install Plugins
=> Choose a file...
and select the rce.zip
we downloaded from the repository.
Unpacking the zip locally it contains a README.md
with the path for the uploaded webshell.
1 |
|
The README.md contains the path to the upload functionality and also the location the webshell get’s placed after unzipping and installing it.
After clicking on install and continue the plugin get’s successfully installed. Browsing to it and testing it we have achieved RCE on the server.
We send the request to burp repeater set up a ncat listener and send ourselves a reverse shell.
1 |
|
We get a connection back instantly. Python is not in the path to upgrade our shell but we can identify its location with a quick find command.
1 |
|
Database
After doing some enumeration on the machine we are able to find database credentials in /usr/local/www/apache24/data/moodle/config.php
. Using these credentials we are able to retrieve the password hashes from the moodle database.
1 |
|
The admin hash is of particular interest to us so we try to crack it with hashcat and are successful at it.
1 |
|
Since there are only 2 users steve and jamie on the machine we can try the password with ssh for both of them, are able to login as jamie with the password !QAZ2wsx
and grab the user flag.
1 |
|
Root
Manual package
Running sudo -l
as jamie we see he can update the pkg repository and als install random packages.
1 |
|
Looking at the config file for pkg we can see it points to the host devops.htb. The way this was intended to be solved was to use both the update and install command. That is why we are in the wheel group which can edit the /etc/hosts
file. We will first solve it this way and then cover a quicker simpler solution.
1 |
|
1 |
|
/etc/hosts
being writable means we can point the repository update to our machine hosting a repo with a package containing a malicious postinstall script. In this script we can run any command we want as root. I chose to give bash suid.
For the package creation these two blogposts are helpful.
Following them we can create our own package and make a repository out of it, which
we then copy over to our machine via scp. Since the necessary tools to create the repository are already on the machine we will do it there. There is also a cleanup script running on the machine so we will work out of a folder it does not clean. First we follow the blogpost to write a package creation script with a pre and postinstall hook giving bash the suid bit and create a copy of /etc/hosts
where devops.htb
get resolved to our ip.
create_packet.sh
1 |
|
/home/jamie/hosts
1 |
|
In a next step we create the necessary files and use pkg
to package them up to a repository.
1 |
|
We move the repository back to our machine with scp and host it with a python webserver.
1 |
|
1 |
|
Now we can install the package after copying our modified hosts
file over the real one.
1 |
|
Upon updating and installing it we get hits for the files on our webserver.
1 |
|
The code got executed and we can use the suid bash to escalate to the root user.
1 |
|
FPM package
There is also another method involving pkg and fpm which is much quicker than the intended one. There was no entry for pkg in gtfobins at the time for release, but it got added later by a HTB user after doing the box.
First we have to create the package with fpm using the following steps.
1 |
|
Now we can transfer the created package over with curl, install it with the --no-repo-update
flag, drop into a root shell and grab the flag.
1 |
|