After a recent discovery of malicious PyPI packages, questions remain about the security community’s ability to mitigate threats posed to open source repositories.
The threat of software supply chain attacks has taken center stage in the year 2022, and a robust track record of these attacks demonstrates that there is an evergreen threat to software at large. What put software supply chain attacks on the map was SolarWinds. But more recently, the dangers associated with the use of open source repositories specifically has made itself more clear in the newer software supply chain attacks that are unfolding.
The recent IconBurst software supply chain attack, discovered by ReversingLabs, is a perfect example of how open source repositories can unfortunately be abused by malicious actors. What we found was a widespread campaign to install malicious NPM modules capable of harvesting sensitive data from forms embedded in mobile applications and websites. Unfortunately, IconBurst is just one example of public repositories being the attack vector for threat actors.
This week, a new attack on open source unfolded. ReversingLabs’ Robert Perica and I detected several new malicious packages in the PyPI public repository, uploaded by a separate author. Perica believes that the packages found are almost identical, differing mainly by their names. The basic functionality of these packages is also identical, in that they beacon back successful installation to the C2 server and download a stage 2 payload from the remote server. This payload can be detected by using the open source YARA rule for Parallax RAT.
The following code snippet is of the first malware stage, within the published PyPi package, that downloads the Parallax RAT executable with the file extension reserved for screensavers on Windows.
Figure 1: Python code responsible for communication with C2 server
Figure 2: One of two user accounts used for publishing of malicious packages
ReversingLabs reached out to PyPI’s security team about these malicious packages, and they responded soon after saying that they had removed all of the packages as of August 23rd, 2022.
Malicious packages found on public repositories like PyPI are not a new threat, being similar to IconBurst and other supply chain attacks abusing open source software. However, what is truly alarming for the security community are the recent attacks that have been performed by automatic submission of a large number of malicious packages to open source repositories. For example, on August 19th 2022, more than 900 malicious NPM packages were submitted by a single user, demonstrating that the mass volume of these malicious packages and the abilities of threat actors to easily dump them in public repositories is a current reality.
Figure 3: User account used for publishing of malicious npm packages
With the increasing amount of malicious packages popping up in open source repositories, the bandwidth of the security community may not be prepared to prevent open source-based software supply chain attacks from occurring. Currently, open source software libraries and components form the foundation of, by some estimates, 75% of applications. With an increasing reliance on open source packages, the attacks on these repositories has increased as well: attacks on npm and PyPI combined have surged 289% since 2018.
The spreading of malicious packages is now not the only threat to public repositories. Today, PyPI shared on Twitter (see below) that they have received reports of a phishing campaign targeting PyPI users. They stated that this is the first known phishing campaign against PyPI, creating another realistic threat impacting open source repositories.
Today we received reports of a phishing campaign targeting PyPI users. This is the first known phishing attack against PyPI.
— Python Package Index (@pypi) August 24, 2022
We're publishing the details here to raise awareness of what is likely an ongoing threat.
While it’s clear that open source repositories enable thriving developer communities, security researchers still stand alone in detecting and mitigating these kinds of threats, since public source repositories like PyPI and npm struggle to prevent them, while at the same time never-before-seen threats are emerging.
To learn more about the technical details of this new attack, its indicators of compromise (IoCs), and best practices for avoiding and mitigating these kinds of attacks, continue reading.
Anatomy of the attack
As a part of this malicious campaign almost 40 PyPI packages were published to the PyPI repository from two different accounts — pypzz and pypiappz. Since all of the packages contain almost identical code shown in Figure 1, it can safely be concluded that the same actor is managing both of them. All of the packages from the same author were published in a very short period of time leading to a conclusion that some kind of automated publishing process was utilized.
As described earlier, the functionality of these python packages is quite simple. First they beacon back to the C2 server notifying it about successful installation. After that stage2 payload is downloaded and executed on the infected machine. Download link for the stage 2 payload is hxxps://python-release.com/python-install.scr. The domain as well as package names lead to the conclusion that the malicious actor is trying to impersonate the legitimate python download website.
Figure 4: Impersonation attempt of the legitimate python download webpage
Looking at the content of the webpage hosted on this impersonation domain shows a slightly corrupt web layout. What stands out is a notice at the top of the page trying to convince the visitor into enabling javascript execution on this webpage. HTML source code of the page references a suspicious script.
Figure 5: Reference to a suspicious jquery script
The name tries to mimic a jquery javascript file, but the content of the script is obfuscated with Javascript obfuscator (mentioned in a few of our previous blog posts). The contents of this script uncover another file hosted on this weblocation which can also be downloaded under the name python-setup.zip.
Figure 6: Artifacts revealing usage of Javascript obfuscator
So to quickly summarize, the python-release.com domain hosts two downloadable files python-install.scr and python-setup.zip. The first one, referenced directly from PyPI packages, contains packed Parallax RAT malware. The second one is a zip archive containing several legitimate executables signed by Python Software Foundation. But it also contains an executable named python-install.scr (the same name as the one referenced from the PyPI packages) signed with a certificate issued to M-Trans Maciej Caban organization.
Figure 7: Valid signature of the malicious executable
The signature is valid but the file contains malicious .NET executable in the file overlay. Behavior indicators extracted from this .NET executable reveal that it performs credential stealing from Microsoft Edge and Google Chrome local databases and exfiltrates that data to python-release.com C2 domain.
Figure 8: Behavior indicators extracted from python-install.scr payload
One of the powerful features ReversingLabs a1000 platform provides is URL analysis. It provides a way to see a history of analysis performed for some domain and to see how many different files were downloaded from that domain. In this case 4 different files were downloaded from this domain and so far, only two were covered with the current research. So it is possible that earlier in time, different files were served when the same URL was visited.
Figure 9: Behavior indicators extracted from python-install.scr payload
ReversingLabs file similarity algorithms confirm this information and enable pivoting from the original two samples to the other ones previously hosted on the same domain. One of the files discovered in this way exfiltrates data to linkedopports.com domain, which is also seen in the PyPI packages as the domain to which beaconing about successful malware installation is reported. Both of the domains have alexander surovcev under their Registrant Organization entry in their public domain record. The total list of malicious files discovered during this investigation can be found in the IoC section at the end of this blog post.
Indicators of Compromise (IoC)
C2 domains extracted from the analyzed PyPI packages:
linkedopports.com
python-release.com
Stage 2 payloads:
b33824cafd32e7fb1a7bf01865ddac69f1ffd038
68d32e3b84c0596805f438fb1cfc1b3befba821f
1e697bc7d6a9762bfec958ee278510583039579c
567e1d5aa3a409a910631e109263d718ebd60506
0a6731eba992c490d85d7a464fded2379996d77c
d3ed1c7c0496311bb7d1695331dc8d3934fbc8ec
a30df748d43fbb0b656b6898dd6957c686e50a66
Package versions:
statmodel |
4.5.2 |
204914fd686aeea8dfe6b2cdb740b394e94488e3 |
etuptool |
4.4.9 |
3aa184781b0a047b6a9a68cdd6a6b09de16b4f3f |
yinance |
4.5.2 |
2aaa80ce453a35728241193feae0dee707ae366f |
yaudio |
4.5.2 |
98629ee071cced65aef699ace70a2aef2a84d444 |
proxycrape |
4.5.2 |
e2386d874347cf15771b9aa42ae97b7e27b44434 |
etuptool |
4.5.2 |
e66e558d8d6187c9fd12e585ee73ff22e3f9d80f |
etuptool |
4.4.8 |
ac152bffd1f6c35467c3aef0b00ef4c4ba1a9978 |
deeepl |
4.5.2 |
ca39a7a5ceee86a1ce1fd13463138385d8364c82 |
statsmodel |
4.5.2 |
2b29eeb77e5a0fdc78cf5a50365824d435121b6d |
proxyrape |
4.5.2 |
700e8b533406bbe2a4934c4a5ba1f312b4be8fac |
yinstaller |
4.5.2 |
1a9f683a47d242c2aba4a4c811ab0ffc9a062e34 |
etuptool |
4.4.7 |
cc1bcf24e17957dfa533aaa951d823370adf0cf3 |
etuptool |
4.5.1 |
1f7549003aa8cd96682962effcad48005ff31366 |
eepl |
4.5.2 |
f51fb81df3dc990b91c11afe59117487d1847056 |
ywin32 |
4.5.2 |
4b768ac033b2bc673038f10ed7106a9ede01447d |
statmodels |
4.5.2 |
b2467b8689232ca2e3d14f078c1b242f2c389435 |
discordhook |
4.5.2 |
1e44d0184dc43714cf78394a33ba121717c3e5dc |
igtoolz |
4.5.2 |
86a50659bbde4310afef05b94a8e8db14e06f8e5 |
elenium |
4.5.2 |
3f336b5768b015c4dd7d2ad10c4a132187b6f812 |
asn2crypto |
4.5.2 |
801fbbacf11f0ba4f36964408d37bbaa6d86616e |
bitcoinliv |
4.5.2 |
5f2821f973045bde351254bb5b3612428e90767e |
crypto-data-fetch |
4.5.2 |
0abc9b6b0bec33be282f3abd93be79a339ea333e |
crypto-get-price |
4.5.2 |
0ae235914da06b39dc6fa8e6d9a97eae92d679f1 |
crypto-open |
4.5.2 |
024dfa015eca044014800c4fa95fae549f5bdf14 |
crypto-os |
4.5.2 |
ec1da8be4029d12688e934b8a901867cff0f3395 |
cryptobalance |
4.5.2 |
5bce39d594b360a044586f7b271000788c1ec6c8 |
django-metamaks-auth |
4.5.2 |
20379bac52e98d84dca01e29e407013dd25af038 |
django-metamask-aut |
4.5.2 |
e064a11c1890f7c059e98411b854236d1869b99f |
django-web2-auth |
4.5.2 |
c1424d23a3b60b80103a87dea831641c861b59b3 |
django-web3-aut |
4.5.2 |
d2b8a49e615597e4b0eaf0a833371d881803464c |
django-web4-auth |
4.5.2 |
cd52dc473a8207546bae0d76c93c7def3cc2e775 |
hameni |
4.5.2 |
27473d1193e4ab1bded44119b0f7ed95fb81b062 |
historic-crypt |
4.5.2 |
c7ad5141df48d63f7264388176bce1fd6f828984 |
jango-metamask-auth |
4.5.2 |
c7a103b612ed783fd5bbc252681130d711cb5189 |
jango-web3-auth |
4.5.2 |
5130d078b886488f252399121cfeb6f442582fed |
pyvrypto |
4.5.2 |
29b6a61addbc465c0f3ae9a1dc32654a9adcced7 |
pyxrypto |
4.5.2 |
16719ab5dbf1d4ca7661f3518257cd1019de540e |
ycrypto |
4.5.2 |
0de72b64d5da5b93c9b45b89d98fd4d9cd8d19f0 |
ycryptodome |
4.5.2 |
e467fa8c098cc4c360571b1532e2da21e8b1702d |