Dependency Chain Attack

If an application requires a specific package from a custom internal repository, an attacker could upload a malicious package to a public repository with a newer version number. The package manager might then prioritize the malicious package over the official internal one leading to the execution of arbitrary code. So, check if there is a public resource with that repository name, and if not, let's create it. We can also exploit typosquattingarrow-up-right an organization's name or a common misspelling.

The main package managers are:

  • Python Package Index (PyPI) for Python

  • Node Package Manager (NPM) for JavaScript

requirements.txt
name-package~=1.1.0
from name_package import mySubModule

Selection Prioritization

Package manager checks multiple repositories:

  • Public repository does not find a package -> download the package found in the private repository

  • Public repository does contain the package -> will still check both repositories, but will use the one with the newest version, based on the following versioning rule:

    • ~=: Compatible release clause, which will download any version that should be compatible with the requested version. (This assumes that the developer versions the package according to the specification. For example, if some-package~=1.0.0 is requested, 1.0.1, 1.0.5, and 1.0.9 would all match, but 1.2.0 and 2.0.0 would not)

    • ==: Matching clause (wildcards can be used, some-package==1.0.* match 1.0.0 and 1.0.1)

    • <=: Equal or less.

    • >=: Equal or greater

Pip Configuration

For Consumption (PULL)

For Publishing (PUSH)

We can check uploaded packages

For Remove

Package Configuration

Note: dashes cause issues in Python syntax

Instead of setup.py, we can also use pyproject.toml or setup.cfg.

Command Execution

We now have two locations where we can place a payload:

chevron-rightDuring Installationhashtag

If we place yhe payload in setup.py, we can achieve command execution during the installation of the package.

chevron-rightDuring Runtimehashtag

We need to know how the developers use the package. Specifically, which submodule they import from the package.

Create a submodule mySubModule.py with a wildcard function inside that will be executed regardless of the name of the function actually called to avoid generating errors. Then we add the payload at the end so that the code is executed when the app imports the package.

Last updated