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 typosquatting 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
name-package~=1.1.0from name_package import mySubModuleSelection 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:
During Installation
If we place yhe payload in setup.py, we can achieve command execution during the installation of the package.
During Runtime
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