Threat analysis: Malicious npm package mimics Material Tailwind CSS tool

Tailwind-CSS

ReversingLabs has discovered a malicious npm package disguised as the software tool Material Tailwind. Here's an in-depth look at our discovery — and threat analysis.

Highlighting the rise in risk from open source software repositories, ReversingLabs researchers discovered a new technique that threat actors are using to sow open source repositories with malicious code: a malicious NPM package masquerading as Material Tailwind, which is described on their website as “an easy to use components library for Tailwind CSS and Material Design.” 

Both of these components are recognizable names and massively popular libraries among developers, netting millions of downloads each. Tailwind specifically serves as an open-source CSS framework that doesn’t provide predefined classes for elements, while Material Design is a design language that uses grid-based layouts, responsive animations, and other visual effects. 

In contrast, the malicious Material Tailwind npm package, while posing as a helpful development tool, has an automatic post-install script, which downloads a password protected zip file that contains a malicious executable: a custom-packed Windows executable capable of running PowerShell scripts. 

The ReversingLabs research team spotted the package using our Titanium Platform, which tracks software behaviors, specifically looking for packages that contain obfuscated code. Here's our in-depth overview of how we came across this package, as well as how our team deobfuscated the malicious code to gain insight into the threat actor’s methods, and indicators of compromise (IOCs) that can help your organization determine whether or not you have been compromised. 

Obfuscated code: A red flag in npm packages

As with previous discoveries, Material Tailwind caught the attention of the Titanium Platform’s behavior indicator because it contained code obfuscated with JavaScript Obfuscator. 

Unlike the previous research cases, however, the threat actor responsible for Material Tailwind did quite a good job at making the package description as convincing as possible. Upon closer inspection, however, we noted that the package description is, in fact, copied from another npm package named tailwindcss-stimulus-components. The threat actor took special care to modify the entire text and code snippets to replace the name of the original package with Material Tailwind. The malicious package also successfully implements all of the functionality provided by the original package. 

Post-install shenanigans

But behavior indicators don’t lie. One of the JavaScript files present in the package contains obfuscated code. It also happens that this tailwindcss-stimulus-scripts.min.cjs file is also declared as postinstall script in package.json file. Packages delivered via npm let developers declare various types of scripts inside package.json file, those get executed at some point of the package lifecycle.

Postinstall scripts get executed immediately after package installation. This is why they are a quite popular mechanism for achieving code execution among threat actors. From the perspective of a threat researcher: an obfuscated script that is set to run immediately after installation is a (big) red flag. 

In the case of Material Tailwind, the obfuscated script was deobfuscated and its content was analyzed in detail. 

image (3)Figure 1: NPM module imports

Looking at the deobfuscated script content, the list of imported modules already looks suspicious. It contains modules for file system operations, encryption, network communication, archive decompression and process manipulation.

The module first sends a POST request with platform information to a specific IP address and validates that it is executed on a Win32 system. Then it constructs a download link containing the type of the operating system. It also adds a parameter which is probably used to validate that the download request is coming from the victim's machine. This parameter is generated by performing a bcrypt hash of the victim's IP address and removing the first 7 bytes from the hash value. 

image (4)Figure 2: Code responsible for stage 2 download

The downloaded file is a password protected zip archive named DiagnosticsLogger.zip which contains only one file, and it is named DiagnosticsHub.exe. The name of the executable varies between different versions of the package. For the current  ZIP archive version, the password that encrypts its contents is “J##$dj&%qvvV89”. Since the archive contains only one file, password protection is likely used to avoid basic antivirus checks.

The chosen file names suggest that the attacker is trying to disguise the payload as some kind of diagnostic tool. Finally, the script spawns a child process that executes the downloaded file using cmd /c command.

Windows executable

The downloaded Windows executable implements several protections to frustrate analysis. It is packed with a custom runtime packer. The Assembly unpacking routine utilizes xmm registers. Typically used for high precision math, they’re abused here for evading security solutions. The malicious code also performs long sleep delays in its execution, another effort to avoid detection. While running, the Windows executable is tries to contact trustworthy domains like google.com to verify that it has internet access and detect if it is executing in a sandboxed environment. 

