top of page
Hijacked NPM Account Leads to Critical Supply Chain Compromise

Cloud Security

Hijacked NPM Account Leads to Critical Supply Chain Compromise

Rony Moshkovich

Short bio about author here Lorem ipsum dolor sit amet consectetur. Vitae donec tincidunt elementum quam laoreet duis sit enim. Duis mattis velit sit leo diam.

Tags

Share this article

10/24/21

Published

As earlier reported by US-CERT, three versions of a popular NPM package named ua-parser-js were found to contain malware.


The NPM package ua-parser-js is used in apps and websites to discover the type of device or browser a person is using from User-Agent data.


The author of the package, Faisal Salman – a software developer from Indonesia, has commented about the incident:


Hi all, very sorry about this. I noticed something unusual when my email was suddenly flooded by spams from hundreds of websites (maybe so I don’t realize something was up, luckily the effect is quite the contrary). I believe someone was hijacking my npm account and published some compromised packages (0.7.29, 0.8.0, 1.0.0) which will probably install malware as can be seen from the diff here: https://app.renovatebot.com/package-diff?name=ua-parser-js&from=0.7.28&to=1.0.0 I have sent a message to NPM support since I can’t seem to unpublish the compromised versions (maybe due to npm policy https://docs.npmjs.com/policies/unpublish) so I can only deprecate them with a warning message.

There are more than 2.5 million other repositories that depend on ua-parser-js. Google search “file:ua-parser-js.js” reveals nearly 2 million websites, which indicates the package is popular.


As seen in the source code diff, the newly added file package/preinstall.js will check the OS platform. If it’s Windows, the script will spawn a newly added preinstall.bat script.


If the OS is Linux, the script will call terminalLinux() function, as seen in the source below:


var opsys = process.platform;
if (opsys == "darwin") { opsys = "MacOS";
} else if (opsys == "win32" || opsys == "win64") { opsys = "Windows";
	const { spawn } = require('child_process');
	const bat = spawn('cmd.exe', ['/c', 'preinstall.bat']);
} else if (opsys == "linux") { opsys = "Linux";
	terminalLinux();
}

The terminalLinux() function will run the newly added preinstall.sh script.


function terminalLinux(){
exec("/bin/bash preinstall.sh", (error, stdout, stderr) => {
    ...
});
}

The malicious preinstall.sh script first queries an XML file that will report the current user’s geo-location by visiting this URL.

For example, for a user located in Australia, the returned content will be:


<Response> <IP>[IP_ADDRESS]</IP> <CountryCode>AU</CountryCode> <CountryName>Australia</CountryName>
    ...
</Response>

Next, the script searches for the presence of the following country codes in the returned XML file:


  • RU

  • UA

  • BY

  • KZ


That is, the script identifies if the affected user is located in Russia, Ukraine, Belarus, or Kazakhstan.


Suppose the user is NOT located in any of these countries. In that case, the script will then fetch and execute malicious ELF binary jsextension from a server with IP address 159.148.186.228, located in Latvia.


jsextension binary is an XMRig cryptominer with reasonably good coverage by other AV products.


Conclusion

The compromised ua-parser-js is a showcase of a typical supply chain attack. Last year, Prevasio found and reported a malicious package flatmap-stream in 1,482 Docker container images hosted in Docker Hub with a combined download count of 95M. The most significant contributor was the trojanized official container image of Eclipse.


What’s fascinating in this case, however, is the effectiveness of the malicious code proliferation. It only takes one software developer to ignore a simple trick that reliably prevents these things from happening. The name of this trick is two-factor authentication (2FA).


About the Country Codes

Some people wonder why cybercriminals from Russia often avoid attacking victims outside of their country or other Russian-speaking countries. Some go as far as suggesting it’s for their own legal protection.


The reality is way simpler, of course:


  • “Не гадь там, где живешь”

  • “Не сри там, где ешь”

  • “Не плюй в колодец, пригодится воды напиться”

Polite translation of all these sayings is:


“One should not cause trouble in a place, group, or situation where one regularly finds oneself.”

Related Articles

Unleash the Power of Application-Level Visibility: Your Secret Weapon for Conquering Cloud Chaos

Unleash the Power of Application-Level Visibility: Your Secret Weapon for Conquering Cloud Chaos

Cloud Security

Mar 19, 2023 · 2 min read

Securing the Future: A Candid Chat with Ava Chawla, Director of cloud security at AlgoSec

Securing the Future: A Candid Chat with Ava Chawla, Director of cloud security at AlgoSec

Cloud Security

Mar 19, 2023 · 2 min read

The AlgoSec perspective: an in-depth interview with Kyle Wickert, worldwide strategic architect

The AlgoSec perspective: an in-depth interview with Kyle Wickert, worldwide strategic architect

Uncategorized

Mar 19, 2023 · 2 min read

Speak to one of our experts

bottom of page