A malicious Python file found on the PyPI repository adds backdoor and data exfiltration features to what appears to be a legitimate SDK client from SentinelOne.
A malicious Python package is posing as a software development kit (SDK) for the security firm SentinelOne, researchers at ReversingLabs discovered. The package, SentinelOne has no connection to the noted threat detection firm of the same name and was first uploaded to PyPI, the Python Package Index, on Dec 11, 2022. It has been updated 20 times since, with the most recent version, 1.2.1, uploaded on Dec 13, 2022.
The package appears to be a fully functional SentinelOne client, but contains a malicious backdoor, according to ReversingLabs threat researcher Karlo Zanki. The malicious functionality in the library does not execute upon installation, but waits to be called on programmatically before activating - a possible effort to avoid detection. We are calling this campaign "SentinelSneak."
The SentinelOne imposter package is just the latest threat to leverage the PyPI repository and underscores the growing threat to software supply chains, as malicious actors use strategies like “typosquatting” to exploit developer confusion and push malicious code into development pipelines and legitimate applications.
Background
The ReversingLabs research team is continuously monitoring open-source package repositories for instances of malicious code and software supply chain attacks. This work involves both automated and human-led scanning and analysis of packages published in the most popular public package repositories like NPM, PyPI, Ruby and NuGet.
During these scans, we leverage our proprietary Titanium platform, and our deep file repository of goodware and badware to spot malicious and even suspicious elements hiding in plain view. Our ReversingLabs secure.software solution builds upon that past work. The platform provides a way for dev and SOC teams to deeply examine their CI/CD workflows, containers and release packages to spot nascent or active software supply chain compromises.
Frequently, our work turns up evidence of active software supply chain attacks. In April, for example, we came across NPM packages that used a javascript obfuscator to hide their functionality. Our analysis of those packages produced proof of simulated “dependency confusion” attacks on the software supply chain of leading German companies across a number of industries. (That campaign turned out to be the product of an authorized “red team” exercise conducted by a security firm on behalf of its customers.)
In July, a similar inquiry uncovered a wide ranging campaign on the npm platform we dubbed “IconBurst.” That campaign employed a technique known as “typosquatting,” with many of the malicious packages using naming that was similar to popular npm packages offering icons for use in graphical interfaces. We wrote about another typosquatting campaign dubbed “Material Tailwind” in September, also on the npm platform. That included a malicious npm package masquerading as a development tool for Tailwind CSS and Material Design, two popular npm packages. That malicious package included a post-install script that downloaded a malicious executable capable of running PowerShell scripts on systems that installed the Material Tailwind package.
PyPI saw less malicious activity relative to npm. In fact, our State of Software Supply Chain Security report found that, in contrast to npm, the PyPI repository saw a nearly 60% decrease in malicious package uploads this year, going from 3,685 in 2021 to 1,493 packages through the first 10 months of 2022. But malicious PyPI activity since 2020 is still way up (there were just eight malicious packages detected in 2020). And recent weeks have seen a number of malicious campaigns on PyPI, including a campaign of malicious packages distributing the W4SP stealer malware.
We are continually tracking PyPI repositories for suspicious behaviors. And those efforts led to the discovery of our most recent malicious package, which attempts to hijack the name of a respected cybersecurity firm, SentinelOne.
Discussion
The core capability of ReversingLabs’ secure.software solution is analyzing code intent while highlighting malicious behaviors. These indicators cover all kinds of software behavior, from network and file system activities to use of packers associated with malicious campaigns, and the use of evasion techniques.
Red flags in allegedly ‘commercial’ module
In the case of the SentinelOne PyPI package, our researchers were tipped off by telltale suspicious behavior including the execution of a file, the spawning of new processes and the presence of URLs that reference a host by IP address.
Figure 1: PyPI package without description is always suspicious
Even a cursory glance at the SentinelOne PyPI package raises red flags. The project page has a very rudimentary look with no description of the SentinelOne package and a maintainer account that was created only days before the initial package was uploaded. While such behaviors are sometimes observed in legitimate modules, this is not behavior that would be expected from a commercial software vendor of SentinelOne’s stature.
Taking a look at the SDLC (software development lifecycle) report generated with ReversingLabs secure.software platform provides clues that helped to quickly pinpoint the location of the malicious content in the counterfeit SentinelOne package. In the following sections, we'll discuss that in more detail.
Why SentinelOne?
The most obvious point is that the SentinelOne PyPI package we discovered has no connection to SentinelOne, the respected cybersecurity firm that offers threat detection and response capabilities. It appears that the malicious actor(s) behind the SentinelOne PyPi package are attempting to draft on SentinelOne’s strong brand recognition and reputation. The malicious PyPI package poses as an SDK that will abstract access to SentinelOne’s APIs and make programmatic consumption of the APIs more simple.
Funky functionality
The first clue that something was amiss with the SentinelOne PyPI package was that most of the “interesting” behaviors detected by TitaniumPlatform were concentrated in just two api.py files, out of more than 100 code files in the project. Especially interesting was the combination of the detected behaviors which includes enumeration of files in a given directory, deleting of a file/directory and creation of a new process. When such behaviors are combined with the presence of a URL which references the host by IP address, you can mark that module as suspicious. Referencing the host by an official domain would be expected from a commercial product.
Figure 2: Interesting behavior indicators triggered on api.py files
That sense was confirmed when we compared the differences between roughly 20 versions of the SentinelOne PyPI package uploaded over the course of two days. Only one python source code file changed between the versions out of the scores of files that make up the package. Which package? You guessed it: api.py.
Figure 3: Data exfiltration URL from api.py files
The second “red flag” was the discovery of networking strings in the code of the two api.py files. As mentioned earlier, one of the things that triggered our threat detection heuristics was the presence of URLs that reference the host by an IP address that was not affiliated with the company SentinelOne.
Figure 4: Behavior differences between two of the package versions
The api.py files were also where we located the malicious code. A detailed analysis of that code revealed capabilities that are focused on exfiltration of data that is characteristic for development environments.
Figure 5: Data exfiltration
In the above screen grab, for example, we see the malicious code for collecting information about shell command execution history as well as the contents of the .ssh folder containing ssh keys and configuration information, including access credentials and secrets, related to git, kubernetes and AWS services.
The code likewise performs a directory listing of the root directory. The collected data is then exfiltrated to the command and control (C2) server. Though clearly malicious, the counterfeit SentinelOne package is selective: taking only what is needed, and focusing on the subset of services that are found on machines used for software development.
Figure 6: Anomalies in module naming
Further analysis of the changes between the versions of the counterfeit SentinelOne module shows that the attacker modified its functionality to adapt to targets. For example, initial versions of the module didn’t make any distinction based on the operating system in which they were executed. But it seems that version of the data collection algorithm didn't work correctly if it was executed in the Linux environment, based on hardcoded paths to targeted directories. Those issues were fixed in later versions and the malware’s data stealing capabilities were expanded with subsequent releases.
Figure 7: Adapting malicious code based on host environment
During development, the malicious actor published five additional packages with similar naming variations, which were used for testing purposes and did not contain api.py files with malicious functionality. These packages were published between December 8th and 11th, 2022. ReversingLabs reported the incident to the PyPI security team on December 15th, 2022, and SentinelOne was notified on December 16th, 2022.
IOCs
Data exfiltration IP address:
54.254.189.27
PyPI packages:
package_name |
version |
SHA1 |
SentinelOne |
1.0.0 |
68b09896b65db21d2c6cd2923d2486a2f69f73ef |
SentinelOne |
1.0.0 |
557af28f0a42d4fb7466376ce422bcb518e7ccc0 |
SentinelOne |
1.0.1 |
1378d35524804d2f0e42fc1e8e6365211713731f |
SentinelOne |
1.0.1 |
3859aa3ddc941be0d8459b90244f7cb0f48da1be |
SentinelOne |
1.0.2 |
268546ab1aedee336151933159f056c45844ef4c |
SentinelOne |
1.0.2 |
3eaa0ced4d19742c35bc3d9a99636e5333ceb573 |
SentinelOne |
1.0.3 |
94f6ba66169f54975771d6201bd8a40a65ffee16 |
SentinelOne |
1.0.3 |
9e0373a8e50a1a87a552cd25cfdad51322b00719 |
SentinelOne |
1.0.4 |
3c4d2e0f3125817c10ae4aa4a29a8ddcedbe3065 |
SentinelOne |
1.0.4 |
f8438699804645ebc7cc573cc1326050814b02e4 |
SentinelOne |
1.0.5 |
661450bd7934ae7a138a040d9d27b086414237d3 |
SentinelOne |
1.0.5 |
de2a6dfbed323e0109ce02737df1d9ce5de38561 |
SentinelOne |
1.0.6 |
1a891771806974ec18111a6c69b6d5bb92d6298d |
SentinelOne |
1.0.6 |
a219cec2f4a3ea2c2a707925473ebe68b620e75c |
SentinelOne |
1.0.7 |
596659f434ef78a4f7433c59d3efa79d50fa3de2 |
SentinelOne |
1.0.7 |
d932be913409595ecc1d94e644c5050f5d5ce5a3 |
SentinelOne |
1.0.8 |
8d02c52b03b034774bfb6767d53569035aa6398b |
SentinelOne |
1.0.8 |
52bf75dc7db3db210eea58bcea31d6cf7964a5d1 |
SentinelOne |
1.0.9 |
1ee6eace8ccf865fc4ddb67d895833ad664f7a5b |
SentinelOne |
1.0.9 |
d394756d77d2cd85fce527c3cd3c1e4c7ebdd1fb |
SentinelOne |
1.1.0 |
b4a490e54f9ed0f584de48dad80cc35217fa528d |
SentinelOne |
1.1.0 |
0b25161aa8a4e0ea3be8ad8870409e4c93941086 |
SentinelOne |
1.1.2 |
19a6b849d6bcb7a8dbbbde2158923135c0ee647c |
SentinelOne |
1.1.2 |
508a81ffe18fd608fddcb73ea2aba4a83c1a8fc3 |
SentinelOne |
1.1.3 |
12ea7268665ea0e2688a47278c6b24ea6f907535 |
SentinelOne |
1.1.3 |
ed5433e5c3b836ee9a4f9f3dde6c8b4e703eca0e |
SentinelOne |
1.1.4 |
9673c811de0ab875b542eaabfed121100f3ffad9 |
SentinelOne |
1.1.4 |
1dca0855dd4175dadbe2f9917ad4e1ab176c8052 |
SentinelOne |
1.1.5 |
7298b2bbf8558259ed8a5f2a286e1c2607e85bd5 |
SentinelOne |
1.1.5 |
3bd886c69d380745a2db2a2da3b8d9adbff4627e |
SentinelOne |
1.1.6 |
c5af9a6308e4720a451f79124ee238ce8e021087 |
SentinelOne |
1.1.6 |
43d2dbe829300587d5672c9209c39233a0d1ff8d |
SentinelOne |
1.1.7 |
37407dbd8f41a896ce8c68bc2eb5a7041e9fe47d |
SentinelOne |
1.1.7 |
b3a35866f23496cf52b8c7ad609f64b39003a386 |
SentinelOne |
1.1.8 |
5ac10152a5db8b5f3ca827616a526314ad9b8983 |
SentinelOne |
1.1.8 |
3f62cd17186dd821495080b7fed822ad271b9a24 |
SentinelOne |
1.1.9 |
ca3aecd84b5b82ee0dac98223111bf300fec6441 |
SentinelOne |
1.1.9 |
2ee8cec7f388873ad50c6108e16225b344035e4c |
SentinelOne |
1.2.0 |
1a16d6cacd5cd19b143d88f6f93cb15b535e8f15 |
SentinelOne |
1.2.0 |
9ba06781f172dd8a0bfd333c6f18ea7b15af3d85 |
SentinelOne |
1.2.1 |
761cfd2c1c38477ff27291b841f27c345622d58f |
SentinelOne |
1.2.1 |
adc917741164cc59da629cc4fd44f9f46ec06a2d |
sentinelone-sdk |
6.2.2 |
085b0b8974a8d93998a2dafb1335306b676274eb |
SentineloneSDK |
1.0.0 |
48fda8ccdf50e7c210c3cffe1af3572b1962bd68 |
Sentinelone |
1.0.0 |
e4f6c8886de708a4c16e88e3ebf17f60adfacbad |
SentinelOneSDK |
1.0.0 |
5d843c53ef47ef89a1ab4a8d2e58bb9c2ae6bf34 |
sentinelone-sdk |
6.2.1 |
bc890c4578ba52a27902c4b6e2bfe0c18ca84a2d |
SSL certificate:
A self-signed SSL certificate was associated with the 54.254.189.27 IP address. Since the data exfiltration uses https protocol and there is a high correlation between the certificate issue and package publishing dates, it is very likely that the certificate is related to this campaign.
SHA1 |
2a12e17eff9a485f03dc707a6be76ecb23aded7e |
Serial number |
110586408742899611342786376272762984188488572179 |
Subject |
Internet Widgits Pty Ltd (default value for this field) |
Issued |
2022-12-11 |
Expires |
2023-12-11 |
Conclusion
The SentinelOne PyPI package is a malicious module that attempts to exploit the name and reputation of the cybersecurity firm SentinelOne. The module appears to have been built on top of legitimate SentinelOne SDK client code, likely obtained from the company by way of a legitimate customer account.
It contains a backdoor as well as information stealing capabilities. The malicious functionality was placed in the package through the addition of two Python modules, both api.py files. The malicious code appears designed to siphon sensitive information from development environments, according to an analysis by ReversingLabs.
Based on our analysis of the malware and the associated C2 infrastructure, it is unclear if this package was or is being used in active attacks against development environments. We found no evidence of such attacks. However, download statistics from PyPi suggest that the package was downloaded more than 1,000 times. ReversingLabs notified PyPI and SentinelOne about our discovery and the presence of this malicious package in the PyPI repository.
This latest discovery underscores the ongoing threat of malicious code lurking on open source repositories such as PyPI, npm, RubyGems, GitHub and more. As with prior malicious open source supply chain campaigns, this one attempts to exploit confusion on the part of developers to push malicious code into development pipelines. In this case, the attackers attempt to leverage the name and reputation of SentinelOne, a highly respected cybersecurity firm, to fool users into downloading a malicious payload that includes a backdoor.
Also like prior incidents, this discovery shows telltale signs of malicious activity, including the execution of a file and use of URLs in the code that reference a host by IP address, rather than a DNS host name.
Though small in scope, this campaign is a reminder to development organizations of the persistence of software supply chain threats. As with previous malicious campaigns, the "SentinelSneak" campaign plays on tried and true social engineering tactics to confuse and mislead developers into downloading a malicious module. To counter such attacks, development organizations need to invest more heavily in training and awareness campaigns that ensure developers will not fall for typosquatting and other impersonation attacks. It also highlights the need for tools and processes to ensure that any open source or proprietary code is evaluated for the presence of suspicious or malicious indicators including hidden (obfuscated) functionality, unexplained communications with third party infrastructure and more.