🌐 No Sql Injection
A detailed write-up of the Web challenge 'No Sql Injection' from PicoCTF - 2024
📊 Challenge Overview
Category Details Additional Info 🏆 Event PicoGym Event Link 🔰 Category Web 🌐 💎 Points Out of 500 total ⭐ Difficulty 🟡 Medium Personal Rating: 2/10 👤 Author NGIRIMANA Schadrack Profile 🎮 Solves (At the time of flag submission) 4.351 solve rate 📅 Date 10-02-2025 PicoGym 🦾 Solved By mH4ck3r0n3 Team:
📝 Challenge Information
Can you try to get access to this website to get the flag? You can download the source here
🎯 Challenge Files & Infrastructure
Provided Files
Files:
🔍 Initial Analysis
First Steps
Initially, the website appears as follows:
With a login screen. Given the title of the challenge, I immediately thought of a
NoSQL Injection
. In fact, after opening the attached files, in theserver.js
file, I already found the first hint ofNoSQL
.
1 2
const mongoose = require("mongoose"); const { MongoMemoryServer } = require("mongodb-memory-server");
When
MongoDB
is used, it is always good practice to check for aNoSQL Injection
. As we can see, the user is created with the fieldsemail, firstName, lastName, password, token
(where thetoken
field contains the flag):
1 2 3 4 5 6 7
const userSchema = new mongoose.Schema({ email: { type: String, required: true, unique: true }, firstName: { type: String, required: true }, lastName: { type: String, required: true }, password: { type: String, required: true }, token: { type: String, required: false, default: "{{Flag}}" }, });
All set with
type: String
. I also found the initialization of a first user:
1 2 3 4 5 6
const initialUser = new User({ firstName: "pico", lastName: "player", email: "picoplayer355@picoctf.org", password: crypto.randomBytes(16).toString("hex").slice(0, 16), });
which shows an email I can use to log in:
picoplayer355@picoctf.org
(so the only field I don’t know is the password for the userpico
). In the source of thelogin
page, I found ajs
script that makes a request to/login
, sending thepassword
fields that we enter in the form with'Content-Type': 'application/json'
. If the response is handled successfully, I am redirected to the/admin
page:Trying to open
BurpSuite
and intercepting the login request withemail=a
andpassword=a
, I get this:Continuing to review the attached files, these are the exact lines of code where the vulnerability is present:
1 2 3 4 5 6 7 8 9 10
const user = await User.findOne({ email: email.startsWith("{") && email.endsWith("}") ? JSON.parse(email) : email, password: password.startsWith("{") && password.endsWith("}") ? JSON.parse(password) : password, });
If
password
start and end with{}
, the server attempts to parse them as JSON objects usingJSON.parse
. This allows the attacker to send malformed or malicious queries, which are accepted by the database as valid. Once the vulnerability is understood, we can move on to exploitation.
🔬 Vulnerability Analysis
Potential Vulnerabilities
- NoSQL Injection
🎯 Solution Path
Exploitation Steps
Initial setup
Since we already have a valid email
picoplayer355@picoctf.org
, we only need to perform aNoSQL Injection
on the password field.
Exploitation
In MongoDB, a query like the one used in the backend tries to find a user that satisfies two conditions:
Condition on the email:
email = picoplayer355@picoctf.org
:
- This condition is already satisfied, since we know a valid user with that email.
Condition on the password:
password = something
:
- This is the point we need to bypass. If we don’t know the correct password, normally the query would fail.
Since it’s a logical AND, both conditions must be true to find a user in the database. However, by exploiting the unvalidated input, we can manipulate the
password
condition to always be true. Thanks to the vulnerability, we can use MongoDB’s$ne
operator. This operator means “not equal” or “different from”. For example:
1
"password": { "$ne": "qualcosa" }
It states: “Find a document where the password is different from ‘something’”. Since there is always a password that is different from
'a'
(or any other static value we provide), this condition will always be true, regardless of the actual content of thepassword
field. By doing so, we can exploit the injection to retrieve the user data and the flag.
However, there is an important detail to consider: as we can see from the vulnerable code, the functionpassword.startsWith("{")
is called. If we directly send a JSON object as the password value, for example:
1
{"email": "picoplayer355@picoctf.org", "password": {"$ne": "a"}}
The backend will try to call the
startsWith
function onpassword
. Here’s the problem: the value ofpassword
is no longer a string, but already a JSON object (in our example:{"$ne": "a"}
). Since JSON objects in JavaScript don’t have thestartsWith()
method (which is a function defined only for strings), an error occurs, and the server returns:
1
{"success": false, "error": "password.startsWith is not a function"}
So, since it expects a string, we need to send a string. But be careful here as well, because if we send:
We will get another error due to the escaping of the
'
character. So, I use the\
character to escape the quotes, and by sending the following payload, I obtain the flag encoded inbase64
contained in thetoken
:
1
{"email": "picoplayer355@picoctf.org", "password": {\"$ne\": \"a\"}}
Once the base64 flag is extracted, we simply decode it to obtain the
plain text
:
1
echo;echo cGljb0NURntqQmhEMnk3WG9OelB2XzFZeFM5RXc1cUwwdUk2cGFzcWxfaW5qZWN0aW9uXzc4NGU0MGU4fQ== | base64 -d
(I added
echo;
at the beginning to have a\n
before the output, so the flag appears on the next line and not attached to the command text).
Flag capture
🛠️ Exploitation Process
Approach
The automatic exploit leverages the previously seen
NoSQL Injection
and performs all the steps mentioned, i.e., it retrieves the token, decodes it from base64, and then prints only the flag.
🚩 Flag Capture
Flag
Proof of Execution
🔧 Tools Used
Tool Purpose Python Exploit Burp Suite Web Testing
💡 Key Learnings
Time Optimization
When
MongoDB
is present, always keep in mind that it could be aNoSQL Injection
challenge.
Skills Improved
- Binary Exploitation
- Reverse Engineering
- Web Exploitation
- Cryptography
- Forensics
- OSINT
- Miscellaneous
📚 References & Resources
Learning Resources
📊 Final Statistics
Metric | Value | Notes |
---|---|---|
Time to Solve | 00:02 | From start to flag |
Global Ranking (At the time of flag submission) | Challenge ranking | |
Points Earned | Team contribution |
Created: 10-02-2025 • Last Modified: 10-02-2025 *Author: mH4ck3r0n3 • Team: *