Aqua Nautilus security researchers have revealed that threat actors could perform a timing attack on npm’s API to uncover private packages.
A malicious attacker can send multiple consecutive requests to determine if the package exists or has been removed. Such a timing attack consists of comparing “the time it takes to search for a private package that exists with a private package that doesn’t exist,” Aqua’s Yakir Kadkoda wrote.
The researchers discovered it takes around five consecutive API requests to find that the API response takes significantly more time when the package exists or has been removed: 648ms vs. 101ms. Such a gap allows the discovery process to be automated by creating a list of potential package names to be tested.
The issue was reported to GitHub’s bug bounty program in March 2022, but the platform’s answer is not reassuring: “Because of these architectural limitations, we cannot prevent timing attacks from determining whether a specific private package exists.”
How Hackers Can Exploit the API Design Flaw
Kadkoda’s methodology is quite straightforward: he created a private npm package under a “random-organization” and uploaded some files.
Then he verified that the package existed with an authenticated and authorized user (member of the organization). He did the same with an unauthenticated user but did not find notable differences with a single consecutive request. It’s only after five consecutive requests from “various systems” that the results became significant:
This information could be exploited to disclose private package names and perform various malicious techniques like typosquatting or dependency confusion to hack the software supply chain.
To achieve that, attackers could use generic or more customized dictionaries with names that contain the name of the organization. It’s not uncommon for dev teams to apply some naming convention to keep things organized and clean.
According to Aqua researchers, an attacker may also use public datasets to get a list of removed public packages that could have been converted to private packages.
It’s definitely not the first time npm (and other platforms) has been impacted by such threats, which put many organizations at risk (see Software Supply Chain: A Risky Time for Dependencies).
“Over the past few years, we’ve seen a dramatic increase by hundreds of percentage points in supply chain attacks,” Kadkoda wrote. “In some cases, the threat actors’ goal is to gain access to open-source packages/projects and poison them. Other times they masquerade as private or public packages/projects, deliberately misspelling their names in order to trick unsuspecting victims into downloading their malicious package instead of legitimate popular ones.”
How to Protect Against the npm Timing Attack
Aqua Nautilus recommends recording all private and public packages, a good practice that can be summarized as “know your supply chain.”
The researchers said dev and security teams should also look for typosquatting, lookalikes, or masquerading packages.
“Verify that there are no other packages with the same name as your internal private packages,” they said. “If you find any similar packages, make sure that they do not contain malware and notify the relevant stakeholders.
“If you don’t find public packages similar to your internal packages, consider creating public packages as placeholders to prevent such attacks.”
Because big software platforms have huge constraints, fixing flawed API design and other security holes can take a long time or even be marked as “won’t fix.” It does not mean companies should quit all third-party services and handle everything by themselves internally, however.
- The DIY approach is not always rewarding, as it shifts the responsibility to the end of the chain without guaranteeing better security
- The total cost would rise significantly and could even make the infrastructure a maintenance and security nightmare
Another good approach is to avoid multiplying private packages, which is pretty tempting for dev teams but not always the best way, as many utilities can be grouped and refactored. The more private packages you create, the more it extends the attack surface, by definition.
Many teams start with internal tools that could potentially become great public open-source packages, but there’s no need to keep everything at the same place. Nobody needs the complete history. Just create a public repository with the same name, and leave it blank until it’s time to share it publicly.
You’ll avoid unwanted disclosures via the Git commits too.
Last but not least, have documented procedures to install and use dev environments and prevent developers from installing (and committing) packages. Adding, updating, or removing packages requires team reviews.
Get the Free Cybersecurity Newsletter
Strengthen your organization’s IT security defenses by keeping up to date on the latest cybersecurity news, solutions, and best practices.