Writeup for the Data Vault Web challenge from the Snyk ctf 2026 hosted by Nahamsec. It will teach you about how to abuse XML for local file inclusion. You can do this challenge for free on HackingHub.

Challenge description

DataVault is a secure JSON-based profile storage API. Can you find a way to access sensitive server files? Author: neetroxx

The front page looks like this:

None
Challenge homepage

Lets enter some values and use caido to intercept the request.

POST /api/profile HTTP/1.1
Host: 3n05amc0mch1.ctfhub.io
Accept: */*
Content-Type: application/json
Content-Length: 30

{
  "name":"test",
  "bio":"test"
} 

Not much to do here. But one thing you should always try is changing the Content-Type. It says it only accepts json payloads but a small detail you might have missed is the code symbol < / > next to the json symbol at the bottom of the form. If you inspect the html youll find its an icon with the class xml-icon. Endpoints that process json can often also process xml. (I talk more about this in this in my upload vuln blog post.)

We can start testing by setting: Content-Type: application/xml

add a simple payload for testing first:

<?xml version="1.0" encoding="UTF-8"?>
<user>
<name>test</name>
<bio>my bio</bio>
</user>

The response:

{
"received": {
"bio": "exampel",
"name": "test"
},
"source": "application/xml",
"status": "ok"
}

Good sign! Lets test for XXE (XML External Entity Injection). XXE can be used to read files from the victims computer. Here is an example payload for reading /etc/passwd:

None

You might notice the above is not a standard code cell but a screenshot of a code cell. That because i ran into an issue with medium when writing this blog. Medium wouldn't let me safe my draft for this story. I randomly figured out that the above payload actually triggered a security mechanism by Cloudflare to protect Medium from my evil XXE attack. This is a somewhat perfect example of the importance of this attack… I will definitely investigate this further (;

None
Medium crashed by a simple xxe payload ….

Anyway back to our ctf. (Were already there anyway). You can always try a few common files in this case the flag was in etc/passwd

 {

"received": {
"bio": "root:x:0:0:root:/root:/bin/bash\ndaemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin\nbin:x:2:2:bin:/bin:/usr/sbin/nologin\nsys:x:3:3:
sys:/dev:/usr/sbin/nologin\nsync:x:4:65534:sync:/bin:/bin/sync\ngames:x:5:60:games:/usr/games:/usr/sbin/nologin\nman:x:6:12:man:/var/cache/man:/usr/sbin/nologin\nlp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin\nmail:x:8:8:mail:/var/mail:/usr/sbin/nologin\nnews:x:9:9:news:/var/spool/news:/usr/sbin/nologin\nuucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin\nproxy:x:13:13:proxy:/bin:/usr/sbin/nologin\nwww-data:x:33:33:www-data:/var/www:/usr/sbin/nologin\nbackup:x:34:34:backup:/var/backups:/usr/sbin/nologin\nlist:x:38:38:
Mailing List Manager:/var/list:/usr/sbin/nologin\nirc:x:39:39:ircd:/run/ircd:/usr/sbin/nologin\n
_apt:x:42:65534::/nonexistent:/usr/sbin/nologin\nnobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin\n
datavault:x:1001:1001:flag{XX3_v!a_C0nt3nt_Typ3_Sw1tch}:/nonexistent:/usr/sbin/nologin\n",
"name": "test"

} 

If you read this far, your welcome to leave a comment what you wanna see next, i still don't have to many subscribers but saw a few of you even subscribed with email. If you want drop a comment and i will try my best to cover your interests