HIGH command injectionmongodb

Command Injection in Mongodb

How Command Injection Manifests in Mongodb

Command injection in MongoDB occurs when untrusted input is incorporated into database queries without proper sanitization, allowing attackers to execute unintended operations. Unlike SQL injection in relational databases, MongoDB injection exploits the query language's flexibility and JavaScript engine integration.

The most common MongoDB injection vectors involve:

  • JavaScript execution through $where clauses that accept arbitrary JavaScript expressions
  • Operator injection where malicious operators like $ne, $gt, or $regex are injected into query objects
  • Object injection where attacker-controlled objects bypass type checking
  • Pipeline injection in aggregation pipelines where stage ordering can be manipulated

Consider this vulnerable Node.js code:

app.get('/users', async (req, res) => {
  const { username } = req.query;
  
  // VULNERABLE: Direct interpolation of user input
  const query = { $where: `this.username == '${username}'` };
  
  const users = await db.collection('users').find(query).toArray();
  res.json(users);
});

An attacker could submit ?username=' || '1'='1 to return all users, or more dangerously, inject JavaScript:

?username='; return db.adminCommand('listDatabases'); //

This executes db.adminCommand('listDatabases') on the server, potentially exposing database metadata.

Another common pattern involves operator injection:

app.get('/products', async (req, res) => {
  const { price } = req.query;
  
  // VULNERABLE: User controls the operator
  const query = { price: { $gt: price } };
  
  const products = await db.collection('products').find(query).toArray();
  res.json(products);
});

Here, an attacker could submit ?price[$ne]=0 to bypass price filtering entirely, or ?price[$where]=function(){return true} to execute arbitrary JavaScript.

Aggregation pipeline injection presents another attack surface:

app.get('/reports', async (req, res) => {
  const { groupBy } = req.query;
  
  // VULNERABLE: User controls pipeline stage
  const pipeline = [
    { $group: { _id: `$${groupBy}`, total: { $sum: '$amount' } } }
  ];
  
  const results = await db.collection('transactions').aggregate(pipeline).toArray();
  res.json(results);
});

An attacker could manipulate the pipeline structure by submitting field names that inject additional stages or modify query logic.

Mongodb-Specific Detection

Detecting MongoDB command injection requires analyzing both the query structure and the execution context. Static analysis tools can identify vulnerable patterns, but runtime scanning provides more accurate detection of actual attack surfaces.

middleBrick's MongoDB-specific scanning examines:

  • JavaScript injection points in $where clauses and aggregation expressions
  • Operator injection through query parameter manipulation
  • Object injection via type confusion in query construction
  • Pipeline manipulation in aggregation stages

Using middleBrick's CLI for MongoDB API scanning:

npm install -g middlebrick
middlebrick scan https://api.example.com --category mongodb

The scanner tests common MongoDB injection patterns including:

// $where clause injection attempts
{ $where: "this.username == 'admin' || '1' == '1'" }

// Operator injection payloads
{ price: { $ne: 0 } }
{ $where: "function() { return db.adminCommand('listDatabases') }" }

// Aggregation pipeline manipulation
[
  { $match: { $where: "function() { return true }" } },
  { $group: { _id: "$category", total: { $sum: "$price" } } }
]

middleBrick also analyzes OpenAPI specifications for MongoDB-specific vulnerabilities:

$ref: '#/components/schemas/QueryObject'

components:
  schemas:
    QueryObject:
      type: object
      properties:
        $where:
          type: string
          description: JavaScript filter expression (HIGH RISK)

During scanning, middleBrick tests unauthenticated endpoints by submitting payloads designed to trigger MongoDB-specific error messages or unexpected behavior. The scanner looks for indicators like:

  • MongoDB error stack traces in responses
  • Unexpected data exposure from injected queries
  • Changes in response structure when injecting operators
  • Execution time variations suggesting JavaScript evaluation

For applications using MongoDB Atlas or other managed services, middleBrick can detect configuration issues that increase injection risk, such as:

// Insecure configuration example
{
  "mongodbUri": "mongodb://localhost:27017",
  "allowJSInjection": true,  // NEVER set this to true in production
  "disableAuthentication": true
}

Mongodb-Specific Remediation

