Description
SSH into the server and discover a hidden Python script you can run with sudo. The script imports base64, and you have write permission on base64.py in the Python library. Edit that file to inject a system call, then run the script with sudo to read the flag.
Setup
SSH into the provided server using the given credentials.
List hidden files in your home directory to find the server script.
Check what sudo allows you to run.
ssh <USER>@<HOST> -p <PORT>ls -lasudo -lSolution
Walk me through it- Step 1Discover the hidden script and sudo permissionsAfter logging in, list all files including hidden ones. There is a hidden file called .server.py in the home directory. Running sudo -l shows you can run python3 .server.py as root without a password.bash
ls -labashcat .server.pybashsudo -lLearn more
sudo -l lists the commands the current user can run with elevated privileges. The output shows something like
(root) NOPASSWD: /usr/bin/python3 /home/user/.server.py, meaning you can run that specific Python script as root without entering a password.The script itself imports
base64andos, and does something innocuous. The key is that it imports Python standard library modules, and those module files might be writable by your user. - Step 2Find the writable Python library fileCheck the permissions on the base64.py file in the Python standard library. It turns out to be writable by your user, which means you can inject code that will run when the script imports it.python
python3 -c 'import base64; print(base64.__file__)'bashls -la /usr/lib/python3.*/base64.pyLearn more
Python's
importstatement searches directories in order and executes the module file when it is first imported. If a module file is world-writable, any user can add arbitrary code to it. That code runs with whatever privileges the importing script has.This is a Python library hijacking attack. The misconfiguration is leaving a standard library file world-writable, which lets an unprivileged user inject code that runs as root when a sudo-enabled script imports that module.
- Step 3Inject code into base64.pyAdd an os.system() call at the top of base64.py to read and print the flag file. The existing code must remain intact so the import does not fail.python
python3 -c 'import base64; print(base64.__file__)'bash# Prepend a system call to base64.pybashecho 'import os; os.system("cat /challenge/metadata.json")' >> /usr/lib/python3.10/base64.pyLearn more
Appending code to the end of the module works because Python executes the module file from top to bottom on import. Adding a line at the end is safer than inserting at the beginning, since it does not break the existing function definitions that the script may rely on.
The flag is stored in
/challenge/metadata.json. That file is owned by root and not readable by your user directly, which is why privilege escalation is needed. - Step 4Run the script with sudo to trigger the injectionRun the server script with sudo. Python imports base64, executes your injected os.system() call as root, and the flag is printed to stdout.bash
sudo python3 .server.pyLearn more
When Python runs the sudo script, it imports base64. The import mechanism executes base64.py, which now contains your injected call. Since the script runs as root via sudo, the
os.system()call also runs as root, andcat /challenge/metadata.jsonreads and prints the flag.The fix for this misconfiguration: never leave Python standard library files writable by unprivileged users. Standard library permissions should be root-owned and not world-writable. For more on Linux privilege escalation see Linux CLI for CTF.
Flag
picoCTF{pYth0n_lIb_hIj4ck1ng_f56b6b5c}
Write access to base64.py lets you inject code that runs as root when the sudo script imports the module.