Python Library Hijacking on Linux (with examples)

Cristian Cornea
Analytics Vidhya
Published in
5 min readJun 1, 2020
(Photo by David Clode on Unsplash)

In this article, we will discuss three effective methods to hijack the Python library in a Linux environment.

Why is it important?

Let’s see… What happens if a Python script runs with sudo privileges, but you have got write permissions on the imported module?

Exactly! You can escalate your privileges by editing the imported functions to call system commands or even spawn a shell, that will have root rights.

Methods to abuse this issue

I am going to share three scenarios where anybody can exploit this vulnerability (or better call it a “security misconfiguration”):

  1. Write Permissions on Imported Python Module
  2. Higher Priority Python Library Path with Broken Privileges
  3. Redirecting Python Library Search through PYTHONPATH Environment Variable

Common Requirement

Each scenario has a specific requirement in common. The Python script must meet one of the following conditions for a successful privilege escalation attempt:

  • Script must be compiled into a binary format that presents SUID permissions of a higher privileged user (the executable will inherit the owner’s privileges). You can search for SUID files within a Linux system, through the following command:
find / -perm /4000
  • Script must be compiled into a binary format that presents SGID permissions of a higher privileged group (the script will inherit the group owner’s privileges). You can search for SGID files within a Linux system, through the following command:
find / -perm /4000

Or you can search for files that have both SUID and SGID permissions:

find / -perm /6000
  • Script can be initiated using SUDO and can run under root. You can check if this is possible by entering the following command through the terminal:
sudo -l

SCENARIO 1: Write Permissions on Imported Python Module

Let’s suppose we have a Python script that imports the base64 module and calls the b64encode function from this module, in order to encode a specific string.

Now, let’s locate the base64 module path within the Linux file system.

Got it under many paths (because I have more Python versions installed), but our attention should fall on the Python3.7 path:

/usr/lib/python3.7/base64.py

Let’s check the permissions of the Python module.

We can clearly see that it got read, write, and execute permissions for everyone.

Next, the b64encode function within that file must be edited in order to execute a system command such as whoami.

Save the file, return to the terminal and type the following command to check which files we can run with sudo:

sudo -l

And here we are, after running the script:

We can notice that whoami system command got executed and returned expected results.

SCENARIO 2: Higher Priority Python Library Path with Broken Privileges

When importing a module within a script, Python will search that module file through some predefined directories in a specific order of priority, and it will pick the first occurrence.

For example, on Ubuntu, the default searching priority is the following:

/usr/lib/pythonX
/usr/lib/pythonX/plat-x86_64-linux-gnu
/usr/lib/pythonX/lib-tk
/usr/lib/pythonX/lib-old
/usr/lib/pythonX/lib-dynload
/usr/local/lib/pythonX/dist-packages
/usr/lib/pythonX/dist-packages
X - Python Version (2.6, 2.7, 3.7, and so on)

You can find your order, based on your Python version, with the following command:

pythonX -c 'import sys; print("\n".join(sys.path))'X - Python Version (2.6, 2.7, 3.7, and so on)

Maybe you already figured out how the attack works, if not, I am going to explain it in the paragraph below.

The searched module will be located in one of the defined paths, but if Python finds a module with the same name in a folder with higher priority, it will import that module instead of the “legit” one.

The requirement for such a method to work, is to be able to create files in folders above the one in which the module resides.

We will use the same hijack.py script, but I moved the base64.py module to a lower priority folder within the directories hierarchy, so now the /usr/lib/python3.7/ folder doesn’t contain the module anymore.

The above screenshot provides the actual folders priority hierarchy for Python Library search, on my local machine.

Next, I’ll check the privileges for /usr/lib/python3.7.

And there it is, the folder has read, write and execute permissions, so we can create our custom base64.py module inside.

The malicious module must contain a function definition as the one called through the Python script (in our case b64encode), and with the exact number of arguments (in our case, just a string is parsed as an argument, so we will define the function with a single one, called “a”).

Now, save the module, run the script, and notice that the payload was successfully executed.

SCENARIO 3: Redirecting Python Library Search through PYTHONPATH Environment Variable

The PYTHONPATH environment variable indicates a directory (or directories), where Python can search for modules to import.

It can be abused if the user got privileges to set or modify that variable, usually through a script that can run with sudo permissions and got the SETENV tag set into /etc/sudoers file.

In our example, I moved the Python module to the /tmp/ folder.

Let’s check if the SETENV tag is set, through the “sudo -l” command:

And now, we can run the script like this:

There it is!

Prevention Tips

Do not set write permissions for users, on folders where Python modules are located.

Restrict access to specific modules through virtual environments rather than letting Python search through the folders.

I really hope this article was useful and wish you all a great day!

--

--

Cristian Cornea
Analytics Vidhya

🇷🇴 Founder: Zerotak Security | Cyber Security Training Centre of Excellence (CSTCE) | SectionX.io | BSides Transylvania