The Sherlock provides hands-on experience involving forensics and Incident response, including the MongoBleed Vulnerability. MongoBleed is a heap-memory disclosure vulnerability in the MongoDB Server. It arises in the server’s zlib compression handling logic, specifically in how it parses compressed network messages. By sending specially crafted messages with inconsistent length fields, an attacker can cause MongoDB to return uninitialized heap memory, potentially exposing sensitive in-memory data, without any authentication.
A single external host hammered an internet-reachable MongoDB server with tens of thousands of short-lived connections, the signature of a heap-disclosure exploit leaking memory a few bytes at a time. Shortly afterwards the same host logged in over SSH as a local service account, first with a throwaway login that closed almost immediately and then with a hands-on session. From that shell the attacker piped linPEAS from GitHub straight into sh to hunt for privilege escalation paths, then served the database directory over a Python web server, most likely for exfiltration. How the SSH credential was obtained is not shown in the logs; the leak is the probable source but that link is inferred.
mongod.log → JSON lines, read with grep and Python. Holds the build info and every connection eventauth.log → read with grep. sshd authentication and session lines/home/mongoadmin/.bash_history → plain text, read directlyTimestamp note: Answers need
YYYY-MM-DD hh:mm:ss.mongod.logcarries milliseconds, so truncate them before submitting.
The scenario describes a zlib length-field flaw that returns uninitialised heap memory without authentication, under the name MongoBleed. That name maps to a single CVE in the Horizon3 research page and the Debian security tracker, which both carry the ID.
mongod logs a Build Info entry at startup, and its buildInfo.version field is the installed version. Compare it to the fixed release in the advisories from Q1: the installed build sits one patch below the fix.
grep -m1 'Build Info' mongod.log | grep -oE '"version":"[0-9.]+"'
Count the remote address on every Connection accepted event. One address owns all of them, tens of thousands of lines with no other source mixed in, so there is no baseline of legitimate clients to separate it from.
grep 'Connection accepted' mongod.log | grep -oE '"remote":"[0-9.]+' | sort | uniq -c | sort -rn
From Q3 the attacker IP is the pivot. The earliest Connection accepted event from it marks the start of the flood, and the timestamp is in UTC in the log. Drop the milliseconds for the answer.
grep 'Connection accepted' mongod.log | grep 65.0.76.43 | head -1
Count the attacker’s events by message type. Every connection produces a Connection accepted event and a matching Connection ended event, both with the attacker IP, so the log holds twice as many events as connections. The connections are indistinguishable from each other: each lasts between 0 and 13 ms and carries no client metadata, so there is no field that splits one from another. The expected total comes from counting both event types together, so treat it as a counting convention and not something the log proves on its own.
grep 65.0.76.43 mongod.log | grep -cE 'Connection (accepted|ended)'
Gotcha: Counting only the
Connection acceptedevents gives the natural-looking figure of half the answer, and the platform rejects it. Count accepted plus ended events.
Switch to auth.log and search for the attacker IP. There are two accepted keyboard-interactive logins for the same local account. The earlier one closes within a second, which looks like an automated credential check. The later one belongs to sshd[39962] and runs for several minutes, so that is the hands-on session. Both land after the connection flood, which fits the idea that leaked memory exposed a credential, but nothing in the logs shows which secret was used, so that link stays inferred.
grep 'Accepted' auth.log | grep 65.0.76.43
Gotcha: The first accepted login is the short one. Check how long each session lasts before choosing a time.
The session account’s home directory is in the evidence, and its .bash_history records the commands typed during the Q6 session. One line downloads the linPEAS enumeration script from the PEASS-ng GitHub release and pipes it into sh, so the script runs in memory and never touches disk. The answer is the whole line, flags included.
cat /home/mongoadmin/.bash_history
Later in the same .bash_history, the attacker changes into a directory and then starts python3 -m http.server on port 6969 from it. The web server’s document root is whatever the working directory was, so the directory they cd into just before is the one being shared.
grep -B2 'http.server' /home/mongoadmin/.bash_history
| Phase | Action |
|---|---|
| Initial Access | Connection flood from one external IP against MongoDB 8.0.16, exploiting the zlib heap disclosure |
| Credential Access | Credential likely recovered from leaked heap memory (inferred, not shown in the logs) |
| Initial Access | Throwaway SSH login as mongoadmin that closes within a second |
| Initial Access | Hands-on SSH login as mongoadmin, session lasts until 05:48:28 |
| Privilege Escalation | linPEAS fetched with curl and piped into sh |
| Exfiltration | Python web server started on port 6969 from the MongoDB data directory |
| Type | Value |
|---|---|
| IP | 65.0.76[.]43 |
| Account used | mongoadmin |
| URL | hxxps[://]github[.]com/carlospolop/PEASS-ng/releases/latest/download/linpeas.sh |
| Listener | python3 -m http.server 6969 |
| Targeted path | /var/lib/mongodb |
| Technique | ID | Description |
|---|---|---|
| Exploit Public-Facing Application | T1190 | MongoBleed against MongoDB 8.0.16 |
| Unsecured Credentials: Credentials In Files | T1552.001 | Leaked heap memory probably exposed the credential (inferred) |
| Valid Accounts: Local Accounts | T1078.003 | mongoadmin login over SSH |
| Remote Services: SSH | T1021.004 | Interactive session from the attacker IP |
| Ingress Tool Transfer | T1105 | linPEAS fetched with curl from GitHub |
| Data from Local System | T1005 | Interest in the MongoDB data directory |
| Exfiltration Over Alternative Protocol | T1048 | Python HTTP server on the data directory |
An unpatched, reachable mongod is a pre-authentication leak. The server ran 8.0.16, one patch below the fix, and accepted connections from the internet. Patching to 8.0.17 and binding the listener to internal addresses would have removed the attack surface.
A single source with tens of thousands of short connections is the exploit’s signature. Each connection lasted milliseconds and carried no client metadata. An alert on connection rate per source IP in mongod.log would have fired well before the SSH login.
Treat a memory-disclosure bug as a credential exposure. Anything in the server’s heap could have leaked, and a valid SSH login arrived minutes after the flood. Rotate secrets and review logins from the same source after any such exploit.
Command auditing catches the post-exploitation steps. curl ... | sh and a Python HTTP server on a data directory both sit plainly in shell history. Auditd or EDR rules on those patterns, plus an alert on unexpected listeners, would have caught the privilege-escalation attempt and the exfiltration staging.
A pre-authentication memory leak in an unpatched MongoDB turned into an SSH foothold and an exfiltration listener on the data directory within about twenty minutes. The exploit left a loud connection flood in
mongod.log; nobody was watching for it.