PyPI is the leading Python repository, the most commonly in use by Python users. Every python developer is familiar with the ‘pip install’ daily routine to bring the Python software they need.
Pypi helps developers find and install software developed and shared by other developers of this community. The platform and its use is currently free and developers use the repository daily. According to their own website, Pypi has over 612,240 active users, working on 391,325 projects, with 3,664,724 releases.
What many users are not aware is the fact that this one liner simple command can put them at an elevated risk. The pip install command triggers a package installation which can include a setup.py script. This script can include Python snippets to make the required installation process at the target installer machine. Hackers leverage that feature to place malicious code as part of the installation script, code which seamlessly runs on the user’s machine without being noticed. Ignorance is not a bliss in this case, as such attacks commonly harvest very critical data points such as passwords and Api tokens. Moreover, such attacks are on the rise. A relevant example would be the recent pygrata attack where malicious packages were in use to steal AWS (Amazon Web Services) keys and environment variables as part of a supply chain attack. It is important to note that the malicious actors are not waiting, and as you will see, the same attackers seem to have already generated a new campaign against PyPI users. Details of the packages we detected are described and detailed in this blog.
Ascii2text is a malicious package, simply mimicking the popular art package by name and description. Interestingly, they were smart enough to copy the entire project description without the release part, preventing users from realizing this is a fake package.
The fake ascii2text description VS the origin art package description
The package malicious part was in the package __init__.py file, imported by the setup.py installation script. The code on the __init__.py file was responsible for downloading and executing a malicious script which searches for local passwords and uploads them using a discord web hook.
The malicious snippet inside the __init__.py
The malicious script it downloads
Pyg-utils seems like a leftover of the recent Pygrata campaign whose aim was to harvest users’ AWS credentials. As part of its setup.py installation, Pyg-utils connects to the same malicious domain (pygrata.com) which could be an infrastructure for a phishing attack. Pymocks and PyProto2 interestingly have almost identical code which targets a different domain – pymocks.com. While Pyg-utils was released on 15/6, Pymocks and PyProto were released more recently (24/6 and 4/7 correspondingly). The Pymocks.com domain was also created on the very same day (24/6). Therefore, it makes sense to assume all these packages were made by the very same malicious actor, probably motivated by the fact Pyg-utils went under the hood and decided to copy and retrigger their malicious campaigns.
The Pyg-utils malicious setup.py file next to the almost identical Pymocks and PyProto2 ones
Test-async is described in its description as a ‘very cool test package that is extremely usefull and that everyone needs 100%’. In its setup.py installation script it downloads and executes, probably malicious, code from the web. Interestingly, prior to downloading that snippet, it notifies a Discord channel that a ‘new run’ was started.
Test-async setup.py installation script
Free-net-vpn and Free-net-vpn2 are malicious packages which targets environment variables. Having on its setup.py installation script a clean and documented code to harvest the user’s credentials (nice to see that even hackers are paying attention to code standards). These secrets are then published to a site mapped by a dynamic DNS mapping service.
Free-net-vpn setup.py installation script
The zlibsrc package probably tried to confuse legit users with the popular Python built-in zlib package. On its setup.py script it downloads and runs a malicious file as part of it’s the installation.
Zlibsrc __init__.py script
Browserdiv is a malicious package which aim was to steal the installers credentials by collecting and sending them to a predefined discord webhook. Interestingly while according to its naming it seems to target web design related programing (bowser, div), according to its description the package motivation is to enable the use of selfbots inside discord.
Browserdiv setup.py installation script
A malicious package which steals users’ credentials as part of its setup.py installation script (interestingly while based on its description it’s a ‘package to exploit windows RPC Vulnerability’, the reality is it just steals the installer credentials).
WINRPCexploit setup.py installation script
Supply chain attacks are designed to exploit trust relationships between an organization and external parties. These relationships could include partnerships, vendor relationships, or the use of third-party software. Cyber threat actors will compromise one organization and then move up the supply chain, taking advantage of these trusted relationships to gain access to other organizations’ environments. Such attacks became more frequent and grew in impact in recent years, therefore it is essential developers make sure are keeping their actions safe, double checking every software ingredient in use and especially such that are being downloaded from different repositories, especially ones which were not self-created.
At Spectralops.io, Now A Check Point company, our mission is to generate a secure development process, to make sure developers are doing the right things (security wise). As part of this effort, we are constantly scanning PyPI after malicious packages to prevent such supply chain attack risks.
Once we identified these malicious users and packages, our researchers have alerted PyPI, via the designated email noted on the PyPi official website, inviting users to alert on security matters, asking them to be removed. Following our disclosure PyPI removed these packages.