CSEC CTF: Doors Plus

Jul 10, 2020 • 3 minutes to read

Challenge Info

This is a challenge from the UTS Cyber Security Society (CSEC) Semester-long CTF for 2020 Autumn session.

Link: here

Challenge Doors Plus

Let’s look around

So the challenge starts with a URL (not the YouTube link!). Go to that link we see:

Epic Doors Plus No Fuss API

Seems this website provides a set of web API. And our objective, as described, is to create a door named “Backdoor”.

Firstly I tried to send a GET request to /api/door with Postman:

Forbidden

I got a 403 error. Seems the authentication is a real deal. Well then, let’s become a legal user and get authenticated, by calling /api/user/register and /api/user/login.

Register:

Register

Login:

Login

So by sending my credentials in JSON format to /api/user/register and then to /api/user/login I got myself a token. With this token I should be able to access the APIs need authentication.

Well let’s try /api/door again with this token:

Doors

Cool! There are already some doors, and this API call seems to list them all.

Then I wanted to try adding a door. According to the API reference, I need to provide my user ID as ownerId argument. But so far I didn’t know my ID yet.

The token seems to be a JWT. So I tried to decode the token and see what it contains:

JWT

So my userId is 8121, and I’m not a admin. Now we can try adding a door:

Door created

It returned with the info of the door I just created. And let’s run a GET on this API again:

Doors 2

Our newly created doors is listed!

Next I tried /api/user/:id. First I give it a go with my own ID:

ttya

Yes, it’s me. It’s my username, and I’m not a admin.

Now I should try another ID. We can try all other IDs seen in the door list:

john2

ID 4592

user123

ID 123

Curious. ID 123 does not exist.

Seems as a registered user, I can see other users’ info, even if I’m no admin. It’s just natural to enumerate the numbers and see what we can get.

From previous tests we know that the status code of the response to GET /api/user/:id request will be 200 if the user ID exists, or 400 if the user ID doesn’t exist. So we can make a simple Python script to do this for us: enumerate through a lot of integers, and print the user info if the user ID exists.

I’ll show you the code:

import requests

base_uri = 'http://35.189.41.102:8000/api/user/'
headers = {'Authorization': 'Bearer eyJhbGc... <your token here>'}

for i in range(100000):
	print('\r%d' %i, end='')
	r = requests.get(base_uri + str(i), headers=headers)
	if r.status_code == 200:
		print()
		print(r.json())

After several minutes of numbers flashing, I found there are much more users than I imagined, and something interesting showed up:

Users

Funny you mentioned that. What would happen if I look into user ID 696969? Let’s find out:

Admin

Hah! 696969 is the admin!

However, I’m clueless now. How am I gonna POST a door as the admin? The API reference says the ownerId must match my auth token…

Wait a sec!

What if I try POSTing a door with my own token and filling the ownerId field 696969?

Wouldn’t hurt, right?

(A sensible API design wouldn’t even leave such a field for the client to fill, since all the doors can only be owned by whoever created them by design)

So. Ready, aim, fire!

Backdoor

Haha! We got it!

CTFcsecweb
comments powered by Disqus