ReversingLabs researchers have identified a new, malicious supply chain attack affecting the npm platform. The “typosquatting” campaign first appeared in August and pushed a malicious package, node-hide-console-windows, which downloaded a Discord bot that facilitated the planting of an open source rootkit, r77.
This is the first time ReversingLabs researchers have discovered a malicious open source package delivering rootkit functionality, and suggests that open source projects may increasingly be seen as an avenue by which to distribute malware.
Typosquatting delivers open source malware
This is just the latest in a string of malicious, supply chain attacks to leverage npm. In August, for example, ReversingLabs researchers uncovered evidence of additional malicious packages connected to npm’s campaign targeting cryptocurrency providers. In July, we reported on Brainleeches, another npm-based campaign that targeted both end users and developers with malicious code designed to harvest user data with phony Microsoft.com login forms and implant credential harvesting scripts in applications that inadvertently incorporate the npm packages.
As with those previous campaigns, this latest discovery relies heavily on a technique known as typosquatting, in which cybercriminals stand up malicious packages with names that closely resemble legitimate and widely used open source modules.
In this case, the malicious package, named node-hide-console-windows, mimics the legitimate npm package node-hide-console-window, which is used to toggle an application’s console window visibility. As you can see, these two packages are nearly identical, with only the letter “s” distinguishing the malicious package from the legitimate one.
As the threat research team has seen in prior campaigns, the attackers also took other steps to make the packages indistinguishable to hurried developers looking to add the node-hide-console-window functionality to their application. For example, the npm page for the malicious package was set up to look very similar to the page for the legitimate package. Also, the malicious npm package had 10 versions published, the same as node-hide-console-window.
This latest campaign began at the end of August.
Figure 1: Legitimate package’s versions
The malicious node-hide-console-windows package attracted ReversingLabs researchers' attention during routine monitoring of the npm public repository. The team regularly scans npm packages using the ReversingLabs Software Supply Chain Security platform. Packages that contain suspicious characteristics are identified and manually vetted by our researchers.
When our researchers discover malicious packages, we report them to npm maintainers so that they can be removed. We also conduct more in-depth analysis on our own to better understand malicious supply chain campaigns. The node-hide-console-windows package displayed a number of peculiar behaviors our team often finds in malicious packages, prompting greater scrutiny.
Figure 2: Behavior indicators of node-hide-console-windows
For example, in addition to the package’s suspiciously familiar name and version history, the maintainer account responsible for the package was newly created and not connected to any other npm projects. More to the point, upon inspection by RL's Software Supply Chain Security platform, malicious code was located inside of the node-hide-console-windows file index.js, which is specified as the main inside package.json. The code in that file wasn’t obfuscated nor did it look very trustworthy. When it ran, it fetched an executable that was detonated immediately thereafter.
DiscordRAT - An Open Source Trojan?
So the research team took a look at the executable that the index.js file fetched. Our analysis quickly identified it as a copy of DiscordRAT 2.0, an open source “Discord Remote Administration Tool” that is intended “for educational use only.” In short: this is open source malware.
This was not the first time malicious actors have used a copy of open source malware available on GitHub in an actual attack. In May, for example, we observed a malicious npm package nodejs-encrypt-agent that contained a malicious executable file which turned out to be TurkoRat, an open source infostealer packaged with legitimate npm package pkg. More recently, the third stage executable connected to the recent Roblox campaign was discovered to be a PyInstaller-compiled executable serving Luna Grabber, another open source infostealer.
For would-be attackers, DiscordRAT 2.0 is very simple to use. Its authors provided detailed instructions in the readme.md file that are easy to follow. The bot needs to be registered with the Discord developer portal and added into the Discord server or guild, through which a malicious actor wants to control it.
Before deploying it, a bot token must be acquired from the Discord developer portal along with a guild ID in which the bot was added. This is then included inside the malicious DiscordRAT 2.0 executable, which can be delivered to victims through various channels including as phishing email attachments, packages deposited on public repositories and targeting developers, and so on.
The team extracted both these identifiers from DiscordRAT’s configuration using the IDA Pro application. The bot token used in this malicious executable was:
MTEzNTM5NDcwMTk3ODEwODAxNg.GtdDHG.Aaj0Z8_IKQtFSG2p6VIQeDqNBvd-PkLeTD8WnE. The guild ID was: 1140853704396902591.
Figure 3: DiscordRAT’s configuration
To discover more information about the Discord guild that was managing the DiscordRAT (and potentially collecting sensitive information from the victim’s machine), the team used the open source tool DiscordLookup. It turned out that the guild was launched on August 15, only 10 days before the first version of the malicious node-hide-console-windows package was published.
Figure 4: Guild creation timestamp
Execute once, no further action needed
DiscordRAT makes managing infected hosts easy. Once the malicious executable is run, it creates a channel in the associated Discord server- one channel for each victim. At the same time, an initial payload is sent to the infected host (Figure 5).
Figure 5: Starting payload sent to newly created Discord channel
Following that, the bot is waiting for a malicious actor to send additional commands. DiscordRAT provides series of commands for everything from extracting information to controlling the victim’s machine by disabling Windows Defender and firewall, killing processes, blocking use of the victim’s mouse and keyboard, as well as shutting down or “bluescreening” the infected device. (A long and complete list of these commands is available on DiscordRAT's GitHub page.)
Getting to the root(kit) of the problem
As we continued our investigation of the package and executable, our interest was piqued when we noticed one of the commands named: !rootkit. This command allowed malicious actors to launch the r77 rootkit on the victim's machine.
Like DiscordRAT, r77 is an example of open source malware with extensive documentation that makes it easy to deploy, even by novice actors. r77 is a fileless ring 3 rootkit that is able to disguise files and processes and that can be bundled with other software or launched directly. r77 is a recent addition to DiscordRAT 2.0, with previous versions of that open source malware (Discord-RAT) lacking the ability to launch a rootkit. Also of interest: the DiscordRAT 2.0 executable we studied did not use the newest version of the r77 rootkit, but an older version of the rootkit.
In terms of functionality, when the bot receives the !rootkit command, the r77 rootkit is launched and two registry subkeys are created to hide the bot's presence. One subkey is used to hide the path of the executable. The other is used to hide the bot’s process, meaning that the executable that launched the bot and the path to the executable are hidden from the user of the compromised device.
(We also discovered another command !unrootkit, which removes the r77 rootkit from the victim’s machine.)
This wasn’t our first time encountering the r77 rootkit. The malware has been the star of a number of previous malicious campaigns. However this was the first time that ReversingLabs researchers found r77 hiding in a malicious open source package on npm.
But wait… there’s more!
All 10 versions of node-hide-console-windows that we analyzed downloaded the same malicious executable serving DiscordRAT 2.0. Interestingly, the last two versions had an added malicious payload disguised as visual code update that was fetched by index.js in addition to the DiscordRAT.
Once again, this unexplained behavior was a major red flag that warranted more in-depth analysis: A random npm package downloading an update for Visual Studio Code from an arbitrary page not connected to the official page, paired up with various different suspicious behaviors.
Figure 6: Behavior indicators of the second downloaded executable
In this case, the malicious payload associated with visual code update turned out to be a PyInstaller-compiled executable serving Blank-Grabber, an infostealer written in Python 3 that recently switched maintainers after its original author transferred control of the project to one of a contributor.
An open source package delivering a PyInstaller-compiled open source infostealer is something we saw recently with the Roblox campaign, though the deliverable there was LunaGrabber rather than Blank-Grabber. Still, the similarities suggest that malicious actors are turning to open source projects to plant malware while evading antivirus detection.
Indicators of Compromise (IOC)
The following IOCs were collected as part of ReversingLabs researchers' investigation of the node-hide-console-windows software supply chain campaign.
npm packages:
package_name | version | SHA1 |
node-hide-console-windows | 1.5.7 | cbb162d0623ff74925ecd4cfff7faef87bf45efd |
node-hide-console-windows | 1.5.6 | af0dbb3f13dc432924092783fe30433c24b3c929 |
node-hide-console-windows | 1.5.4 | 54ea32fa0c81c4da247121aa3c9aaf218b9e27f9 |
node-hide-console-windows | 1.4.4 | c24c666979267304ed42748153301fdadf46d40e |
node-hide-console-windows | 1.3.4 | f58431d141672cde5df4dfa82cb02f1df35fe6b8 |
node-hide-console-windows | 1.2.4 | 6cc6f76d75887485e0614e74acb2fb5c5bc55628 |
node-hide-console-windows | 1.2.3 | 74a3f8f5bf9ceefd95ad7102de9049250d501369 |
node-hide-console-windows | 1.2.2 | 08e4acca3c4a87c90141fc9ef90fe7974e4bccf3 |
node-hide-console-windows | 1.1.2 | d40b6f93acb2b88a88a42f9fc4163ec4449b68e6 |
node-hide-console-windows | 1.1.0 | b93898d08b3b6263a168bf9f13a5aa05761ab6c4 |
Second stage payloads:
SHA1 |
1563b5814b7dd655892a80be3a6cc740dad282a3 |
43feaf19f1a7410358ab8cd51f00b2446d62e798 |
Conclusion and a call to action
Compared with other malicious supply chain campaigns such as IconBurst, the r77 rootkit campaign had a limited reach among developers. Before being detected and removed by npm maintainers, the node-hide-console-windows was downloaded around 700 times — a fraction of the downloads associated with the malicious IconBurst packages. So, was this a sophisticated, targeted campaign, or just noise — an unsophisticated lark by low skill script kiddies? It is unclear to the team at this point.
On one hand, our research shows that the malicious actor or actors made an effort to make their packages appear trustworthy. As we observed, the actor or actors behind this campaign fashioned an npm page that closely resembled the page for the legitimate package that was being typosquatted, and even created 10 versions of the malicious package to mirror the package they were mimicking.
On the other hand, all of the projects used in this campaign were well-documented, open source malware posted to major platforms like GitHub “for training purposes.” In other words, the entire campaign was fashioned from components that are freely and publicly available online. Such a campaign requires little effort by attackers to build and execute. The reliance on known and frequently deployed open source malware also increased the chances of detection by the targeted organizations.
Still, for the thousands of developers utilizing popular open source projects like node-hide-console-window, such distinctions don’t matter. Regardless of how this campaign ranks in sophistication, these packages highlight an always present, and growing, danger lurking on public repositories such as npm or PyPI, as well as on GitHub. Something as dangerous and invasive as a rootkit is easily available to everyone, well documented, and ready for use.
Such availability makes supply chain attacks — once the province of well-resourced and sophisticated, nation-state or cybercriminal groups — accessible to low-skill malicious actors and “script kiddies.” For development organizations of all kinds, that’s even worse news than a slick, targeted and covert campaign like the one targeting 3CX or SolarWinds. That’s because it shows that the supply chain attack door is now open to low-stakes actors, who may fool incautious developers and infiltrate development pipelines in ways that reverberate far and wide.
Like other recent campaigns we have highlighted, this campaign underscores the need for organizations to sharpen their tools for detecting risks from open source packages. As with this case, these attacks hinge on developer inattention to small details in naming — in this case a single letter “s.” But that’s not the only trick available to would-be supply chain attackers. The use of obfuscated code is a major warning sign. Other indicators include suspicious naming and package versioning, new packages with sketchy histories, 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 also 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 threat hunting and Software Supply Chain Security platforms, deliver the visibility teams need to discover malware.
Keep learning
- Find the best building blocks for your next app with RL's Spectra Assure Community, where you can quickly search the latest safe packages on npm, PyPI and RubyGems.
- Get up to speed on securing AI/ML systems and software with our Special Report. Plus, see the Webinar: The MLephant in the Room.
- Learn about complex binary analysis and why it is critical to software supply chain security in our Special Report. Plus: Take a deep dive with RL's white paper.
Explore RL's Spectra suite: Spectra Assure for software supply chain security, Spectra Detect for scalable file analysis, Spectra Analyze for malware analysis and threat hunting, and Spectra Intelligence for reputation data and intelligence.