Category: Web Exploitation
Difficulty: Medium
Points: 100
Description
The server accepts an XML body at a /data endpoint. A scripts endpoint leaks some JavaScript, and the main page hints that the backend parses XML directly.
Overview
- The vulnerability is an XML External Entity (XXE) injection.
- The server parses an attacker-controlled XML body without disabling external entity resolution.
- This allows reading arbitrary files from the server filesystem.
Solution
Step 1: Identify the Attack Surface
- Fetching the main page and its linked scripts reveals the server accepts XML POST requests to
/data. - No input sanitization or DOCTYPE restriction is applied server-side.
Step 2: Craft the XXE Payload
- An XXE payload defines a custom entity that maps to a local file via the
file://URI scheme. - The entity is then referenced inside the XML body, causing the parser to substitute the file contents.
data = '<?xml version="1.0" encoding="UTF-8"?>' \
'<!DOCTYPE data [<!ENTITY file SYSTEM "file:///etc/passwd">]>' \
'<data><ID>&file;</ID></data>'
r = requests.post(url + "/data", data=data)
- The server returns the contents of
/etc/passwdembedded in the response.
Step 3: Extract the Flag
- The flag appears in the last line of the parsed response.
- Splitting on newlines and taking the final element isolates it.
result = r.text.splitlines()[-1].split(":")[-1]
Why XXE Works Here
- XML parsers that support the DOCTYPE declaration can resolve
SYSTEMentities pointing to external resources. - If the server does not explicitly disable external entity processing (e.g. via
libxml2’sLIBXML_NOENTflag or an equivalent), anySYSTEMentity reference is resolved. - The fix is to disable DTD processing entirely or use a safe XML parser configuration.
Flag
picoCTF{XML_3xtern@l_3nt1t1ty_e79a75d4}