SecurinetsQuals2K21's Hack The Empire Writeup

Dependency confusion, a supply chain attack challenge

Adarsh Shetty
6 min readMar 23, 2021

Introduction

Hey everyone, a little something about myself, I’m Adarsh Shetty aka albatraoz. I’m a Software Engineer at DNIF, a student pursuing Masters’s in Information Technology, a part-time bug hunter and I’ve recently started playing CTFs with my team thehackerscrew.

This writeup is about one of the web challenges of SecurinetsQuals2K21 CTF which was based on the dependency confusion research by Alex Birsan. I’ll try to keep this write-up as beginner-friendly as possible.

Challenge

Let’s not take more of your time and jump straight into the challenge. So the challenge didn’t have much information about what to hack. No IP address, no domain, nothing. It just said that we had to hack CTFQ21EmpireTmp. You can read the whole challenge description below:

Challenge Description

We will get to the important note given in the above descriptions later as it had a give away for this challenge which you will see in the latter part of this writeup.

Information Gathering

So the only information we had about this challenge was that the flag is in /flag.txt and we have to hack CTFQ21EmpireTmp which I didn’t know what It stood for. So I did what anyone else would do when they have no clue about something. Yes, I googled the word CTFQ21EmpireTmp and found there was only one search result which was a blog similar to stack overflow. There was a query posted by a developer maybe who belonged to CTFQ21EmpireTmp. Below is the snapshot of the query asked by the person.

Query posted by the developer on stackoverflow

The extra-index-url in the /etc/pip.conf rang a bell in my mind about the dependency confusion research which I’ve read about on Twitter. I quickly opened the article to go through it once and I got to know that the extra-index-url parameter is insecure by design. So what it does is:

  1. Check If the package exists in a private repository.
  2. Check If the package exists in a public repository i.e PyPI.
  3. Installs whichever version is found. If the package exists on both, it defaults to installing from the source with the higher version number

The query posted on StackOverflow also mentioned that system is installing all the packages which match the regex ctf_q21_empire_tmp_[a-z0–9_]{5,10}. This means that maybe If I create a python package that matches this regex and upload it to PyPI. This will lead the victim system to download the package from the public repository and execute the code embedded in the library. Remember that all this is possible because of the misconfiguration of the pip config with extra-index-url. We have all the pieces of the puzzle coming together so what are we waiting for? Let’s jump right into pwning the empire.

Exploitation

I’ll divide the exploitation part into multiple parts so that you can understand what's happening here.

  1. Create a python package with the name of the package matching the regex that we got previously so that the system installs it without any issue.
  2. The code inside the package has to go and fetch the flag from the system and return it to me somehow. (Remember? That’s why we are here in the first place)
  3. Upload the python package to PyPI which is a public repository so that system installs the package when it doesn’t find the package in the private repository due to misconfiguration as discussed previously.
  4. This step is nothing but waiting for the flag to be fetched in the duration when the victim system installs all the packages which is in the frequency of like every 5 minutes.

Step 1:

First and foremost I created a folder named ctf_q21_empire_tmp_albatraoz which will be the name of the package too as it matches the regex as discussed previously.

regex101

Step 2:

For creating a python package you need some files in the above-created folder and they are as follows:

  • setup.py
  • setup.cfg
  • LICENSE.txt
  • README.md (optional but recommended)

setup.py

This file will have the code that would be run when the package is installed. We will make this code fetch the flag from the system and send it through webhook (This was mentioned in the important part of the challenge description). So what we will do is read the content of the /flag.txt and send its content as the value of a query parameter to our webhook URL. The code snippet for the same is below:

If you look closely in the above snippet, I’ve added my webhook URL using https://webhook.site/ so that as soon as the package is installed I’ll get a request on my webhook with the flag in params.

Waiting for a hit with the flag

setup.cfg

Just a small config file that will have the description file parameter.

LICENSE.txt

This will contain the license details and you can go ahead and add any license that you want as it has no effect on the exploit whatsoever.

README.txt

A simple readme file with some information about what the package does.

You can find all the content of the package from my GitHub repository hosted here.

Step 3:

Let’s upload the package that we created to PyPI.

The first thing you have to do is create an account on https://pypi.org/ and verify your primary email address. This is important for uploading our python package to PyPI.

After the account creation, there are a few commands that you need to run for uploading your package to PyPI as follows:

Get inside the package folder that you just created

cd ctf_q21_empire_tmp_albatraoz

We have to create a source distribution with the following command

python setup.py sdist

We will have to install twine for uploading the distribution to the PyPI

pip install twine

Then run this command to upload the package to PyPI

twine upload dist/*

You’ll be prompted to enter your username and password after this command. Use the credentials that you used previously for creating an account on https://pypi.org/

Yayyy! 🥳 Your package has been successfully uploaded to the PyPI amd you can find it at https://pypi.org/project/[YOUR_PACKAGE_NAME]/

Step 4:

The package has been uploaded to the public repository and now all we have to do is just wait for the victim machine to install our package, execute the code inside the package and send us the flag through the webhook url params.

So just after waiting for 5 minutes, I got a hit on my webhook URL:

We got the flag!!

Let’s gooooo!🔥 We got the flag in the query parameters of the request with some description about the vulnerability that this challenge is related to which is dependency confusion. We hacked the Empire!!!

P.S:

A huge shout out to the Securinets for such an interesting challenge and Alex Birsan for his amazing research.

Last but not least for my team at thehackerscrew, we have a long way to go ❤️

Hope you enjoyed reading this interesting write-up as much as I loved writing this.

Ciao! ✨

--

--

Adarsh Shetty

I like to make things, I like to break things. I like to make things that break things.