27017-27018-mongodb.md (10858B)
1 --- 2 title: "27017,27018 - Pentesting MongoDB" 3 section: "Network Services" 4 sectionSlug: "network-services-pentesting" 5 sourcePath: "src/network-services-pentesting/27017-27018-mongodb.md" 6 sourceUrl: "https://github.com/HackTricks-wiki/hacktricks/blob/188de82beb54e70956b2952367a0af91d26758b8/src/network-services-pentesting/27017-27018-mongodb.md" 7 sha: "188de82beb54e70956b2952367a0af91d26758b8" 8 isIndex: false 9 modified: true 10 license: "CC-BY-NC-4.0" 11 --- 12 13 # 27017,27018 - Pentesting MongoDB 14 15 ## Basic Information 16 17 **MongoDB** is an open-source, document-oriented database. A normal `mongod` or `mongos` listener defaults to TCP **27017**, a shard server defaults to **27018**, and a config server defaults to **27019**.<sup>[[7]](#references)</sup> 18 19 ```text 20 PORT STATE SERVICE VERSION 21 27017/tcp open mongodb MongoDB 2.6.9 2.6.9 22 ``` 23 24 ## Enumeration 25 26 ### Manual 27 28 ```python 29 from pymongo import MongoClient 30 client = MongoClient(host, port, username=username, password=password) 31 client.server_info() #Basic info 32 #If you have admin access you can obtain more info 33 admin = client.admin 34 admin_info = admin.command("serverStatus") 35 cursor = client.list_databases() 36 for db in cursor: 37 print(db) 38 print(client[db["name"]].list_collection_names()) 39 #If admin access, you could dump the database also 40 ``` 41 42 **Some MongoDB commands:** 43 44 ```bash 45 show dbs 46 use <db> 47 show collections 48 db.<collection>.find() #Dump the collection 49 db.<collection>.count() #Number of records of the collection 50 db.current.find({"username":"admin"}) #Find in current db the username admin 51 ``` 52 53 ### Automatic 54 55 ```bash 56 nmap -sV --script "mongo* and default" -p 27017 <IP> #By default all the nmap mongo enumerate scripts are used 57 ``` 58 59 ### Shodan 60 61 - All mongodb: `"mongodb server information"` 62 - Search for full open mongodb servers: `"mongodb server information" -"partially enabled"` 63 - Only partially enable auth: `"mongodb server information" "partially enabled"` 64 65 ## Login 66 67 Self-managed MongoDB defaults to `security.authorization: disabled`, but it also defaults to binding only to localhost. An externally reachable listener without authorization is therefore a dangerous configuration, not a safe Internet-facing default.<sup>[[7]](#references)</sup> The `admin` database is the usual authentication database for administrative users. 68 69 ```bash 70 mongo <HOST> 71 mongo <HOST>:<PORT> 72 mongo <HOST>:<PORT>/<DB> 73 mongo <database> -u <username> -p '<password>' 74 ``` 75 76 The nmap script: _**mongodb-brute**_ will check if creds are needed. 77 78 ```bash 79 nmap -n -sV --script mongodb-brute -p 27017 <ip> 80 ``` 81 82 ### [**Brute force**](https://github.com/HackTricks-wiki/hacktricks/blob/188de82beb54e70956b2952367a0af91d26758b8/src/generic-hacking/brute-force.md#mongo) 83 84 Look inside _/opt/bitnami/mongodb/mongodb.conf_ to know if credentials are needed: 85 86 ```bash 87 grep "noauth.*true" /opt/bitnami/mongodb/mongodb.conf | grep -v "^#" #Not needed 88 grep "auth.*true" /opt/bitnami/mongodb/mongodb.conf | grep -v "^#\|noauth" #Not needed 89 ``` 90 91 ## Mongo Objectid Predict 92 93 Example [from here](https://techkranti.com/idor-through-mongodb-object-ids-prediction/).<sup>[[1]](#references)</sup> 94 95 MongoDB ObjectIds are **12-byte values**, conventionally displayed as 24 hexadecimal characters:<sup>[[8]](#references)</sup> 96 97  98 99 For example, here’s how we can dissect an actual Object ID returned by an application: 5f2459ac9fa6dc2500314019 100 101 1. `5f2459ac`: a 4-byte Unix timestamp (`1596217772`, Friday, 31 July 2020 17:49:32 UTC) 102 2. `9fa6dc2500`: a 5-byte random value generated once per client-side process 103 3. `314019`: a 3-byte counter initialized to a random value 104 105 Older ObjectId layouts exposed separate machine and process identifiers; the current specification replaced those fields with one per-process random value. The timestamp changes once per second and the counter increments within a process, so IDs observed from the same generator in a narrow time window can still be partially predictable. This is not universal: drivers generate ObjectIds client-side, different processes use different random values, and applications may choose unrelated `_id` values.<sup>[[1]](#references)[[8]](#references)</sup> 106 107 Given an observed ObjectId, `mongo-objectid-predict` generates nearby candidates for authorization testing.<sup>[[9]](#references)</sup> Treat this as a targeted IDOR test rather than a general ObjectId breaker: it is most effective when the target IDs share the timestamp, process-random component, and adjacent counter values. 108 109 The upstream command exposes `--counter-diff` (how many adjacent counter values to explore), `--per-counter` (how many timestamp offsets to try for each counter), and `--backward` (generate earlier rather than later candidates). Its defaults are `20` and `60`, producing roughly a thousand candidates; expand them only after establishing that a smaller authorized sample shares the generator component.<sup>[[9]](#references)</sup> 110 111 ```bash 112 ./mongo-objectid-predict 5ae9b90a2c144b9def01ec37 113 ./mongo-objectid-predict 5ae9b90a2c144b9def01ec37 --counter-diff 50 --per-counter 120 114 ./mongo-objectid-predict 5ae9b90a2c144b9def01ec37 --backward 115 ``` 116 117 The repository currently contains Python 2-era code and describes the older machine-ID/process-ID terminology. Review or port it before use, and do not mistake generated candidates for evidence that a resource exists or that access is authorized. 118 119 ## Post 120 121 With authorized root access to a self-managed host, you can audit the effective configuration and, in a disposable recovery lab, start a local-only instance with authorization disabled. Current YAML configuration uses `security.authorization: disabled`; legacy `noauth = true` examples apply to old configuration formats. Do not expose that recovery listener beyond loopback.<sup>[[7]](#references)</sup> 122 123 ## MongoBleed zlib Memory Disclosure (CVE-2025-14847) 124 125 A widespread unauthenticated memory disclosure ("MongoBleed") impacts MongoDB 3.6–8.2 when the **zlib network compressor is enabled**. The `OP_COMPRESSED` header trusts an attacker-supplied `uncompressedSize`, so the server allocates a buffer of that size and copies it back into responses even though only a much smaller compressed payload was provided. The extra bytes are **uninitialized heap data** from other connections, `/proc`, or the WiredTiger cache. Attackers then omit the expected **BSON `\x00` terminator** so MongoDB’s parser keeps scanning that oversized buffer until it finds a terminator, and the error response echoes both the malicious document and the scanned heap bytes **pre-auth** on TCP/27017.<sup>[[2]](#references)</sup> 126 127 ### Exposure requirements & quick checks 128 129 - Server version must be within the vulnerable ranges (3.6, 4.0, 4.2, 4.4.0–4.4.29, 5.0.0–5.0.31, 6.0.0–6.0.26, 7.0.0–7.0.27, 8.0.0–8.0.16, 8.2.0–8.2.2).<sup>[[6]](#references)</sup> 130 - `net.compression.compressors` or `networkMessageCompressors` must include `zlib` (default on many builds). Check it from the shell with: 131 132 ```javascript 133 db.adminCommand({getParameter: 1, networkMessageCompressors: 1}) 134 ``` 135 136 - The attacker only needs network access to the MongoDB port. No authentication is necessary.<sup>[[3]](#references)[[4]](#references)</sup> 137 138 ### Exploitation & harvesting workflow 139 140 1. Initiate the wire-protocol handshake advertising `compressors:["zlib"]` so the session uses zlib. 141 2. Send `OP_COMPRESSED` frames whose declared `uncompressedSize` is far larger than the real decompressed payload to force **oversized heap allocation full of old data**. 142 3. Craft the embedded BSON **without a final `\x00`** so the parser walks past attacker-controlled data into the oversized buffer while looking for a terminator. 143 4. MongoDB emits an error that includes the original message plus whatever heap bytes were scanned, leaking memory. Repeat with varying lengths/offsets to aggregate secrets (creds/API keys/session tokens), WiredTiger stats, and `/proc` artifacts.<sup>[[2]](#references)</sup> 144 145 The public PoC automates the probing offsets and carving of the returned fragments:<sup>[[5]](#references)</sup> 146 147 ```bash 148 python3 mongobleed.py --host <target> --max-offset 50000 --output leaks.bin 149 ``` 150 151 ### Detection noise signal (high-rate connections) 152 153 The attack usually generates many short-lived requests. Watch for spikes of inbound connections to `mongod`/`mongod.exe`. Example XQL hunt (>500 connections/min per remote IP, excluding RFC1918/loopback/link-local/mcast/broadcast/reserved ranges by default):<sup>[[2]](#references)</sup> 154 155 <details> 156 <summary>Cortex XQL high-velocity Mongo connections</summary> 157 158 ```sql 159 // High-velocity inbound connections to mongod/mongod.exe (possible MongoBleed probing) 160 161 dataset = xdr_data 162 | filter event_type = ENUM.NETWORK 163 | filter lowercase(actor_process_image_name) in ("mongod", "mongod.exe") 164 | filter action_network_is_server = true 165 | filter action_remote_ip not in (null, "") 166 | filter incidr(action_remote_ip, "10.0.0.0/8") != true and 167 incidr(action_remote_ip, "192.168.0.0/16") != true and 168 incidr(action_remote_ip, "172.16.0.0/12") != true and 169 incidr(action_remote_ip, "127.0.0.0/8") != true and 170 incidr(action_remote_ip, "169.254.0.0/16") != true and 171 incidr(action_remote_ip, "224.0.0.0/4") != true and 172 incidr(action_remote_ip, "255.255.255.255/32") != true and 173 incidr(action_remote_ip, "198.18.0.0/15") != true 174 | filter action_network_session_duration <= 5000 175 | bin _time span = 1m 176 | comp count(_time) as Counter by agent_hostname, action_remote_ip, _time 177 | filter Counter >= 500 178 ``` 179 180 </details> 181 182 183 ## References 184 185 - [1] [IDOR through MongoDB Object IDs prediction](https://techkranti.com/idor-through-mongodb-object-ids-prediction/) 186 - [2] [Unit 42 – Threat Brief: MongoDB Vulnerability (CVE-2025-14847)](https://unit42.paloaltonetworks.com/mongobleed-cve-2025-14847/) 187 - [3] [Tenable – CVE-2025-14847 (MongoBleed): MongoDB Memory Leak Vulnerability Exploited in the Wild](https://www.tenable.com/blog/cve-2025-14847-mongobleed-mongodb-memory-leak-vulnerability-exploited-in-the-wild) 188 - [4] [MongoDB Security Advisory SERVER-115508](https://jira.mongodb.org/browse/SERVER-115508) 189 - [5] [MongoBleed PoC (joe-desimone/mongobleed)](https://github.com/joe-desimone/mongobleed) 190 - [6] [Censys – MongoBleed Advisory](https://censys.com/advisory/cve-2025-14847) 191 - [7] [MongoDB Manual - Self-Managed Configuration File Options](https://www.mongodb.com/docs/manual/reference/configuration-options/) 192 - [8] [MongoDB Manual - ObjectId BSON type](https://www.mongodb.com/docs/manual/reference/bson-types/#objectid) 193 - [9] [andresriancho/mongo-objectid-predict](https://github.com/andresriancho/mongo-objectid-predict) 194 195 ---