code

RCE via Dependency Confusion Attack

Written by Sagiv Michael on

RCE via Dependency Confusion Attack

Written by Sagiv Michael on


Introduction

Efficiency and productivity are highly valued in the fast-paced software development world. Developers who work on complex projects require accessible and dependable external libraries, frameworks, and tools. This is where package managers such as NPM (Node.js), PyPI (Python), and RubyGems(Ruby) step in, acting as essential helpers, streamlining the development process, no matter which programming language is used.

In this article, we will discuss a critical security vulnerability related to the dependencies of a software project and how it can potentially lead to remote code execution. We will explore its implications on software development and how developers can mitigate this risk effectively.

What is a Dependency Confusion Attack?
The Dependency Confusion attack, also known as “dependency hijacking” or “substitution attacks,” is a severe security vulnerability that can impact organizations relying on package managers to manage their software dependencies. It occurs when a developer unintentionally installs a malicious or unauthorized package, leading to potential security breaches, data leaks, and arbitrary code execution in the applications.

The root cause of this attack vector lies in how some package managers handle the resolution of dependencies. In a typical scenario, when a developer specifies a package dependency in their project configuration file (such as the package.json file for NPM), the package manager attempts to fetch the required package from the official public repository or private registry linked to the organization.

However, attackers can exploit the fact that some package managers prioritize the public repository over private ones when resolving package names. They can create a malicious package with the same name as an internal package used within the organization. The package manager first checks the public repository for the package. In that case, it will unknowingly download the attacker’s malicious version, even if a legitimate version is in the organization’s private registry.

Subsequently, it creates “dependency confusion,” where the package manager installs the malicious package, potentially leading to disastrous consequences.

The attacker could use this opportunity to introduce backdoors, malware, or other harmful code into the organization’s software.

RCE Dependency Confusion Attack - NPM Package Manager Diagram Flow
NPM Package Manager Diagram Flow

Explanation of The Attack

To better understand how a Dependency Confusion attack can be leveraged and used as an attack vector, we will share a real-case scenario we encountered during a penetration test and demonstrate how we leveraged the attack vector to achieve Remote Code Execution (RCE) on a targeted system.

As a starting point, we studied the web application and learned about its purpose, business logic, and underlying technologies. This in-depth analysis gave us a comprehensive understanding of the website’s structure and potential vulnerabilities.

We conducted an OSINT (Open-source intelligence) activity, an essential step in gathering valuable information from publicly available sources. During the OSINT, we stumbled upon a significant discovery: an exposed file named package.json on the system’s client-side resources, storing crucial information about applications and modules utilized by the web application.

The exposure of the package.json file created a perfect opportunity for a Dependency Confusion attack, and we quickly realized its potential implications. 

RCE Dependency Confusion Attack - Node.js Dependencies Requirements
Node.js Dependencies Requirements

Upon examining the contents of this file, the web application utilized an internal dependency (for privacy reasons, we have altered the package name and its internal dependency). To verify that it was an internal dependency, we checked if it was available publicly on the Node Package Manager (NPM) official website, which was not. This indicated that the organization relied on its private registry to host and manage this specific package.

Recognizing the significance of this finding, we proceeded to conduct a Proof-of-Concept (PoC) to test and execute the attack thoroughly. Our objective was to demonstrate the potential consequences of a Dependency Confusion attack to execute arbitrary code (Remote Code Execution) on the targeted system.

Proof of Concept (PoC)

In our attempt to craft a Proof-of-Concept (PoC) that would effectively execute the Dependency Confusion attack on both Windows and Linux operating systems, we used the combined knowledge of three programming languages: Powershell, Bash, and JavaScript. Leveraging the HTTPS protocol (port 443) for our communication, we ensured that our PoC could bypass the company’s firewall restrictions, as this protocol is commonly allowed in the firewall’s rule base.

For the payload, we strategically designed basic OS commands that would grant us valuable information about the targeted system, including its public IP address, username, hostname, and current path. These details would provide essential reconnaissance data to assess the target’s security posture.

To execute our payload seamlessly after the package is installed on the targeted system by the company’s developers, we took advantage of NPM’s convenient feature known as “postinstall”. By specifying a script in the package.json file under “postinstall,” we ensured that our payload would automatically trigger after the package installation process was completed.

One crucial element we considered during the PoC development was the need for the internal package to be fetched from the public NPM registry. To achieve this, we published our custom package with version 99.99.99 on the NPM website. This approach ensures that the client application would fetch our “malicious” version hosted on the NPM website since it seeks the latest version of the internal package (“internal_dependency”), as shown in the above image (No. 2).

Publishing the Package with a Higher Version along with Postinstall Script

After waiting a while, we observed a couple of HTTP POST requests containing our crafted payload sent to our controlled web server – one from a Linux machine and the other from a Windows machine. These requests proved that the targeted machines had successfully installed our hosted package and triggered the execution of the system commands we controlled.

RCE Dependency Confusion Attack
Running Successful OS Commands on the Targeted Linux Machine
Running Successful OS Commands on the Targeted Windows Machine

Mitigation

If you have encountered any of the above scenarios, please follow to instructions below provided by Clear Gate for immediate mitigation and to prevent Dependency Confusion attacks further

  • Explicitly Specify Package Sources: Clearly define and prioritize the sources from which your package manager should fetch dependencies. This ensures that internal packages are fetched from private registries before searching public repositories.
  • Use Package Locking: Utilize package-lock.json (for NPM), Pipfile.lock (for Pip) to lock dependency versions. This ensures that your application always uses the intended versions, preventing potential substitutions.
  • Audit and Monitor Dependencies: Regularly audit the dependencies in your projects to identify vulnerabilities and update them to secure versions. Use automated tools to track and notify you of any potential security risks in your dependencies.
  • Implement Access Controls: Enforce strict access controls to limit who can publish and update packages in your internal package registry. Authenticate and authorize users based on their roles and responsibilities.
  • Verify Package Authenticity: Verify the authenticity and integrity of packages by using cryptographic signatures or checksums before installation.

Conclusion

In conclusion, exploring the Dependency Confusion attack and its attack vectors, such as Remote Code Execution (RCE), highlights the critical importance of securing software development processes. The real-life scenario encountered during our penetration test illustrates the risks of exposing sensitive configuration files, such as package.json.

Organizations should prioritize cyber security risk assessments and penetration tests to mitigate risks in dependencies deployments, which have become increasingly popular among companies developing SaaS products. Clear Gate, a trusted cybersecurity provider, offers in-depth manual penetration tests to help organizations strengthen their development process security and protect valuable data from potential threats.

References