Overview
Windows Server 2022 (build 10.0.20348). Stack: Apache XAMPP + PHP 8.1.
| Stage | Technique | Result |
|---|---|---|
| Recon | nmap: 22 (SSH), 80 (HTTP), 3389 (RDP) | Windows, a video upload form |
| Foothold | .wax/.asx playlist leaks Net-NTLMv2 via Responder | hash for MEDIA\enox |
| Crack | hashcat -m 5600 + rockyou | enox:1234virus@ |
| Access | SSH (WinRM/5985 is closed) | shell as enox |
| Lateral | NTFS junction from Uploads\<md5> to C:\xampp\htdocs | write a webshell as Apache |
| Shell | webshell + reverse shell | nt authority\local service |
| PrivEsc | FullPowers (recover SeImpersonate) then GodPotato | nt authority\system |
Two official paths to SYSTEM:
- FullPowers then GodPotato (abusing
SeImpersonatePrivilege) - HTB official: abuse
SeTcbPrivilegevia theTcbElevationPoC (add a user to Administrators)
Reconnaissance
| |
- TTL 127: a Windows host, one hop.
- SSH on Windows (OpenSSH
for_Windows_9.5): unusual, but this is the login path (WinRM 5985 is closed, soevil-winrmis out). - Apache
2.4.56 (Win64) ... PHP/8.1.17: default XAMPP. - The default Apache 404 confirms XAMPP and leaks versions.
Web: a “ProMotion Studio” site with an upload form. The field description states the file is opened in Windows Media Player, which is the whole attack surface.
feroxbuster -x php finds /phpmyadmin, /webalizer, /examples (403/503), typical
XAMPP dead ends.
Initial Access
Net-NTLMv2 theft via a WMP file
WMP playlist files (.wax, .asx, .m3u) can point at a remote resource over UNC
(file://server\... or \\server\...). When WMP on the server opens such a file, it
tries to fetch the stream from the given host and automatically authenticates with its
NTLM hash (SMB auth). Point it at your machine running Responder and you capture the
Net-NTLMv2 for the account that opened the file (here the review.ps1 automation running
as enox).
Reference: Morphisec, “NTLM Privilege Escalation: The Unpatched Microsoft
Vulnerabilities” (example #4 is .wax).
Minimal .wax (XML/ASX format):
| |
Or with a tool:
| |
.wax and .asx work reliably. .m3u only fires on interactive open.
Capture and crack:
| |
Login:
| |
A closed WinRM does not mean no access; OpenSSH is increasingly common on Windows. Always check 22.
Lateral Movement
NTFS junction to the web root
Goal: from enox (a low-privilege user) write a PHP file into the web root for RCE as the
Apache account (LOCAL SERVICE), which has more privileges.
Source (C:\xampp\htdocs\index.php):
| |
Three critical facts:
The folder name is predictable:
md5(firstname + lastname + email), computable offline:1echo -n "[email protected]" | md5sum # -> 317d52e7c825dd847d9c750a35547edcif (!file_exists(...)): if the folder already exists (because we replace it with a junction), PHP does not overwrite it.move_uploaded_fileruns as the Apache process (LOCAL SERVICE), so the write happens with Apache’s privileges, not ours.
Step by step:
| |
Webshell:
| |
| |
An NTFS junction is a reparse point that works only for directories; a reference to it is
transparently redirected to the target. Unlike symlinks, a junction does not require admin
rights or SeCreateSymbolicLinkPrivilege; a regular user can create one given write
access to the source directory. The attack: a higher-privileged process (Apache = LOCAL
SERVICE) follows the link and performs an operation (a file write) in a location we could
not write to, but it can. This is link-following file operation abuse.
Reading icacls Output
icacls prints ACLs: who can do what with a file or folder. One line (an ACE) is:
| |
Permission masks:
| Short | Meaning | Offensive meaning |
|---|---|---|
F | Full control | Everything: write, delete, change ACL, take ownership |
M | Modify | Write + read + delete (not ACL change) |
RX | Read & execute | Read + run |
R | Read only | Read |
W | Write only | Write (append data/files) |
D | Delete | Delete |
WD | Write DAC | Change permissions (dangerous) |
WO | Write Owner | Take ownership (dangerous) |
They can also appear expanded in brackets, for example (DE,WDAC,WO,...) (DE=delete,
WDAC=write DAC, WO=write owner, GA=generic all).
Inheritance flags:
| Flag | Name | Meaning |
|---|---|---|
(I) | Inherited | The rule was inherited from the parent, not set directly |
(OI) | Object Inherit | Files in this folder inherit the rule |
(CI) | Container Inherit | Subfolders inherit the rule |
(IO) | Inherit Only | The rule does NOT apply to this object, only to objects inheriting from it |
(NP) | No Propagate | Inheritance only one level down |
The most important offensive distinction:
(OI)(CI)without(IO): the rule applies to this object AND its children.(OI)(CI)(IO): the rule applies only to children, NOT to the object itself. This is a trap when skim-reading: you see “Full” and think you have Full on the folder, but(IO)means only on what is created inside it.
The uploads folder (icacls * in C:\Windows\Tasks\Uploads):
| |
Everyone:(I)(OI)(CI)(F): everyone has Full control, inherited, propagated to files and folders. Soenoxcan delete and create objects here, which means it can delete the folder and plant a junction. This is what enables the attack.BUILTIN\Administrators:(I)(F): admins have Full on the object itself....:(I)(OI)(CI)(IO)(F): an inheritance-only entry (IO), does not apply to this object. Ignore it when assessing “what can I do here”.
The web root (icacls C:\xampp\htdocs):
| |
NT AUTHORITY\LOCAL SERVICE:(I)(OI)(CI)(F): the Apache account has Full control on htdocs, so it can writeshell.php.BUILTIN\Users:(I)(OI)(CI)(RX): ifenoxtried to write to htdocs directly, it would get onlyRX(read/execute), no write.
That is the whole point of the junction attack: enox has no write to htdocs but has Full
on the uploads folder, and Apache (which has write to htdocs) performs the write for us,
redirected through the junction.
What to look for in icacls:
Everyone:(...)(F/M/W)orBUILTIN\Users:(...)(F/M/W)where it should not be: a misconfiguration, almost always exploitable.(F),(M),(W),(WD),(WO)for your account on a service binary, scheduled script or DLL: a potential privesc.(IO): does not apply to the object itself, only to future children.(I): only tells you the origin (inherited vs explicit), not what you can do.
Privilege Escalation
After a reverse shell as nt authority\local service (PowerShell #3 Base64 from
revshells.com, delivered through the webshell), the real privesc begins.
Trimmed privileges
| |
| |
No SeImpersonatePrivilege. Service accounts (LOCAL SERVICE, NETWORK SERVICE, IIS/Apache)
normally have it by default, which is their Achilles’ heel. Here the privilege set has
been deliberately trimmed (token filtering / service configuration) to make potato
attacks harder.
FullPowers, recovering the default privilege set
FullPowers (itm4n) exploits the fact that service accounts should by definition have the
full default privilege set. It creates a Task Scheduler task in the service account’s
context; the process spawned by the scheduler gets a fresh token with the full default
set, including SeAssignPrimaryTokenPrivilege and SeImpersonatePrivilege. FullPowers
then runs the given process (our reverse shell) in that context.
| |
After the new reverse shell connects:
| |
| |
GodPotato, abusing SeImpersonatePrivilege
SeImpersonatePrivilege (“Impersonate a client after authentication”) lets a process take
the security context (token) of a client that authenticated to it. Legitimate for
services; abused as follows:
- The attacker stands up an endpoint (named pipe / COM / RPC).
- Coerces a high-privileged process (running as SYSTEM) to authenticate to that endpoint.
- With
SeImpersonate, takes the SYSTEM token of that connection and creates a process in the SYSTEM context.
The potato family:
- RottenPotato / JuicyPotato: older, DCOM/NTLM reflection; JuicyPotato does not work on newer Windows (10 1809+ / Server 2019+).
- PrintSpoofer: coerce via the Print Spooler service (named pipe).
- RoguePotato / SweetPotato: newer DCOM variants.
- GodPotato: universal, based on DCOM/RPC (RPCSS) abuse; works from Win8 / Server 2012 to Server 2022. The default choice here.
| |
GodPotato finds a SYSTEM token (PID:888 ... NT AUTHORITY\SYSTEM), unmarshals a DCOM
object, impersonates and starts a process as SYSTEM.
| |
Alternative path, SeTcbPrivilege
The official HTB writeup uses SeTcbPrivilege (“Act as part of the operating system”),
one of the most powerful Windows privileges: it lets code create tokens and impersonate
any user, acting as part of the TCB (Trusted Computing Base).
PoC TcbElevation (compile:
x86_64-w64-mingw32-g++ TcbElevation.cpp -o TcbElevation.exe -lsecur32 -municode):
| |
Then log in over SSH as enox (now an Administrator). Confirm groups with
whoami /groups (BUILTIN\Administrators, S-1-5-114).
Check whoami /priv for the privilege you have: SeImpersonate /
SeAssignPrimaryToken -> potato; SeTcb -> act-as-OS PoC; SeBackup / SeRestore ->
copy SAM/SYSTEM; SeDebug -> inject into a SYSTEM process.
Detection and Mitigation
- Never open untrusted WMP/playlist files on a server automatically; they force NTLM auth over UNC. Block outbound SMB (445/139) and disable automatic NTLM fallback.
- Enforce strong passwords:
1234virus@fell in seconds against rockyou. - Application: do not use predictable path names (md5 of user data), validate extensions server-side, store outside the web root, disable PHP execution in the uploads directory.
- Protect against link-following: higher-privileged processes should not follow links
created by lower-privileged accounts (redirection guard /
ProcessMitigation). - Do not trim a service privilege “halfway”: removing
SeImpersonatewithout blocking Task Scheduler achieves nothing (FullPowers recovers it). Harden service accounts fully and monitor task creation.
Lessons Learned
- A closed WinRM does not mean no access; check SSH on Windows.
- A junction redirects a higher-privileged process’s write into a location you cannot reach.
(IO)inicaclsmeans the ACE applies only to future children.- FullPowers proves that trimming
SeImpersonatealone is not a mitigation.
Command Reference
| |