How to find NPM dependencies vulnerable to account hijacking
Security engineer outlines self-help strategy for keeping software supply chain safe
Following the recent disclosure of a technique for hijacking certain NPM packages, security engineer Danish Tariq has proposed a defensive strategy for those looking to assess whether their web apps include dependencies tied to subvertable email domains.
NPM, acquired by Microsoft's GitHub in March 2020, operates the NPM Registry, an online repository of code libraries that web developers include in their applications. It currently hosts almost two million packages and serves more than 174 billion downloads per month.
The attack described earlier this month by security consultant Lance Vick involves identifying NPM packages managed by email accounts tied to expired domains. By registering the expired domain, the attacker then gains control of any email addresses associated with that domain.
Taking over an NPM package tied to that domain then becomes a matter of resetting the password of the NPM account associated with the commandeered email address – the password reset message goes to the new account holder. It's a known attack vector that just hasn't been fixed.
Stand up and fight
The defensive strategy described by security engineer Danish Tariq offers admins and developers an opportunity to preempt this threat. It involves making a list of NPM packages within one's apps and querying each package for its maintainer's email:
npm view package_name_here maintainers.email
NPM's CLI just provides this information, though during the account creation process it does warn, "Your email address will be added to the metadata of packages that you publish, so it may be seen publicly."
The next step is to gather a list of email addresses – easily extracted by copying the CLI output history and pasting it into a tool like Debounce's Email Extractor to remove extraneous text.
Then the email list can be run through a bulk email validation tool like H-supetools to identify addresses tied to domains that have expired. Any associated packages could then be flagged for removal, based on the concern the maintainer accounts could be taken over at any time.
What's more, Tariq believes it would be reasonably simple to automate this process.
Risk and reward
Asked whether this approach could help attackers as well, Tariq said he doesn't see it raising the risk.
"Malicious users already know the ways or could find the ways in," he told The Register in an email. "But we have to notify the defenders on how to stay defensive."
He likens the situation to the way Log4shell was widely discussed online, which made attackers aware but helped defenders even more.
It should be said that the set of NPM maintainers who created accounts using custom domains and allowed those domains to expire is likely to be fairly small.
With any luck it's smaller than last December, when security researchers scanned NPM and found 2,818 maintainer email addresses associated with expired domains, through which they had the opportunity to hijack 8,494 packages via account takeovers.
Subverted NPM packages represent a potentially serious security threat, particularly if the compromised packages have become dependencies in widely distributed apps or libraries.
Lance Vick, asked for his thoughts on this Tariq's approach, said this is more or less what he did to find the expired domain in the attack he described.
The chains that bind
To help clients understand supply chain risks, Vick in an email to The Register said, "I programmatically count the number of unique maintainers/emails that control their dependencies. It is common for packages to have several maintainers, any of which can potentially take it over."
"I can then say something like 'These 2,415 people with these email addresses are currently more trusted than your own software engineers as they can effectively run any code they want on your production infrastructure without review from anyone.'"
"Statements like that don't make compliance auditors happy, but they are true and need to be said."
Vick said another approach he used for a client was to write a script to query domain ownership for all domains in the client's software supply chain and was able to identify an expired domain. He also said he will often simply attempt to reset the passwords on the NPM accounts associated with a client's dependencies, to give the client a list of people who don't have 2FA enabled and are at higher risk of account takeover.
"Phishing risk impacts roughly 90 percent of packages I have tried this with," he said, "but this can't be easily automated."
- Email domain for NPM lib with 6m downloads a week grabbed by expert to make a point
- GitHub's Dependabot learns to report bad news you can use
- GitHub to require two factor authentication for code contributors by late 2023
Attacks on the software supply chain increased 300 per cent in 2021 compared to the year prior, according to Aqua Security. And WhiteSource Security reports [PDF] finding more than 1,300 malicious NPM packages in 2021.
Vick said he's only aware of two fintech companies, out of hundred that he has direct or indirect exposure to, that actively review the dependency code they trust to control vast amounts of wealth.
"Few understand that code copied from the internet from strangers needs to be reviewed under the same scrutiny, if not higher, than code written by employees," he said. "The reality is most companies trust code written by random strangers more than their own employees, and it causes really embarrassing headlines."
Vick added, "I kind of empathize with historical doctors that spent their lives trying to normalize common sense things like washing hands and tools between patients."
A spokesperson for GitHub and NPM did not immediately respond to a request for comment.
Signs of progress
NPM is aware of the account takeover attack, among others, and is in the process of forcing NPM account holders to activate two-factor authentication (2FA), which can help avoid account-related mischief (though it doesn't assure code integrity like code signing).
The code registry began making 2FA mandatory for top 100 package maintainers in February – at which time, according to Aqua Security, about a third of the top 35 most popular packages were not using 2FA.
NPM plans to have the top 500 package maintainers using 2FA by the end of May, and later this year to extend this to maintainers of packages with more than one million weekly downloads or 500 dependents.
But this leaves maintainers of less used packages to decide for themselves whether 2FA security is worthwhile. To help make this happen, NPM has subjected this group to "enhanced login verification," which involves receiving an emailed one-time code on login to confirm account control. To avoid this extra step, you have to activate 2FA. ®