While regularly combing through packages available on public repositories such as npm and PyPI, ReversingLabs researchers encounter packages with different combinations of behaviors and characteristics. These behaviors and characteristics might not be easily discernible simply by observing the package’s contents. However, they can be observed once the package is analyzed with the ReversingLabs Software Supply Chain Security platform.
In the course of analyzing millions of suspicious packages, the ReversingLabs team has identified a number of combinations of behaviors that, when seen together, are highly indicative of malicious activity. For example, open source packages that contain hard coded IP addresses in their code, while also executing commands and writing data to files, in our experience, usually turn out to be malicious. It is true: None of those capabilities, individually, are malicious. When seen in combination, however, they’re usually supporting malicious functionality.
The presence of such suspicious characteristics and behaviors that first caused the npm package nodejs-encrypt-agent to come to our attention. First published more than two months ago, nodejs-encrypt-agent appears at first glance to be a legitimate package. However, discrepancies raised red flags with our researchers. Despite that, our first thought was still that this package couldn’t be malicious. If it were, it would surely have been noticed and removed by npm administrators.
In the end, we went with our gut: The package was analyzed in depth using ReversingLabs Software Supply Chain Security. What follows is our threat research team’s findings.
Funky packaging: Name and version discrepancies
Even before we analyzed the nodejs-encrypt-agent, there were a number of signs that the package was fishy that jumped off the screen. Take the package name. While the name on the npm page looked normal, it differed from the name listed in the readme.md file (agent-base). That’s not unheard of, but previous investigations we have conducted have proven that it is a red flag.
As is often the case, the name in the readme.md was not accidental. A quick search revealed that agent-base is the name of a legitimate npm package. In fact, alink to the GitHub page of agent-base was added so the malicious package could look more authentic.
Irregularities in the package version numbers also jumped out at us. The oldest version of the package listed on the nodejs-encrypt-agent npm project page was published two months prior to our discovery of the package, but had a strangely high version number (6.0.2) for what amounted to a version 1.0. As we’ve noted, high version numbers are popular among malware authors hoping to infiltrate open source repositories via typosquatting and other supply chain attacks, where hurried developers are often quick to grab the latest edition of a package, as designated by the version number.
Upon further investigation, the choice of that high version number was intentional, also. Version 6.0.2 of the agent-base model that the malicious actors were mimicking had been downloaded over 20 million times. The malicious actors were clearly hoping one of those millions of developers would be fooled into downloading the malicious package instead of the benign one.
Figure 1: Versions of nodejs-encrypt-agent
Under the hood: Mind the PE
When we looked inside the nodejs-encrypt-agent, we found that the code and functionality mirrored the agent-base package it was squatting on. That is to be expected. There was, however, a small, but very significant difference: the nodejs-encrypt-agent package contained a portable executable (PE) file that, when analyzed by ReversingLabs was found to be malicious (Figure 2).
This was no false positive, but rather a malicious file doing malicious things.
The PE file was executed almost immediately after the package is run, leveraging malicious commands hidden in the first few lines of the index.js file. Among the malicious behaviors identified in the PE component (Figure 3), the ReversingLabs Software Supply Chain Security platform identified the ability to write to and delete from Windows system directories; the ability to execute commands; and ability to tamper with DNS (domain name system) settings, among others. In summary: This was no false positive, but rather a malicious file doing malicious things.
Figure 2: An SDLC report on the PE file found within nodejs-encrypt-agent
Figure 3: Behavior policies in ReversingLabs Software Supply Chain Security
To better understand how the PE functions as well as its provenance, it was analyzed in detail, with the help of another ReversingLabs researcher, Igor Kramarić. The following section details our findings:
Figure 4: index.js, where malicious PE file is executed
Malicious file analysis: Call me TurkoRat!
As we observed above: there was little question that the PE discovered within the npm package was malicious. The list of malicious or suspicious behaviors observed was long, with features designed to steal sensitive information from infected systems including user login credentials and crypto wallets as well as fool or defeat sandbox environments and debuggers that are used to analyze malicious files.
Figure 5: Stealing user’s information
These features made analyzing the PE a challenge. However, having extracted all javascript files that were being run and looking at previous versions of the nodejs-encrypt-agent package, ReversingLabs was able to identify the PE as a malicious executable known as TurkoRat, an open-source family of malware dubbed a “stealer,” and used to lift everything from Website cookies to crypto wallets. Our identification was confirmed by correlating the javascript files we extracted from the PE to the files found in the TurkoRat GitHub repository. The files matched almost perfectly, with minor variations such as a customizable Webhook.
TurkoRat is just one of many open source malware families that are offered for “testing” purposes, but can readily be downloaded and modified for malicious use, as well. TurkoRat’s author clearly anticipates this, as he provides instructions on how to use malicious code, while stating that he is “not responsible for any damages this software may cause and that it was only made for personal education.”
As it turns out, this particular version of the TurkoRat malware uses the npm package pkg to bundle all the necessary files into a single package executable. All the files reside inside a virtual file system, or snapshot, to which the packaged application has access during runtime.
A list of all the files embedded in this particular PE file is found at the end of the file that pkg creates during the packaging process. Some of the files belong to dependencies, which can be easily deduced from prefix node_modules in their paths. From a cyber forensic standpoint, those of the most interest can be observed in Figure 6 and are found inside a folder named “new virus do gusta” (if you still had doubts about malicious intent).
Figure 6: List of files used in PE file
TurkoRat: Customizable code
TurkoRat is notable for having many customizable parts. Those include the aforementioned webhook component, which is found in config.js. A malicious actor using TurkoRat can modify a few settings in the build to alter the configuration and capabilities of the finished PE. They would then need to use build.bat to rebuild it and package it into a malicious executable. Afterwards, there are various ways that a malicious actor could distribute the malware. Those include hiding it in a legitimate software package, as it was hidden inside the nodejs-encrypt-agent.
Figure 7: Customizable config.js
TurkoRat: Sniffing around other packages
In fact, nodejs-encrypt-agent wasn’t the only package we found with TurkoRat hiding inside. It was also discovered lurking in the first few versions of the npm package nodejs-cookie-proxy-agent. This time, attackers disguised it as a dependency, axios-proxy, that was imported into every file found inside nodejs-cookie-proxy-agent versions 1.1.0, 1.2.0, 1.2.1 and 1.2.2. (axios-proxy had been previously found and marked as malicious by ReversingLabs researchers.) As we saw with the nodejs-encrypt-agent, nodejs-cookie-proxy-agent had a few versions available on npm, and was first published to npm two months ago. Our analysis show that the malicious package was removed from npm soon after it was discovered by ReversingLabs researchers and marked as malicious, which may explain why the last two versions of nodejs-cookie-proxy-agent (1.2.3 and 1.2.4) switched to embedding the nodejs-encrypt-agent, instead.
As with the nodejs-encrypt-agent, the code found in nodejs-cookie-proxy-agent also mirrors a commonly used, legitimate package, node-cookie-proxy-agent. This package is not as popular as agent-base, but it was continuously downloaded throughout last year. As with the nodejs-encrypt-agent, the GitHub page of the actual package was also linked to the legitimate package it was squatting on. With the legitimate and malign packages only differing by two letters, this is a clear example of typosquatting, making it very possible that a developer would mistakenly download and use the malicious nodejs-cookie-proxy-agent in place of the legitimate node-cookie-proxy-agent.
Figure 8: Versions of nodejs-cookie-proxy-agent
Malicious file hashes
Below are hashes of the malicious packages detected on npm, as well as the malicious portable executable (PE) containing the TurkoRAT malware.
Malicious PE file found in nodejs-encrypt-agent: ef3ea4dc2d3ba466e40b8cc5e2b20cb026cf7936
package_name |
version |
SHA1 |
nodejs-encrypt-agent |
6.0.2 |
1a8a8fa87aff26fc2b269846f0f0d5be588bc6ee |
nodejs-encrypt-agent |
6.0.3 |
99537ef2edffcebe6ebe88cc5d3d9420d397e89c |
nodejs-encrypt-agent |
6.0.4 |
8093060aa8cea40a790ea0538c14bb11f3a02cd0 |
nodejs-encrypt-agent |
6.0.5 |
395d592b52c2947dd6bff455725a3c4204f41bb4 |
nodejs-cookie-proxy-agent |
1.1.0 |
d6e03a4023a3759cd28eb85c909bc17af4b78b7e |
nodejs-cookie-proxy-agent |
1.2.0 |
a324176ef05a03a244220072f9f1eb168e4ffa89 |
nodejs-cookie-proxy-agent |
1.2.1 |
97d9fff201c71ef13bb1b2a7dcd442c59a94e5e0 |
nodejs-cookie-proxy-agent |
1.2.2 |
a4ac448a83865bbe7f62f5dad56143f1d5d0b526 |
nodejs-cookie-proxy-agent |
1.2.3 |
3576ccdd8fdde01a6d55c62f45aa8960a479ebee |
nodejs-cookie-proxy-agent |
1.2.4 |
301088fc087f4ae61427a4515b3b822372a9d50f |
axios-proxy |
1.7.3 |
aa02262de80a31b50efdf0a84c9915ca43696389 |
axios-proxy |
1.7.4 |
82ce0491e2415fa8ab8d75faa26adc2278855507 |
axios-proxy |
1.7.7 |
36f4b2e3d1f0e0e791e44178b41c9e53eb1898b5 |
axios-proxy |
1.7.9 |
61122f4857ae5c358cee5a79232b6f1b6213025a |
axios-proxy |
1.8.9 |
c29938c79fd7fb0dcd3b646df136333e0ae62fda |
axios-proxy |
1.9.9 |
ebb5b9d0d5416c5eaa0a3b00e9115ac7ed5839d6 |
Conclusion
Following the ReversingLabs research team’s detection of the malicious npm packages, the affected packages were removed from npm and are no longer available for download. However, these latest discoveries, which lurked on the popular npm platform for two months, underscore the ongoing risk of supply chain attacks via open source packages.
In the case of the two packages discovered and analyzed by ReversingLabs researchers, nodejs-encrypt-agent and nodejs-cookie-proxy-agent, the fallout from these attacks was limited. The nodejs-encrypt-agent was downloaded about 500 times during its two months of availability. The nodejs-cookie-proxy-agent was downloaded fewer than 700 times. Still, the malicious packages were almost certainly responsible for the malicious TurkoRat being run on an unknown number of developer machines. The longer term impact of that compromise is difficult to measure.
From the perspective of threat detection and supply chain security, organizations should pay attention to the wide assortment of “tells” that these packages exhibited and that were clear signs that they could be malicious. Typosquatting attacks hinge on developer inattention to small details in naming (“node” versus “nodejs” in one instance). However, other details are easier to spot even for harried developers, including suspicious versioning, discrepancies in naming, smaller than expected downloads and dependencies and more.
When using packages from public repositories in their projects, developers should keep an eye peeled for these small, but telling details to avoid a malicious package being introduced as a dependency in some larger project.
Development organizations need to scrutinize the features and behaviors of the open source, third-party and commercial code they are relying on in order to track dependencies and detect potential malicious payloads in them. ReversingLabs technology, including our A1000 and Software Supply Chain Security platforms, deliver the visibility teams need to discover malware.
Source: https://www.reversinglabs.com/blog/rats-found-hiding-in-the-npm-attic