Figure 3: Base64 decrypted powershell command creating Scheduled Task

Packed information includes several Powershell code snippets responsible for command and control, communication, and process manipulation. Persistence is achieved by executing a base64 encoded Powershell command which sets up a scheduled task to be executed daily.

At stage 2, the malware fetches a XOR encrypted and base64 encoded file from a public Google Drive link. In case this link isn’t accessible two alternative download locations exist, one at Github and another one at OneDrive. The XOR key it uses for decryption is the hardcoded string “AJUHKJHOIU351q23AJKI8i7y”. 

Figure 4: Google drive file decryption routine

At the time of publication, the encrypted file contains a single IP address, which is the location of its command and control (C2) server, from which the malware receives encrypted instructions using a dedicated socket connection. During dynamic analysis of the malware the C2 server responded with a command indicating that the status of the victims machine wasn’t initialized, which triggered execution of a Powershell command performing a directory listing of the   “C:\Program Files” and “C:\Program Files (x86)” folders. The output was stored in the “C:\ProgramData\DiagnosticsLog\Diagnost.log” file, probably to be uploaded to the C2 server later. 

Figure 5: Powershell directory listing command

Imposter packages are on the rise

This Material Tailwind attack is just the latest example of a growing trend: malicious npm packages that attempt to fool developers by posing as legitimate packages. For example, in the IconBurst campaign that we first discovered and disclosed in early July, we noted malicious NPM packages that name-squatted on heavily-used and legitimate packages, which hid their malicious content using code obfuscation. 

These types of software supply chain attacks can be spotted almost daily now. In most of these cases, the malware in question is fairly simple Javascript code that is rarely even obfuscated. Sophisticated multistage malware samples like Material Tailwind are still a rare find. 

In this case the complexity of the malware tactics leads to a conclusion that sophisticated actors could be behind this attack. For now, our analysis of the situation tells us that Material Tailwind’s stage two payload can be classified as a fully functional Trojan malware. It uses a lot of techniques to complicate reverse engineering. Additionally, IP redirection using a file hosted on a legitimate service like Google Drive is also performed before the communication with the actual C2 server. 

Given the advanced nature of this malicious package and the fact that it is imitating  widely used software development libraries, it is safe to assume that threat actors feel emboldened to continue taking advantage of open source repositories. And as their evasion techniques become more advanced over time, it is essential for software development shops to use a product like ReversingLabs Titanium Platform to spot malicious activity, and keep a close eye on application behaviors prior to including a new third-party dependency in their software. 

Indicators of Compromise (IoC)

IP addresses:

85.239.54.17
135.125.137.220

Package versions:

material-tailwindcss

2.3.0

466ed2f97d127e91ce29d79cd05dbedbe04c5c07

material-tailwindcss

2.3.1

faab8d9ad58d383ab895ff98bc215b497e78a89c

material-tailwindcss

2.3.2

dbd157edaa3f76d14f2bb2c2d81bab33db147f44

material-tailwindcss

2.3.3

3b8c4f1719456d5e6aac798fb27ab33753bb5ebc

 

Zip file:  

81977085079d5629cd9a932055273ed38a7ce87b

Stage 2 PE payload: 

748a67a4276a7547f2413c14b7de7f76342038ef

Stage 2 IP redirect providers:

h[XX]ps://onedrive.live.com/download?cid=8F081466BABC9F13&resid=8F081466BABC9F13%21109&authkey=AOGgyB9v2wrFkJM

h[XX]ps://drive.google.com/uc?export=download&id=1eaFJYy0cLLONFaMDKMUmcU6Js0jG5p8r

h[XX]ps://raw.githubusercontent.com/jfrank4512/Mdam/main/test.txt

Keep learning

Article Link: Threat analysis: Malicious npm package mimics Material Tailwind CSS tool