Dependency confusion: Compromising the supply chain
Nowadays, developers use package managers to get and import libraries that are assembled directly with their code. With this in mind, bad actors could abuse these packages to exfiltrate sensitive information or even run code internally, as several apps are still under development on the internal network.
Because some projects have sensitive code or are private, companies use private libraries that are only available inside a private or internal package repository. Nonetheless, when the applications are built, the company’s developers mix the private with public libraries then downloaded from public packages portals such as npm, PyPi, NuGet and so on.
Figure 1: Popular public package portals.
At this point, researchers demonstrated that if a bad actor registers the private names on public package repositories and upload public libraries that contain malicious code, the code could be pushed from internal applications and results in data exfiltration or remote code execution.
The essence of how these attacks work is that many package installers will pick the one with the highest version number when faced with two different versions. For instance, if a bad actor learned the name of a target internal package or script, they can create and upload a malicious version with a higher version number in the public code repository, and the installer will automatically select and download the malicious version.
Deeper into the details
A researcher on Medium wrote about this dependency supply chain attack and demonstrated that several large companies were exposed using this approach.
By analyzing a common package.json file from PayPal, the researcher learned that the file contained a lot of public and private dependencies; public packages from npm and non-public packages names. This detail revealed a new pathway: those packages are probably hosted internally by PayPal.
Figure 2: Internal PayPal packages not available publicly.
By creating those packages in the public repository, executing arbitrary code automatically upon package installation was possible. That code simply collects some information about the target machine.
To accomplish this task, the researcher used DNS requests to bypass internal defenses. Considering that most of the possible targets would be deep inside well-protected corporate networks, but DNS traffic is usually the key in scenarios of this line.
Figure 3: DNS exfiltration approach used to get sensitive data from vulnerable code dependencies.
According to the researcher:
“A few full days of searching for private package names belonging to some of the targeted companies revealed that many other names could be found on GitHub, as well as on the major package hosting services — inside internal packages which had been accidentally published — and even within posts on various internet forums.”
Apple, Yelp and Tesla are just a few examples of companies that had internal names exposed in this way.
Figure 4: Yelp internal packages exposed on the internet via configuration files.
Using this approach, the researcher was able to interact with a lot of devices from several companies as observed in Figure 5 below.
Figure 5: Code execution on internal Apple devices.
Another common technique is called Typosquatting in package managers. It’s a valid approach to use together with dependency confusion chain, an attack leveraging typo’s versions of popular package names.
This attack relies on the generation of good permutations of names and takes advantage of the wrong keys that developers typed on their keyboard when they specified the package’s names to import in their code/apps.
Figure 6: Typosquatting found in a popular package: dependency confusion chain.
As observed below, the author of this piece of code wants to know the hostname, operating system and architecture of all the machines using the malicious package.
Figure 7: Malicious script taking advantage of package Typosquatting.
Hands-on threat intel training
Looking out for private packages
The name of private packages can be found in public code repositories, package.json files or other source code files. Using those names and registering them in public package resources, code execution can be achieved against several companies around the world. In detail, the researcher details how he successfully exploited this vector to infiltrate code and secure large bug bounties from Apple, Shopify, Microsoft and PayPal among others.
According to Microsoft's whitepaper, there are three ways to mitigate the risk of a substitution attack:
- Using a single private package feed online: pull any dependent public packages into your private repository so you can be sure of control. However, this does then mean you need to manually update the public package versions as needed.
- Controlling the scope: if your package manager supports scope control (like npm does) you can prevent internal packages from being retrieved from a public repository.
- Client-side verification: integrity verification, when enabled in the package manager, will abort the build if an unexpected change is detected in a dependent file.
In summary, organizations that use or develop their software must be warned that these kinds of attacks are possible and should do code review and also implement software best practices to mitigate potential risks used in attacks of this nature.
Sources:
3 Ways to Mitigate Risk When Using Private Package Feeds, Microsoft
Dependency confusion chain, Medium
Finding Evil Go Packages, michenriksen