Malicious NPM packages target marked-js library
marked-cs-malicious-package-banner

Two NPM packages masquerading as legitimate javascript libraries were published to the NPM registry this week. 

The packages were published by a user named “kamations” and target the marked-js ecosystem.  Two of the packages appear to be carbon copies of the legitimate marked npm package.

The two malicious packages are marked-ps and marked-cs.  You can find them here:  https://www.npmjs.com/~kamations

malicious-npm-packages-target-marked-js

TIP: Scroll to the bottom for IOCs

What is marked-js?

Marked-js is a popular Javascript library that allows developers to use, embed and edit Markdown in a browser.  It’s a handy library and if you’ve ever edited Markdown in a web app, you were probably using marked-js.

Marked-js is a legitimate, popular and actively maintained Javascript library that was originally published 13 years ago.  It’s NPM package is named simply “marked” and you can find it at https://www.npmjs.com/package/marked

There are 187 versions of the package and more than 8600 other NPM packages depend on marked-js.  The marked NPM package is downloaded more than 8 million times a week!  Suffice it to say, it is one of those very popular Javascript libraries that bad guys love to target!

Very confusingly, the legitimate project is named “marked-js” but the NPM package is simply named “marked”.  Bad guys are taking advantage of these slight differences to deploy lookalike packages.

legitimate-npm-package-marked-stats

Malicious actors are copying the marked-js NPM packages

Threat actors have published two malicious packages marked-ps and marked-cs.  I know, its confusing right?  Marked and marked-js are legit, but marked-cs and marked-ps are not.  Anyhow, these two malicious packages are very similar in how they deploy their malicious payloads.  I will focus on the marked-cs package which is the more popular of the two packages.

I’m including screenshots of the two malicious packages marked-cs and marked-ps so you can see how similar they are to the real marked package.  Marked-cs can be found at https://www.npmjs.com/package/marked-cs

marked-cs-malicious-npm-package

And marked-ps can be found at https://www.npmjs.com/package/marked-ps.

marked-ps-malicious-npm-package

The legitimate package, marked can be found at https://www.npmjs.com/package/marked

legitimate-marked-npm-package

The threat actor has copied the real README file from the legitimate package and used it for both of their malicious packages.  Honestly, if you didn’t know that marked-cs and marked-ps were malicious I could see someone installing these packages thinking they were the real thing.

 

How did I initially find these threats?

I was originally alerted to these marked lookalike packages by my GitHax tool.  It analyzes every new package published to NPM looking for unique signals that the package is malicious.

githax-identifies-malicious-npm-package-marked-js

These two malicious packages marked-ps and marked-cs are very similar in how they deploy their malicious payloads.  I will focus on the marked-cs package which is the more popular of the two packages.

NPM stats can be faked

One of the biggest problems with the NPM ecosystem is that it’s easy for malicious actors to fake some of the details in their malicious package uploads.  For example, in the image to the right which was taken from one of the malicious packaages, the repository and homepage list the legitimate marked-js information.  It’s the same with the Issues and Pull Request statistics at the bottom.  These fields are pulled from the GitHub repository you list in the package metadata, which can be anything you want to put there.

The problem with that is that NPM doesn’t verify that you own the GitHub repository, so what threat actors do is include a legitimate GitHub repo in their malicious package metadata to “piggyback” off the reputation of the original, legitimate GitHub repo.

This helps their malicious package appear more legitimate and is a common technique that malicious actors use to hide in plain sight.

marked-cs-package-info

Watching the attack evolve

Marked-cs was first published on January 7th, and the author has been actively working on it .  They’ve published 13 versions of the package in that time which has given me an excellent opportunity to watch their attack evolve over those three days.

The marked-cs NPM package has had over 700 downloads over the last three days.  This is worrying as the package deploys malware so those 700 downloads represent some number of potential victims.

marked-cs-version-downloads

Let’s inspect the package files

If you inspect the package files, either by downloading the package tarball, or browsing in the web UI, you’ll see that there is a tarball in the package/lib directory.   Threat actors use this common technique:  nesting a second tarball, or compressed archive, inside the main NPM package tarball.

Amongst the package files, there is also a marked.vbs file.  This file is a Visual Basic Scripting edition script, also known as VBScript.  These scripts are an older Microsoft scripting language that predates Powershell.  VBScript is deprecated and support for the scripting language will be removed from Windows operating systems between 2025 and 2027.  Some threat actors use VBScript to bypass Powershell detection rules in security scanning tools.

 

marked-cs-file-listing

The package.json file is the file that defines how the Javascript in the NPM package is executed.  Once the package is installed locally, the postinstall script is called, which runs npm run dev, which in turn runs node ./main.cjs

malicious-npm-package-json

If you inspect the main.cjs file it really only does one thing:  it executes the marked.vbs script.

