A group of more than 200 malicious npm packages targeting developers who use Microsoft Azure has been removed two days after they were made available to the public.
Security firm JFrog on Wednesday said that earlier this week its automated analysis system began raising the alarm about dubious uploads to the npm Registry, the most popular public source of software libraries for the JavaScript ecosystem. This group of packages grew from about 50 to at least 200 by March 21.
“After manually inspecting some of these packages, it became apparent that this was a targeted attack against the entire @azure npm scope, by an attacker that employed an automatic script to create accounts and upload malicious packages that cover the entirety of that scope,” observed security researchers Andrey Polkovnychenko and Shachar Menashe in a write-up. “Currently, the observed malicious payload of these packages were PII (Personally identifiable information) stealers.”
For npm – a command line tool for interacting with the npm Registry – scope serves to associate software packages with the name of an individual or organization. Packages scoped for use with Microsoft Azure append the descriptive package name (e.g. core-tracing) to the scope identifier “@azure” to create package identifiers like “@azure/core-tracing”. This makes it easier to search for Azure-relevant npm packages and easier for organizations to manage code.
The threat actor attempting this software supply-chain attack created at least 218 packages and gave them names identical to the @azure scoped packages but without the @azure portion of the name. In doing so, the attacker hoped to benefit from user error.
“The attacker is relying on the fact that some developers may erroneously omit the @azure prefix when installing a package,” explain Polkovnychenko and Menashe. “For example, running npm install core-tracing by mistake, instead of the correct command – npm install @azure/core-tracing.”
In addition to tailoring package names for typosquatting, the attacker appears to have been trying to facilitate a dependency confusion attack. This involves using high version numbers (e.g. 99.10.9) in the hope that internal npm private proxies – set up for fetching code from an internal registry – are configured to look for new versions of existing packages first from the public npm Registry before falling back to the local registry.
Polkovnychenko and Menashe speculate that the attacker may have been hoping to compromise the accounts of engineers working on Azure code within Microsoft as well as developers building software on Redmond’s cloud.
The attacker further tried to avoid detection by using an upload script that generated a unique username for each of the uploaded packages. That particular deception doesn’t count for much, since there are many other metrics that also get considered when attempting to programmatically assess whether an npm package is malicious.
The recent Socket service, for example, looks for anomalies related to install scripts, licenses, README documentation, significant code changes, network access, and unusual versioning, among other things, to spot suspect packages. JFrog offers a set of free npm scanning tools, too.
According to Polkovnychenko and Menashe, the supply-chain attack managed on average about 50 downloads for each of the 218 malicious packages in the two days it operated prior to being disrupted. That’s potentially as many as 10,900 victims.
The two security researchers argue that the surge in software supply-chain attacks through npm, PyPI, and other software package registries demands additional security measures.
“For example, adding a CAPTCHA mechanism on npm user creation would not allow attackers to easily create an arbitrary amount of users from which malicious packages could be uploaded, making attack identification easier (as well as enabling blocking of packages based on heuristics on the uploading account),” they suggest.
“In addition to that, the need for automatic package filtering as part of a secure software curation process, based on either SAST [static application security testing] or DAST [dynamic application security testing] techniques (or preferably – both), is likely inevitable.” ®