NoSQLi Private Program 2026-01-05
Full Database Dump via NoSQL Injection
Severity: Critical | Status: Resolved
Summary
During an API security assessment, I discovered that multiple GET endpoints were passing URL query parameters directly into MongoDB’s find() function without any sanitization. This allowed for the injection of MongoDB logical operators.
Vulnerability Details
The /api/categories endpoint was vulnerable to NoSQL injection through the use of MongoDB operators like $ne, $gt, or $regex in query parameters.
Root Cause
// Vulnerable code pattern
app.get('/api/categories', async (req, res) => {
const results = await Category.find(req.query); // Direct query injection
res.json(results);
});
Proof of Concept
An attacker could bypass application-level filters to extract all records:
GET /api/categories?_id[$ne]=000000000000000000000000 HTTP/1.1
Host: target.com
The server responded with the full list of all categories, effectively dumping the entire collection. Response size increased from 3KB to 13KB.
Expected vs Actual Behavior
| Scenario | Expected | Actual |
|---|---|---|
| Normal request | 5 public categories | 5 categories |
| Malicious request | 5 public categories | 47 categories (including hidden) |
Impact
- Complete compromise of data confidentiality
- Exposure of hidden/inactive entries
- Leak of voting structure and nominations
- Access to configuration data before official release
Remediation
// Fixed code - validate and sanitize input
const mongoose = require('mongoose');
app.get('/api/categories', async (req, res) => {
const id = mongoose.Types.ObjectId.isValid(req.query.id)
? req.query.id
: null;
const results = await Category.find({ _id: id, isPublic: true });
res.json(results);
}); Responsible Disclosure
This vulnerability was reported responsibly and fixed by the vendor before public disclosure.