Insufficient Logging in Mongodb
How Insufficient Logging Manifests in MongoDB
Insufficient logging in MongoDB typically appears when administrators rely on the default mongod log level, which only records startup/shutdown events and basic errors. Critical operations such as authentication failures, administrative commands (e.g., dropDatabase, cloneCollection), and data‑access patterns (find, insert, update, delete) are not written to the audit trail unless explicitly configured. This gap enables several attack patterns:
- Stealthy data exfiltration: An attacker who gains read access can run repeated
findqueries against collections. Without audit logging, each query leaves no trace, making it impossible to detect unusual volume or anomalous filter patterns. - Privilege escalation via server‑side JavaScript: MongoDB permits JavaScript execution in commands like
mapReduce,$where, andgroup. If an attacker injects malicious JS (e.g., to read the system keyfile or to spawn a reverse shell), the operation succeeds without leaving an audit entry unless JavaScript execution is explicitly logged. - Credential brute‑force: Repeated failed authentication attempts are only logged at the default level if the connection is rejected at the network layer. When authentication is performed via the wire protocol, each failed
saslStartorauthenticatecommand may be omitted from logs, allowing an attacker to guess passwords undetected. - Covert configuration changes: Commands that modify replication settings, sharding keys, or enable/disable authentication (
setParameter,replSetReconfig) are invisible without audit logging, facilitating persistence mechanisms.
These patterns map to the OWASP API Security Top 10 category API9:2019 – Improper Assets Management (the lack of visibility into what assets are being accessed) and to the broader Logging and Monitoring Failures risk identified in the OWASP Logging and Monitoring Cheat Sheet.
MongoDB‑Specific Detection
Detecting insufficient logging starts with confirming whether audit logging or the database profiler is enabled. Because middleBrick performs unauthenticated, black‑box scans of API endpoints, it can indirectly reveal logging gaps by:
- Identifying exposed MongoDB‑adjacent services (e.g., MongoDB Express, custom admin APIs) that return detailed error stacks or verbose operation results without requiring authentication. Such verbosity often correlates with missing server‑side audit trails, as developers rely on client‑side logging instead.
- Checking for the presence of the
WWW‑Authenticateheader on MongoDB‑compatible HTTP interfaces. When authentication is missing or misconfigured, middleBrick flags the endpoint; the same misconfiguration frequently coincides with disabled audit logging. - Scanning for common misconfigurations that suppress logging, such as mongod started with
--quietor log verbosity set to0. middleBrick’s fingerprinting can infer these flags from banners or version strings returned by unauthenticated endpoints.
When a scan reports a finding like "Missing audit log configuration" or "Verbose error responses without authentication", the remediation guidance points to enabling MongoDB’s native auditing features. For example, a middleBrick report may include:
Finding: Audit logging not enabled
Severity: Medium
Remediation: Enable MongoDB audit logging (see mongod auditLog settings) and configure the database profiler to capture write operations.
By correlating the scan’s unauthenticated observations with MongoDB‑specific logging controls, teams can quickly verify whether the logging gap exists in production.
MongoDB‑Specific Remediation
Addressing insufficient logging requires activating MongoDB’s built‑in auditing and profiling mechanisms, then ensuring application code captures relevant events. Below are concrete, syntactically correct examples using the official MongoDB Node.js driver (version 6.x) and mongod configuration.
1. Enable audit logging via mongod configuration
Create or edit /etc/mongod.conf (or the equivalent config file) and add an auditLog section:
systemLog:
destination: file
path: /var/log/mongodb/mongod.log
logAppend: true
auditLog:
destination: file
format: JSON
path: /var/log/mongodb/auditLog.json
filter: &
atype: {
$in: [
"authCheck", # authentication attempts
"createCollection",
"dropDatabase",
"dropCollection",
"insert",
"update",
"delete",
"find",
"command" # captures admin commands like mapReduce, $where
]
}
# Optional: set log verbosity for more detail (0‑5)
systemLog:
verbosity: 2
After saving, restart mongod: sudo systemctl restart mongod. All events matching the filter are written as JSON lines to /var/log/mongodb/auditLog.json, suitable for ingestion by SIEM tools.
2. Activate the database profiler for write‑operation visibility
The profiler logs every database command to the system.profile collection. Enable it at level 2 (profile all operations):
use admin
db.setProfilingLevel(2)
To limit impact, configure a slow‑ms threshold and filter to only writes:
db.setProfilingLevel(1, { slowMs: 100 }) # profile only operations slower than 100ms
# Then manually enable write‑operation profiling via a filter:
use profiling
db.createCollection("system.profile", { capped: true, size: 10000000 })
db.runCommand({ profile: 0, filter: { op: { $in: ["insert", "update", "delete"] } } })
Review the profile with:
use profiling
db.system.profile.find().sort({ ts: -1 }).limit(20)
3. Instrument the Node.js driver to log commands and errors
Even with server‑side audit logging, applications should capture client‑side context (e.g., user‑id, request‑id). The driver emits commandStarted, commandSucceeded, and commandFailed events:
const { MongoClient } = require('mongodb');
const { createLogger, format, transports } = require('winston');
const logger = createLogger({
level: 'info',
format: format.combine(format.timestamp(), format.json()),
transports: [new transports.File({ filename: '/var/log/mongodb-app.log' })]
});
const client = new MongoClient('mongodb://localhost:27017', {
useUnifiedTopology: true,
monitorCommands: true // enables command monitoring
});
client.on('commandStarted', (event) => {
logger.info({ event: 'commandStarted', command: event.command, ns: event.namespace, requestId: event.requestId });
});
client.on('commandSucceeded', (event) => {
logger.info({ event: 'commandSucceeded', durationMicros: event.durationMicros, reply: event.reply, requestId: event.requestId });
});
client.on('commandFailed', (event) => {
logger.error({ event: 'commandFailed', durationMicros: event.durationMicros, failure: event.failure, requestId: event.requestId });
});
// Example operation
async function run() {
await client.connect();
const db = client.db('test');
await db.collection('users').insertOne({ name: 'alice' });
await client.close();
}
run().catch(console.error);
This setup ensures that every command, its outcome, and timing are recorded in the application log, complementing server‑side audit trails.
4. Validate logging is working
After applying the above changes, generate a test event and confirm its presence:
- Server audit:
grep 'authCheck' /var/log/mongodb/auditLog.json - Profiler:
db.system.profile.find({ op: "insert" }).sort({ ts: -1 }).limit(1) - App log:
grep 'commandSucceeded' /var/log/mongodb-app.log
If entries appear, logging is sufficient; otherwise, revisit the filter expressions and verbosity levels.
By enabling MongoDB’s native audit log, configuring the profiler, and adding client‑side command monitoring, you eliminate the blind spots that attackers exploit for stealthy data access, privilege escalation, and credential brute‑force. These controls directly address the finding categories that middleBrick reports under "Insufficient Logging" and give you the forensic data needed to detect and investigate suspicious activity.