🚨 The $5 Million Data Breach
A startup deployed MongoDB with default settings. No authentication, no firewall, port 27017 open to the internet.
Result: Hackers found it in 2 hours. Deleted 500GB of customer data. Demanded $50K ransom. Company lost $5M in lawsuits and went bankrupt.
Prevention: Enable authentication + firewall rules. Would have taken 5 minutes to configure. ✨
⚠️ Never deploy MongoDB without security! This happens to real companies every week.
🛡️ Defense in Depth: Security Layers
MongoDB security uses multiple layers. If one fails, others protect your data.
Layer 1: Network Security
Firewall rules, VPN, IP whitelisting, private networks
Layer 2: Authentication
Verify WHO is connecting (username/password, certificates, LDAP)
Layer 3: Authorization
Control WHAT they can do (role-based access control)
Layer 4: Encryption
Encrypt data in transit (TLS/SSL) and at rest
Layer 5: Auditing
Log all access attempts and operations for compliance
🔐 Authentication: Verify Identity
Enable Authentication (First Step!)
# Step 1: Create admin user
mongosh
use admin
db.createUser({
user: "admin",
pwd: "StrongPassword123!",
roles: ["userAdminAnyDatabase", "dbAdminAnyDatabase", "readWriteAnyDatabase"]
})
# Step 2: Enable auth in mongod.conf
security:
authorization: enabled
# Step 3: Restart MongoDB
sudo systemctl restart mongod
# Step 4: Connect with authentication
mongosh -u admin -p StrongPassword123! --authenticationDatabase admin
Authentication Mechanisms
1. SCRAM (Default - Recommended)
// Salted Challenge Response Authentication Mechanism
db.createUser({
user: "appUser",
pwd: passwordPrompt(), // Secure password input
roles: ["readWrite"]
})
2. x.509 Certificate Authentication
// For internal cluster communication
mongod --tlsMode requireTLS \
--tlsCertificateKeyFile /path/to/server.pem \
--tlsCAFile /path/to/ca.pem
3. LDAP (Enterprise)
// Integrate with Active Directory
security:
authorization: enabled
ldap:
servers: "ldap.example.com"
authz:
queryTemplate: "DC=example,DC=com??sub?(uid={USER})"
🔑 Password Best Practices:
- Minimum 15 characters
- Mix uppercase, lowercase, numbers, symbols
- Never hardcode in application code
- Use environment variables or secret managers
- Rotate passwords every 90 days
👮 Authorization: Control Access
Built-in Roles
// Database User Roles
read // Read any database
readWrite // Read and write any database
// Database Admin Roles
dbAdmin // Database administration
dbOwner // Database owner (admin + readWrite)
userAdmin // Create and modify roles/users
// Cluster Admin Roles
clusterAdmin // Cluster administration
clusterManager // Manage and monitor cluster
clusterMonitor // Read-only access to monitoring
// Backup/Restore Roles
backup // Backup data
restore // Restore data
// Super User Role
root // All privileges (use sparingly!)
Create Users with Specific Roles
// Read-only user for analytics
db.createUser({
user: "analyst",
pwd: "SecurePass456!",
roles: [{ role: "read", db: "sales" }]
})
// Application user with read-write on specific DB
db.createUser({
user: "appUser",
pwd: "AppPass789!",
roles: [{ role: "readWrite", db: "production" }]
})
// DBA with admin privileges
db.createUser({
user: "dba",
pwd: "DBAPass321!",
roles: [
{ role: "dbAdminAnyDatabase", db: "admin" },
{ role: "clusterAdmin", db: "admin" }
]
})
Custom Roles (Fine-Grained Control)
// Create role that can only read specific collection
use admin
db.createRole({
role: "ordersReader",
privileges: [{
resource: { db: "sales", collection: "orders" },
actions: ["find", "listCollections", "listIndexes"]
}],
roles: []
})
// Assign to user
db.createUser({
user: "orderViewer",
pwd: "ViewPass999!",
roles: ["ordersReader"]
})
Verify User Permissions
// Show current user's roles
db.runCommand({ connectionStatus: 1 })
// List all users
db.getUsers()
// Show user privileges
db.getUser("appUser", { showPrivileges: true })
🔐 Encryption: Protect Data
1. Encryption in Transit (TLS/SSL)
# Generate certificates (production: use proper CA)
openssl req -newkey rsa:2048 -nodes -keyout mongodb.key -x509 -days 365 -out mongodb.crt
cat mongodb.key mongodb.crt > mongodb.pem
# Configure mongod.conf
net:
tls:
mode: requireTLS
certificateKeyFile: /path/to/mongodb.pem
CAFile: /path/to/ca.pem
# Connect with TLS
mongosh "mongodb://localhost:27017" \
--tls \
--tlsCertificateKeyFile /path/to/client.pem
2. Encryption at Rest (Enterprise)
# Create encryption key
openssl rand -base64 32 > mongodb-keyfile
# Configure encryption
security:
enableEncryption: true
encryptionKeyFile: /path/to/mongodb-keyfile
encryptionCipherMode: AES256-CBC
# Restart MongoDB - all data encrypted!
3. Client-Side Field Level Encryption (CSFLE)
// Encrypt sensitive fields before sending to DB
const clientEncryption = new ClientEncryption(keyVaultClient, {
keyVaultNamespace: 'encryption.__keyVault',
kmsProviders: { local: { key: masterKey } }
})
// Encrypt SSN field
const encryptedSSN = await clientEncryption.encrypt(
'123-45-6789',
{
algorithm: 'AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic',
keyId: dataKey
}
)
// Store encrypted value
await db.users.insertOne({
name: 'John Doe',
ssn: encryptedSSN // Encrypted in DB
})
💡 Encryption Tip:
TLS = encrypt network traffic, At-Rest = encrypt disk, CSFLE = encrypt specific fields. Use all three for maximum security!
🌐 Network Security
1. Bind to Private IP Only
# NEVER bind to 0.0.0.0 in production!
# mongod.conf
net:
bindIp: 127.0.0.1,10.0.1.5 # localhost + private IP
port: 27017
2. Firewall Rules
# Allow only application servers
sudo ufw allow from 10.0.1.10 to any port 27017
sudo ufw allow from 10.0.1.11 to any port 27017
sudo ufw deny 27017
# For AWS Security Groups
{
"IpProtocol": "tcp",
"FromPort": 27017,
"ToPort": 27017,
"IpRanges": [{ "CidrIp": "10.0.1.0/24" }]
}
3. VPC and Private Networks
# Best practice: Deploy in private subnet
VPC: 10.0.0.0/16
├─ Public Subnet: 10.0.1.0/24 (NAT Gateway)
└─ Private Subnet: 10.0.2.0/24 (MongoDB here!)
# MongoDB only accessible from within VPC
# No public IP, no internet access
4. Change Default Port (Security by Obscurity)
# mongod.conf
net:
port: 37017 # Not 27017 - reduces automated attacks
# Note: This is NOT a replacement for real security!
📋 Auditing & Compliance
Enable Audit Logging (Enterprise)
# mongod.conf
auditLog:
destination: file
format: JSON
path: /var/log/mongodb/audit.json
filter: '{
atype: { $in: ["authenticate", "createUser", "dropDatabase"] }
}'
# Audit events logged:
// - Authentication attempts (success/failure)
// - User creation/deletion
// - Database/collection drops
// - Role changes
// - Configuration changes
Audit Log Analysis
# Find failed login attempts
grep '"atype":"authenticate"' audit.json | grep '"result":5'
# Find user creation events
grep '"atype":"createUser"' audit.json
# Find dropped databases (disaster prevention!)
grep '"atype":"dropDatabase"' audit.json
Compliance Requirements
- GDPR: Encryption, audit logs, data deletion capabilities
- HIPAA: At-rest encryption, access controls, audit trails
- PCI DSS: Network segmentation, encryption, strong auth
- SOC 2: Monitoring, logging, incident response
⭐ Security Best Practices
- Enable Authentication - ALWAYS, even in dev environments
- Use Role-Based Access Control - Principle of least privilege
- Enable TLS/SSL - Encrypt all network traffic
- Encrypt at Rest - Protect data on disk (Enterprise feature)
- Bind to Private IPs - Never expose to internet
- Configure Firewall - Whitelist only trusted IPs
- Regular Updates - Apply security patches promptly
- Strong Passwords - 15+ chars, rotated every 90 days
- Enable Audit Logging - Track all security events
- Disable Unused Features - Reduce attack surface
- Backup Encryption Keys - Store securely, separate from data
- Monitor Security Logs - Alert on suspicious activity
- Use Secrets Manager - Don't hardcode credentials
- Regular Security Audits - Penetration testing annually
- Incident Response Plan - Know what to do when breached
💼 Interview Questions & Answers
Defense in Depth - 5 Layers:
- Network Security: Firewalls, VPC, IP whitelisting
- Authentication: Verify WHO (SCRAM, x.509, LDAP)
- Authorization: Control WHAT (RBAC, roles)
- Encryption: TLS (transit) + at-rest + CSFLE
- Auditing: Log access and operations
Key principle: If one layer fails, others still protect data
Authentication: Verifies WHO you are (identity)
- Username + password
- Certificates (x.509)
- LDAP integration
- Question: "Are you really Alice?"
Authorization: Controls WHAT you can do (permissions)
- Role-based access control
- Read/write permissions
- Database/collection access
- Question: "Can Alice delete this database?"
Example: You authenticate as "admin" → Authorization allows you to create users
Step-by-step process:
// 1. Create admin user (before enabling auth)
use admin
db.createUser({
user: "admin",
pwd: "StrongPassword",
roles: ["userAdminAnyDatabase"]
})
// 2. Enable auth in mongod.conf
security:
authorization: enabled
// 3. Restart MongoDB
sudo systemctl restart mongod
// 4. Connect with credentials
mongosh -u admin -p StrongPassword --authenticationDatabase admin
⚠️ Important: Create admin user BEFORE enabling auth, or you'll lock yourself out!
TLS/SSL (Encryption in Transit):
- Encrypts data traveling over network
- Protects against network sniffing/eavesdropping
- Client ↔ MongoDB communication encrypted
- Required: Certificate files (.pem)
Encryption at Rest:
- Encrypts data stored on disk
- Protects against disk theft/unauthorized access
- Database files encrypted
- Required: Encryption key file (Enterprise only)
Best practice: Use BOTH - TLS for network + at-rest for storage
Top 10 Security Mistakes:
- No Authentication Enabled - Anyone can connect!
- Binding to 0.0.0.0 - Exposed to internet
- Weak Passwords - "admin" / "password123"
- No Firewall Rules - Port 27017 open to world
- No TLS/SSL - Credentials sent in plaintext
- Using 'root' Role - Too much privilege
- Hardcoded Credentials - In source code/config
- No Audit Logging - Can't detect breaches
- Outdated Version - Missing security patches
- No Monitoring - Don't notice attacks
Result: Most breaches happen because of #1-4 combined!
RBAC Implementation Strategy:
// 1. Identify user types and permissions needed
// - Developers: read/write on dev DB
// - Analysts: read-only on production
// - DBAs: admin on all databases
// 2. Create users with appropriate roles
// Developer
db.createUser({
user: "dev1",
pwd: "DevPass",
roles: [{ role: "readWrite", db: "dev_db" }]
})
// Analyst
db.createUser({
user: "analyst1",
pwd: "AnalystPass",
roles: [{ role: "read", db: "production_db" }]
})
// DBA
db.createUser({
user: "dba1",
pwd: "DBAPass",
roles: ["dbAdminAnyDatabase", "clusterAdmin"]
})
// 3. Create custom roles for fine-grained control
db.createRole({
role: "customerDataReader",
privileges: [{
resource: { db: "crm", collection: "customers" },
actions: ["find", "listIndexes"]
}],
roles: []
})
Best practice: Principle of least privilege - give only minimum required permissions