A novel timing attack has emerged for targeting private corporate software packages hosted in the npm code repository. The goal is to uncover the legitimate offerings and then create malicious public packages using the same names in order to trick employees into downloading the doppelganger blocks.
Internal developer projects typically use standard, trusted code dependencies that are housed in private repositories on npm and elsewhere. The idea is to avoid software supply chain attacks and other code dependency issues, and to protect sensitive internal developer code. As such, if they can be hijacked or weaponized, they provide an attractive avenue for cybercriminals looking to crack corporate networks and exfiltrating sensitive information.
Code Dependency Confusion Rides Again
Last year, researcher Alex Birsan pioneered what's known as the code dependency confusion attack, using benign proof-of-concept (PoC) code blocks to target internal apps at Amazon, Lyft, Slack, and Zillow, among others. He created "copycat" packages to be housed instead in public repositories like npm, with the same names as the private legitimate code dependencies. What ensued was that internal projects began defaulting to importing the new public packages instead of the private ones.
The PoC demonstrated how outside code can be imported and propagated through a targeted company’s internal applications and systems, with relative ease — including at Apple, Microsoft, Netflix, PayPal, Shopify, Tesla, and Uber. Unsurprisingly, it didn't take long for malicious actors to replicate the attack pattern.
One way to defend against these kinds of attacks is to keep the package names secret so they can't be cloned. But according to Aqua Security’s Nautilus research team, it's possible to reveal private packages names by using a glitch in npm's registry API.
A New Type of Timing Attack
Npm's registry API allows users to check for the existence of packages, download them, and receive information about them. If a user searches for a private package or one that doesn't exist, the website throws a 404 HTTP error message in both cases. However, there's a difference in the amount of time it takes to return that error page: The average response time to 404 a private package is 648 milliseconds, while the average time when a package doesn't exist at all is just 101 milliseconds.
"If a threat actor sends around five consecutive requests for information about a private package and then analyzes the time taken for npm to reply, it is possible for them to determine whether the private package in fact exists," Nautilus researchers said in an Oct. 13 blog post.
There are a few methods that could be used to create a list of private package names to test with the timing attack, according to the research. These include:
- Guess the names of the private packages by performing a dictionary attack using the patterns found in the nomenclature of the organizations' public packages.
- Use online public data sets (such as libraries.io) access historic information about public packages that were deleted — these may have been converted to private packages.
The researchers reported the issue to npm owner GitHub's bug bounty program, getting this response: “Because of these architectural limitations, we cannot prevent timing attacks from determining whether a specific private package exists on npm.”
To protect themselves, the researchers said, corporations should be actively looking for typosquatting, lookalikes, or copycat packages, and verifying that there are no other packages with the same name as internal private packages being hosted in repositories.