# MongoDB Service Discovery and Access Validation

- **URL:** https://hackindex.io/services/mongodb/enumeration/mongodb-service-discovery-and-access-validation
- **Path:** MongoDB > Enumeration
- **Up:** [Enumeration](https://hackindex.io/services/mongodb/enumeration.md)
- **Published:** 2025-12-29
- **Updated:** 2026-03-28

Service discovery confirms that a port running MongoDB is actually MongoDB, retrieves the version, and establishes whether authentication is enforced. A version without authentication is an immediate finding: move to [unauthenticated access](https://hackindex.io/services/mongodb/vulnerability-discovery/mongodb-unauthenticated-access) to confirm the scope of exposure. Default ports to check:

- 27017: primary MongoDB instance
- 27018: replica set member
- 27019: config server in sharded clusters (often less secured)

If the port shows as filtered, check whether the service is running behind a host-based firewall that allows only specific source addresses. MongoDB does not run on UDP, so skip UDP sweeps.

## MongoDB service discovery with nmap

Run nmap with version detection and the MongoDB-specific NSE scripts to get version, build info, and database list without touching the shell. The `mongodb-info` script connects to the service without credentials and reads server metadata directly. Look for the `ok = 1` field: it confirms the server accepted the status query. If the script returns no data despite the port being open, the instance may require TLS or bind to a specific interface. The `connections.current` value indicates active connections and can hint at a live application backend.

```bash
nmap -sV -p 27017 --script mongodb-info $TARGET_IP
# 27017/tcp open  mongodb  MongoDB 4.4.18
# | mongodb-info:
# |   MongoDB Build info
# |     version = 4.4.18
# |     javascriptEngine = mozjs
# |   Server status
# |     connections
# |       current = 2
# |       available = 838858
# |     uptime = 3742
# |_    ok = 1
```

```bash
nmap -sV -p 27017 --script mongodb-databases $TARGET_IP
# | mongodb-databases:
# |   databases
# |     0  name = admin  sizeOnDisk = 102400  empty = false
# |     1  name = appdb  sizeOnDisk = 81920   empty = false
# |     2  name = local  sizeOnDisk = 40960   empty = false
# |_  totalSize = 225280
```

The mongodb-databases script returning database names without authentication is a confirmed unauthenticated exposure. The `admin` database controls user accounts and role assignments. If you can read it unauthenticated, you can likely list and query other databases too. The `local` database stores internal replication state and is present on every instance. Application databases such as `appdb` are where live user data sits. Note the version from mongodb-info and cross-reference it against the [MongoBleed affected version table](https://hackindex.io/services/mongodb/exploitation/mongodb-cve-2025-14847-mongobleed) immediately. Versions in the 4.4.x series below 4.4.20 have the broadest CVE coverage.

## Run Both Scripts Together

Running both scripts in a single nmap invocation saves a round trip and produces combined output. Compare the version from `mongodb-info` and the database list from `mongodb-databases` side by side. If databases appear without any authentication challenge, that confirms the scope immediately. You can skip the mongosh validation step below if you prefer a non-interactive workflow.

```bash
nmap -sV -p 27017 --script mongodb-info,mongodb-databases $TARGET_IP
```

## Validate Access with mongosh

Connect interactively to confirm whether authentication is enforced. A successful connection without credentials confirms unauthenticated access. If authentication is enforced, mongosh prints an error before dropping to a prompt. The connection attempt still reveals the server version in the banner even when it fails. The shell lands in the `test` database by default, which appears in the prompt. That database often exists even on production instances because MongoDB creates it on first use.

```bash
mongosh $TARGET_IP:27017
# Current Mongosh Log ID: abc123
# Connecting to: mongodb://10.10.10.50:27017/
# Using MongoDB: 4.4.18
# Using Mongosh: 2.1.0
#
# test>
```

A prompt without an authentication challenge confirms unauthenticated access. The default landing database is `test`. If you see an error referencing authentication, the instance requires credentials but you still captured the version from the connection attempt. Run a quick check to confirm what identity the connection has:

```bash
mongosh $TARGET_IP:27017 --quiet --eval 'printjson(db.runCommand({connectionStatus: 1}))'
# {
#   authInfo: {
#     authenticatedUsers: [],
#     authenticatedUserRoles: []
#   },
#   ok: 1
# }
```

Empty `authenticatedUsers` and `authenticatedUserRoles` confirms the connection is unauthenticated. If auth is enabled, this command returns an error before producing output. When roles appear here unexpectedly, your environment or connection string passed credentials you did not intend. Check your mongosh invocation for implicit username or password arguments. Move to [server configuration enumeration](https://hackindex.io/services/mongodb/enumeration/mongodb-server-configuration-and-environment-enumeration) to understand why auth is absent, and to [unauthenticated access testing](https://hackindex.io/services/mongodb/vulnerability-discovery/mongodb-unauthenticated-access) to establish the full scope.

## Non-Interactive Version Check

Quick one-liner for scripted checks across multiple hosts. The loop reads a target list and prints the version or `no access`. A `no access` result covers two distinct cases: authentication rejected the anonymous connection, or the port is reachable but the service refused unauthenticated commands. To distinguish them, check whether mongosh returns an authentication error or times out. An auth error means the service is running and protected. A timeout or connection refused means a network filter or service binding is blocking you. After the sweep, prioritize any host that returns a version string.

```bash
mongosh --host $TARGET_IP --port 27017 --quiet --eval 'db.version()' 2>/dev/null
# 4.4.18
```

```bash
for ip in $(cat targets.txt); do echo -n "$ip: "; mongosh --host $ip --port 27017 --quiet --eval 'db.version()' 2>/dev/null || echo 'no access'; done
# 10.10.10.50: 4.4.18
# 10.10.10.51: no access
# 10.10.10.52: 6.0.5
```

If the NSE scripts return no data on an open port, TLS is likely enabled. Nmap's MongoDB scripts do not handle TLS by default. Switch to mongosh with the `--tls` flag and confirm whether the certificate is self-signed or CA-signed. Some instances bind only to localhost and expose the service through an SSH tunnel or internal proxy. In that case, all external probes stall even though the port appears open. Look for SSH port forwarding rules or internal service meshes if enumeration stalls after confirming the port. On replica sets, probe all three ports: the primary on 27017, the replica members on 27018, and the config server on 27019. Authentication configuration sometimes differs between nodes in the same cluster.

## References

- [nmap: mongodb-info NSE](https://nmap.org/nsedoc/scripts/mongodb-info.html) - Version and build info retrieval without authentication
- [nmap: mongodb-databases NSE](https://nmap.org/nsedoc/scripts/mongodb-databases.html) - Unauthenticated database list enumeration
- [mongosh](https://www.mongodb.com/try/download/shell) - Official MongoDB shell download