Effective MongoDB injection prevention requires defense-in-depth strategies. Start with input validation and parameterized queries, then add runtime protections.

Input Validation and Sanitization

Validate and sanitize all user inputs before query construction:

const { MongoClient } = require('mongodb');
const mongo = new MongoClient(process.env.MONGO_URI);

async function findUser(username) {
  // Validate input type and format
  if (typeof username !== 'string' || username.length > 50) {
    throw new Error('Invalid username format');
  }
  
  // Sanitize to prevent JavaScript injection
  const sanitizedUsername = username.replace(/['"]/g, '');
  
  const query = { username: sanitizedUsername };
  return await db.collection('users').find(query).toArray();
}

Avoid $where Clauses

Replace $where clauses with indexed field queries whenever possible:

// VULNERABLE
const query = { $where: `this.username == '${username}'` };

// SECURE
const query = { username: { $regex: `^${username}$`, $options: 'i' } };

// BEST - exact match with index
const query = { username: username };

Operator Injection Prevention

Whitelist allowed operators and validate query structure:

const allowedOperators = ['$eq', '$gt', '$gte', '$lt', '$lte'];

function buildSafeQuery(field, operator, value) {
  if (!allowedOperators.includes(operator)) {
    throw new Error('Invalid operator');
  }
  
  // Validate value type based on field
  const query = { [field]: { [operator]: value } };
  return query;
}

// Usage
const safeQuery = buildSafeQuery('price', '$gt', 100);
const products = await db.collection('products').find(safeQuery).toArray();

Aggregation Pipeline Security

Validate pipeline stages and use projection to limit exposed fields:

function buildSafePipeline(groupBy) {
  const allowedFields = ['category', 'region', 'productType'];
  
  if (!allowedFields.includes(groupBy)) {
    throw new Error('Invalid group by field');
  }
  
  return [
    { $group: { _id: `$${groupBy}`, total: { $sum: '$amount' } } },
    { $project: { _id: 1, total: 1 } } // Explicitly project allowed fields
  ];
}

const pipeline = buildSafePipeline(req.query.groupBy);
const results = await db.collection('transactions').aggregate(pipeline).toArray();

Database-Level Protections

Configure MongoDB to reduce injection surface:

// MongoDB configuration to enhance security
db.adminCommand({
  setParameter: 1,
  javascriptEnabled: false,  // Disable $where if not needed
  batchSize: 1000,
  maxTimeMS: 30000
});

// Use least-privilege database user
const dbUser = {
  user: 'app_user',
  pwd: process.env.DB_PASSWORD,
  roles: [
    { role: 'readWrite', db: 'myapp' },
    { role: 'read', db: 'myapp' }  // Separate read/write roles
  ]
};

Runtime Monitoring

Implement query monitoring to detect suspicious patterns:

const monitorQuery = async (query) => {
  const suspiciousPatterns = [
    /\$where\s*\(\s*function/i,
    /return\s+db\./i,
    /adminCommand/i
  ];
  
  const queryText = JSON.stringify(query);
  
  if (suspiciousPatterns.some(pattern => pattern.test(queryText))) {
    console.warn('Suspicious query detected:', query);
    // Alert security team or block execution
  }
  
  return await db.collection('users').find(query).toArray();
};

Frequently Asked Questions

How does MongoDB command injection differ from SQL injection?
MongoDB injection exploits JavaScript evaluation and operator injection rather than SQL syntax. Common vectors include $where clauses that execute JavaScript, operator injection through query parameters, and aggregation pipeline manipulation. While SQL injection often involves breaking out of string literals, MongoDB injection frequently involves injecting JavaScript functions or manipulating query operators like $ne, $gt, and $regex.
Can middleBrick detect MongoDB-specific injection vulnerabilities?
Yes, middleBrick includes MongoDB-specific scanning that tests for JavaScript injection in $where clauses, operator injection through query parameters, and aggregation pipeline manipulation. The scanner submits payloads designed to trigger MongoDB-specific error messages and unexpected behavior, then analyzes responses for indicators of vulnerability. It also examines OpenAPI specifications for MongoDB-specific risk patterns and provides remediation guidance mapped to OWASP API Security Top 10.