CVE-2024-6345 - How a Dangerous Bug in PyPA/setuptools’ package_index Module Could Let Attackers Run Code on Your Server

Summary:
In June 2024, a remote code execution vulnerability — CVE-2024-6345 — was disclosed in the popular Python packaging tool setuptools. The issue was buried in the package_index module and allowed attackers to run arbitrary code on machines that called vulnerable functions with untrusted data, such as URLs. This post breaks down how the bug works, which code is affected, how you can exploit it (with a simple demo), and, most importantly, how to protect yourself.

Where’s the Vulnerability?

If you’ve ever installed a Python package from source, chances are you’ve used setuptools. The package_index module pulls packages from various URLs. But up until version 69.1.1, the code that handled these URLs didn't properly sanitize user input. That means if your application—or build system—calls these download functions on user-provided URLs, an attacker could trick it into running code on your system.

Why is that Bad?

- Remote code execution: The vulnerability allows anyone who controls those URLs to run ANY shell command as the user running your process.

Supply chain risk: Attacks could happen during builds or installs.

- Cloud/CI/CD exposure: Continuous integration and deployment systems using unsafe setuptools versions are easy targets.

How the Exploit Works

Let’s go through a basic scenario. The vulnerable code is in the routine that *downloads* and *processes* package URLs. Here’s a simplified (and insecure) example from before the fix:

# Vulnerable snippet from setuptools <70. in package_index.py

import os

def download_file(url):
    os.system("curl -O {}".format(url))

Suppose the url is controlled by an attacker. What if they supply something like

http://example.com/file.tar.gz; rm -rf /

The resulting system command would be

curl -O http://example.com/file.tar.gz; rm -rf /

Now you see the problem. The attacker just added an extra destructive command!

In reality, the package_index code was more complex, but it allowed a similar injection if the right kind of payload was sent.

Suppose you have automation code like this (using an unsafe setuptools version)

from setuptools.package_index import PackageIndex

pi = PackageIndex()
malicious_url = "http://my-mirror.com/package.zip; touch /tmp/pwned"
pi.download(malicious_url)

When this executes, /tmp/pwned will be created on the host!

Who is Affected?

- Users of setuptools <= 69.1.1 who rely on downloading packages from URLs—especially in scenarios where end-users or automation can influence those URLs.

- CI/CD pipelines installing packages the "Python 2" way (e.g., via easy_install instead of pip).

How to Fix

- Upgrade setuptools: Version 70. completely fixes the issue by ensuring all URL handling is sanitized, and no user input is directly inserted into shell commands.
- Change your code: If you have custom scripts reusing package_index.py routines, review them for unsanitized inputs.

Upgrade Now

python -m pip install --upgrade 'setuptools>=70.'

References

- GitHub Advisory for CVE-2024-6345 (PyPA/setuptools)
- Setuptools Release Notes
- PyPA GitHub: Issue discussion
- NVD Entry for CVE-2024-6345 *(should be live soon)*

Final Recommendations

- Audit your automation: If you pass URLs into any kind of Python package installer, especially with old code or custom integrations, check for this bug.

Force minimum versions: Use dependency management to require setuptools>=70..

- Pipeline safety: If your pip, build, or install processes run as root or powerful users, lock them down.

Timeline

Published on: 07/15/2024 01:15:01 UTC
Last modified on: 07/15/2024 13:00:34 UTC