Get details on the Legit research team's discovery of a dependency confusion vulnerability in an archived Apache project.
The Legit research team recently discovered a dependency confusion vulnerability in an archived Apache project. This discovery highlights the need to consider third-party projects and dependencies as potential weak links in the software development factory, especially archived open-source projects that may not receive regular updates or security patches. In most cases, archived projects live on in organizations as legacy, an outcome of the infamous “if it’s not broken, don’t fix it.” Although it may seem tempting to leave them as is, these projects tend to have vulnerabilities that are not getting attention and not likely to be fixed.
What Is Dependency Confusion?
Attackers can initiate software supply chain attacks by inserting vulnerable dependencies in open-source software using techniques such as Typosquatting, RepoJacking, and dependency confusion. In this blog post, we will focus on dependency confusion, a.k.a. “dependency hijacking” or “substitution attack.”
This type of attack occurs when referencing a private/local package, which should be taken from a private registry rather than the public one; however, a malicious package with the same name appears on the public package manager. Thus, an unwanted public package is downloaded instead of the private package. This attack exploits a behavior in the package manager, which looks for packages in the public domain first, and then in the private one.
After the discovery of this type of attack, NPM and similar package managers introduced configurations that aim to prevent it and prioritize the private version over the public one.
But what happens when these configurations are not set as they should be?
Proof of Concept
Let’s take a look at how we managed to exploit this misconfiguration in the wild:
Scanning some open-source projects, we stumbled upon “Cordova App Harness,” an archived open-source project by Apache.
Scanning through this project, we found a local dependency called “cordova-harness-client.” The way this package is referenced is through the package.json file, as seen in line 23:
The package behind this dependency is placed under node_modules/cordova-harness-client.
In this configuration, an attacker can upload a malicious version under the same name with a higher version (and still pass the ~0.0 requirement, e.g., 0.0.4), and NPM will prioritize the higher version from the public registry, meaning this malicious library will get downloaded and used instead of the local one.
To reference a local package safely, use a relative file path:
"dependencies": {
"cordova-harness-client": "file:./node_modules/cordova-harness-client#~0.0",
}
To check if this app is actually in use, I created a public NPM project called Cordova-harness-client with a higher version of the original project, which is identical to the original project and therefore not causing any harm. In just three days, the public package had more than 100 downloads!
This means that:
A) I was successfully able to hijack this library, which could include malicious code that would run when downloaded. The fact that it had many downloads shows that the library is still in use.
B) Although the parent library, Cordova App Harness, is archived, it is still being used and can pose a security risk to its users.
Impact
Upon exploitation, the attacker could execute arbitrary code on the host machine where the vulnerable application is deployed, utilizing the privileges granted to the application.
In simpler terms, this attack can result in Remote Code Execution (RCE) within the production environment.
Disclosure Timeline
March 17, 2024: Discovery of vulnerable repo
March 17, 2024: First version of the public package
March 19, 2024: POC success, real downloads are shown in NPM
March 24, 2024: A full detailed report is transferred to the Apache security team
March 25, 2024: The Apache security team acknowledged the report and accepted our suggested solution (hold a public version of the private package to prevent an attacker from grabbing it)
March 26, 2024: Transferred the public version of the package to Apache.
Importance of Proper Configuration for Package Managers
Although dependency confusion is based on a pretty simple idea, it is a multifaceted issue that is not trivial to address. Attackers can exploit various layers of this vulnerability, including package naming conventions, package manager behaviors, and repository configurations, to launch sophisticated attacks. Organizations must understand the depth of dependency confusion to effectively counteract these threats and protect their software ecosystems.
Proper configuration of package managers, such as NPM, is paramount in mitigating dependency confusion risks. By taking proactive measures, you can significantly reduce exposure to these types of attacks.
Conclusion and Recommendations
The Cordova App Harness POC example proves that dependency confusion is a significant threat to software development security. Organizations should ensure they will not get hacked or exposed by a malicious library in those methods. In addition, the risks associated with using archived third-party projects highlight the urgent need for proactive measures and best practices in software development.
Recommendations:
Implement security scans and audits: Conduct regular security scans and audits of your codebase to identify and address vulnerabilities, including outdated or archived third-party projects. Use automated tools and manual reviews to ensure comprehensive coverage.
Avoid deprecated projects: Replace archived or unmaintained third-party projects with actively maintained alternatives from reputable sources. Prioritize projects with regular updates, security patches, and community support to reduce the risk of security breaches.
Configure dependencies securely: Follow best practices for configuring npm dependencies:
- Configuring local packages in a relative path way
- Configuring private registry through the .npmrc/.yarnrc files
- Grabbing private scopes in the public domain to add an extra layer of security
- Using scoped packages
- Verifying package sources
- Implementing package signing and verification mechanisms
Educate development teams: Educate developers and development teams about the risks of dependency confusion and the importance of secure coding practices. Provide training on identifying and mitigating security threats related to third-party projects and dependencies.
Stay informed and updated: Stay informed about emerging security threats, vulnerabilities, and best practices in software development. Regularly update dependencies to incorporate security patches and enhancements from upstream sources.
By adopting these recommendations and integrating security practices into the software development lifecycle, organizations can strengthen their security posture, mitigate dependency confusion risks, and protect their software ecosystems from potential security breaches and vulnerabilities.
Learn more about software supply chain security in our whitepaper.