marked-ps-vbs-script

VBS script

The VBScript file does a number of things integral to the deployment of the malware in this package:

  1. It disables the Windows Defender endpoint and detection response tool so that Windows can’t detect what’s going to happen next.
  2. It disables push notifications so that administrators won’t know that anything is happening.
  3. It unzips the tarball and then runs the marked.exe file that was in that tarball.
  4. It adds the marked.exe file to the Windows registry.  This will run the marked.exe after the system is restarted.
  5. Finally, the VBScript removes the files that deployed the malware and hides the marked.exe file.

marked-cs-npm-package-explain-vbs-script

The different versions of the marked-cs packages deploy different payload files, which you can see in this screenshot.  You can browse all the versions of the package at https://www.npmjs.com/package/marked-cs/v/2.1.0?activeTab=versions

marked-ps-malicious-package-tarballs

The malware payload

The latest version of the marked-cs package deploys a file marked.exe as its payload. Earlier versions of marked-cs and the other package marked-ps instead drop a file named marked.scr.

Let’s start with the marked.exe file.  If you scan this file with Virustotal, it identifies the file as malicious.

marked-cs-malicious-package-virustotal

What does the malware do?

Virustotal has confirmed that marked.exe is malicious, but what does it do?  To find that out, let’s run the file in a sandbox.  I’ll use the Any.Run sandbox, but there are others like Joe’s sandbox and Recorded Futures Triage.

When I execute the marked.exe file in Any.run, the sandbox watches what it does, what it downloads, and what IP addresses or domains it talks to.

malicious-npm-package-sandbox-output

In this case, the malware analyzed the local system to learn about its environment, and then it reached out to a command and control (c2) server at 43.134.113.193 on port 8000.

Any.Run identified that the malware was an all-purpose malware variant named Purplefox.

npm-package-payload-purplefox

Okay, let’s run the second payload “marked.scr” through the same process.

anyrun-sandbox-marked-scr-findings

The marked.scr file is different than the other payload marked.exe, but they are similar.  They both talk to the same IP address 43.134.113.193 for their C2 and they both do some of the same system recon.

Will source code or package scanning tools protect you from these malicious packages?

Okay, so we’ve verified that these packages are malicious.  Even worse, they drop active malware onto any hosts that install the NPM packages which then connects to a C2 server and takes control of the infected host.  Sounds like something that security scanning tools should pick up right?

Well guess what?  Software composition analysis (SCA) tools are not very good at identifying known malicious packages.  So even if GitHub Security Advisory or OpenSSF’s OSV mark the package as malicious SCA tools typically don’t report this fact to paying customers.

I scanned the marked-cs package with Snyk and it didn’t find anything wrong with it.

snyk-doesnot-identify-malicious-packages

I tried the same thing with Socket.  It was a little better and at least identified that the marked-cs file ran shell commands, but the reality is that half the legitimate packages in NPM registry run shell commands and the vast majority of packages have install scripts.

That’s hardly detecting genuine malicious behaviour.  My guess is that this is what Socket reports for 99% of public NPM packages.  Not encouraging.

socket-doesnot-identify-malicious-npm-packages

Indicators of Compromise (IOCs)

Based on my research these two NPM packages marked-cs and marked-ps have very similar, but slightly different behaviours:

Files:

marked.vbs – sha256 hash: 24dacbd59519a976a313dd1dc21f92ddd309719abcf230b3a98ff7f338a79fe6

marked.exe – sha256 hash: 9d8621a7190ee4015efbc7a093387279a8b6adf06e0b7fc3869a894a9484c864

marked.scr – sha256 hash: 3c3c638aecdd17cc243ee51137ee3240be37ce0a9e1ffdd9d78a6ae7e4e764fa

main.tar.gz – sha256 hash: c24ff7dd833a0ef30a60edb24131935d8b6cf600713f87a3d6870d33fe08274d

C:\Users\admin\AppData\Roaming\DYA_RFVEFSPQPULUKLRTH\1.0.0\Data\dya.dat

IP addresses:

43.134.113.193 TCP port 8000

What can you do?

I’ve alerted NPM but these packages haven’t been marked as malicious yet, so no security tool could protect you from these malicious packages. Unfortunately, that’s how most software supply chain security tools work:  you have to know that a package is malicious before the tool can protect you.

But in general, it’s a good idea not to install NPM packages blindly.  If you know what to look for, there are definite signals that these packages are dodgy.  All of these packages have just two files:  package.json and index.js (or main.js).  This is one of several flags that you can use to determine if a package is legit or not.

Hopefully, NPM will remove these packages soon.

paul-circular-githax-photo

Paul McCarty

SourceCodeRed.com Security Research & Trainer

 

https://www.linkedin.com/in/mccartypaul/

Read about Software Supply Chain Red Teaming