
Detection Script for MongoBleed Exploitation
Offline MongoDB Analysis Tool for CVE-2025-14847 (MongoBleed)
A standalone Linux command-line tool that analyzes MongoDB data to identify likely exploitation of CVE-2025-14847 using multiple detection modules.
MongoBleed (CVE-2025-14847) is a memory disclosure vulnerability in MongoDB's zlib decompression that allows attackers to extract sensitive data—credentials, session tokens, PII—directly from server memory without authentication.
This tool helps incident responders detect exploitation attempts using multiple evidence sources:
Analyzes MongoDB JSON logs to detect exploitation patterns:
| Event ID | Type | Description |
|---|---|---|
| 22943 | Connection Accepted | Logged when a client connects |
| 51800 | Client Metadata | Logged when a client sends driver/application info |
| 22944 | Connection Closed | Logged when a client disconnects |
Key insight: Legitimate MongoDB drivers always send client metadata. The MongoBleed exploit connects, extracts memory, and disconnects—but never sends metadata.
Analyzes snapshots of db.serverStatus().asserts to detect unusual patterns in asserts.user counters:
asserts.user to other assertion types. If user asserts are disproportionately high (ratio ≥250x) or all other types are zero, flags as suspicious (MEDIUM confidence)Note: Cumulative counters can produce false positives. Use in combination with FTDC (Module B2) for best results.
Analyzes MongoDB's Full-Time Diagnostic Data Capture (FTDC) files to detect time-localized spikes in assertion counters. FTDC samples serverStatus periodically, enabling precise timing of potential attacks.
jq - JSON processorawk (gawk recommended)gzip - For compressed log supportpymongo - For FTDC file decodingssh, scp commands)# Shell script dependencies
# Debian/Ubuntu
apt-get install jq gawk gzip
# RHEL/CentOS/Fedora
dnf install jq gawk gzip
# macOS
brew install jq gawk
# Python dependencies (for FTDC decoding)
pip install -r requirements.txt
# Clone the repository
git clone https://github.com/your-org/mongobleed-detector.git
cd mongobleed-detector
# Make scripts executable
chmod +x mongobleed-detector.sh
chmod +x mongobleed-remote.py
chmod +x ftdc-decode.py
# Install Python dependencies (optional, for FTDC support)
pip install -r requirements.txt
Analyze data that has been manually collected from MongoDB hosts.
Automatically collect data from multiple hosts via SSH, then analyze locally.
Collect data from your MongoDB hosts and organize it into this structure:
./collected-data/
├── logs/ # MongoDB JSON logs
│ ├── mongod.log
│ ├── mongod.log.1
│ └── mongod.log.2.gz
├── assert-counts/ # serverStatus().asserts snapshots
│ ├── asserts-2025-01-01.json
│ └── asserts-2025-01-02.json
└── ftdc-files/ # FTDC diagnostic.data contents
├── metrics.2025-01-02T10-00-00Z-00000
└── metrics.interim
# Copy from remote host
scp user@mongohost:/var/log/mongodb/mongod.log* ./collected-data/logs/
Run this command on the MongoDB host (requires mongosh access):
mongosh --quiet --eval 'JSON.stringify({
timestamp: new Date().toISOString(),
hostname: db.hostInfo().system.hostname,
asserts: db.serverStatus().asserts,
uptime: db.serverStatus().uptime
})' > asserts-$(date +%Y%m%d-%H%M%S).json
Copy the resulting JSON file to ./collected-data/assert-counts/.
Tip: Run this command multiple times (e.g., hourly) to establish a baseline and detect spikes.
FTDC files are located at:
<storage.dbPath>/diagnostic.data/ (commonly /var/lib/mongodb/diagnostic.data/)systemLog.path (e.g., /var/log/mongodb/mongos.diagnostic.data/)# Copy FTDC files (may require sudo)
sudo cp /var/lib/mongodb/diagnostic.data/metrics.* ./collected-data/ftdc-files/
# Auto-discovery mode - analyzes all available data
./mongobleed-detector.sh --data-dir ./collected-data/
# With custom thresholds
./mongobleed-detector.sh --data-dir ./collected-data/ \
-t 1440 \ # 24-hour lookback
-c 50 \ # Lower connection threshold
--spike-threshold 50 # Lower spike threshold
For backward compatibility, you can still analyze logs directly:
# Scan default paths
./mongobleed-detector.sh
# Scan specific log files
./mongobleed-detector.sh -p /path/to/logs/*.json
# Forensic mode (analyze multiple hosts)
./mongobleed-detector.sh --forensic-dir /evidence/
Automatically collect data from multiple hosts and analyze:
# Create hosts file
cat > hosts.txt << EOF
mongo-prod-01.example.com
mongo-prod-02.example.com
mongo-staging.example.com
EOF
# Collect and analyze
./mongobleed-remote.py --hosts-file hosts.txt --user admin --output-dir ./collected-data/
# Use specific SSH key
./mongobleed-remote.py --hosts-file hosts.txt --user admin --key ~/.ssh/mongodb_key
# Parallel execution
./mongobleed-remote.py --hosts-file hosts.txt --user admin --parallel 10
# Skip FTDC collection (faster)
./mongobleed-remote.py --hosts-file hosts.txt --user admin --skip-ftdc
# Collect only, analyze later
./mongobleed-remote.py --hosts-file hosts.txt --user admin --collect-only
# Pass SSH options (e.g., jump host)
./mongobleed-remote.py --hosts-file hosts.txt --user admin \
-o "ProxyJump=bastion.example.com"
# Use sudo for privileged file access (FTDC files are often restricted)
./mongobleed-remote.py --hosts-file hosts.txt --user admin --sudo
# Debug mode to troubleshoot connection issues
./mongobleed-remote.py --hosts-file hosts.txt --user admin --debug
Note on FTDC Permissions: FTDC files in
/var/lib/mongodb/diagnostic.data/are typically owned by themongodbuser and not readable by regular users. If you see "FTDC Permission Issues" warnings, use the--sudoflag. This requires the remote user to have passwordless sudo access (NOPASSWD in sudoers).
| Data Type | Source | Destination |
|---|---|---|
| Logs | /var/log/mongodb/mongod.log* | <output-dir>/<hostname>/logs/ |
| Assert Counts | mongosh command | <output-dir>/<hostname>/assert-counts/ |
| FTDC Files | /var/lib/mongodb/diagnostic.data/metrics.* | <output-dir>/<hostname>/ftdc-files/ |
| Option | Description | Default |
|---|---|---|
-d, --data-dir <path> | Directory with collected data (auto-discovery mode) | - |
-p, --path <glob> | Additional log path/glob (repeatable) | - |
-t, --time <minutes> | Lookback window in minutes | 4320 (3 days) |
-c, --conn-threshold | Connection count threshold | 100 |
-b, --burst-threshold | Burst rate threshold per minute | 400 |
-m, --metadata-rate | Metadata rate threshold (0.0-1.0) | 0.10 |
--spike-threshold | Assert spike threshold | 100 |
--user-ratio-threshold | User/other assert ratio for single snapshot detection | 250 |
--no-default-paths | Skip default log paths | false |
--forensic-dir <path> | Analyze subdirectories as separate hosts | - |
| Option | Description | Default |
|---|---|---|
-H, --host <hostname> | Remote host to scan (repeatable) | - |
-f, --hosts-file <file> | File containing hostnames (one per line) | - |
-u, --user <user> | SSH username | Current user |
-k, --key <file> | SSH private key file | ssh-agent |
-P, --port <port> | SSH port | 22 |
-o, --ssh-options <opt> | Additional SSH options (repeatable) | - |
--sudo | Use sudo for privileged file access (FTDC) | false |
-O, --output-dir <path> | Directory to store collected data | ./collected-data |
--log-path <path> | Remote log path to collect (repeatable) | Standard paths |
--ftdc-path <path> | Remote FTDC directory path (repeatable) | Standard paths |
--skip-logs | Skip log collection | false |
--skip-asserts | Skip serverStatus().asserts collection | false |
--skip-ftdc | Skip FTDC file collection | false |
--collect-only | Only collect data, don't run analysis | false |
-j, --parallel <n> | Number of parallel connections | 5 |
--timeout <seconds> | SSH command timeout | 300 |
-d, --debug | Enable debug output (show SSH commands) | false |
-q, --quiet | Suppress progress messages | false |
| Code | Meaning |
|---|---|
| 0 | No HIGH or MEDIUM findings |
| 1 | HIGH or MEDIUM findings detected |
| 2 | Error (missing dependencies, no data, etc.) |
The tool provides a combined confidence verdict based on all available evidence:
| Confidence | Criteria | Interpretation |
|---|---|---|
| HIGH | FTDC peaks detected AND suspicious logs in same time window | Strong indicator of exploitation |
| MEDIUM | FTDC peaks OR suspicious logs (not correlated) | Investigation recommended |
| LOW | Only cumulative assert counts without spikes | Anomaly detected, weak evidence |
| INFO | No significant findings | Normal activity |
For log correlation (Module A), individual IPs are classified:
| Risk | Criteria |
|---|---|
| HIGH | Connections ≥ threshold, metadata rate < 10%, burst rate ≥ 400/min |
| MEDIUM | Connections ≥ threshold, metadata rate < 10%, burst rate < 400/min |
| LOW | Connections ≥ threshold, metadata rate ≥ 10% |
| INFO | Connections < threshold |
INFO: Auto-discovery mode: analyzing ./collected-data/
INFO: Module A: Analyzing 3 log file(s)...
INFO: Module B1: Analyzing assert-counts...
╔══════════════════════════════════════════════════════════════════════════════════════════════════════════════════╗
║ MongoBleed (CVE-2025-14847) Detection Results ║
╚══════════════════════════════════════════════════════════════════════════════════════════════════════════════════╝
Module Status:
[✓] Module A (Log Correlation): 3 log file(s) found
[✓] Module B1 (Assert Counts): 4 snapshot(s) found
[−] Module B2 (FTDC Spikes): No FTDC files or decoder unavailable
Analysis Parameters:
Time Window: 4320 minutes
Connection Thresh: 100
Burst Rate Thresh: 400/min
Metadata Rate: 0.10
Spike Threshold: 100
User Ratio Thresh: 250x
Module A - Log Correlation Findings:
Risk SourceIP ConnCount MetaCount DiscCount MetaRate% BurstRate/m FirstSeen (UTC) LastSeen (UTC)
-------- ---------------------------------------- ---------- ---------- ---------- ------------ -------------- ---------------------- ----------------------
HIGH 137.137.137.137 8172 0 8172 0.00% 490.32 2025-12-27T12:55:52Z 2025-12-27T13:12:32Z
Module B1 - Assert Counts Analysis:
Analyzed 4 snapshots from 2025-01-01T10:00:00Z to 2025-01-01T11:30:00Z
asserts.user: 100 -> 860 (delta: 760)
SPIKE DETECTED: 2025-01-01T10:30:00Z to 2025-01-01T11:00:00Z
Delta: +740 user asserts (110 -> 850)
═══════════════════════════════════════════════════════════════════════════════════════════════════════════════════
Combined Verdict:
MEDIUM CONFIDENCE - Investigation recommended
- Suspicious connection patterns but FTDC data unavailable for correlation
⚠ IMPORTANT: If exploitation is confirmed, patching alone is insufficient.
- Rotate all credentials that may have been exposed
- Review accessed data for sensitive information disclosure
- Check for lateral movement from affected systems
- Preserve logs for forensic analysis
Caveats:
- Connection metadata absence is PoC-specific and can be evaded
- Assertion counters are cumulative - false positives possible without baseline
- FTDC provides timing but not perfect attribution
- Patch + rotate secrets remains mandatory regardless of detection results
The repository includes a test suite to validate the detector.
The example-data/ directory contains real data from a MongoDB 8.0.16 instance that was attacked using the MongoBleed PoC:
example-data/
├── logs/ # Real MongoDB logs with attack patterns
│ ├── mongod.log
│ └── mongod.log.1.gz
├── assert-counts/ # Post-attack serverStatus().asserts snapshot
│ └── asserts-post-attack.json
└── ftdc-files/ # Real FTDC diagnostic data files
└── metrics.*
This data shows:
./test/generate-test-logs.sh
This creates additional synthetic test data with various patterns:
./test/test-detector.sh
Expected output:
╔════════════════════════════════════════════════════════╗
║ MongoBleed Detector Test Suite ║
╚════════════════════════════════════════════════════════╝
Module A Tests (Log Correlation):
✓ PASS: Exit code is 1 (findings detected)
✓ PASS: Detected source IP 137.137.137.137
...
Module B1 Tests (Assert Counts):
✓ PASS: Shows Module B1 status
✓ PASS: Detected assert spike
...
Auto-Discovery Mode Tests:
✓ PASS: Shows Module A status
✓ PASS: Shows combined verdict
...
Results:
Passed: 24
Failed: 0
All tests passed!
⚠️ Important Limitations
PoC-Specific Detection: The metadata absence detection is based on the known MongoBleed PoC behavior. A sophisticated attacker could modify the exploit to send fake metadata, though this would reduce exploitation speed.
Cumulative Counters: asserts.user is cumulative since mongod restart. Without baseline snapshots, high values may be normal for long-running instances. Multiple snapshots over time significantly improve accuracy.
FTDC Timing: FTDC provides timing information but not perfect attribution. Use in conjunction with log correlation for best results.
Log Retention: Can only analyze logs that exist. Aggressive rotation or attacker log clearing will destroy evidence.
JSON Logging Required: MongoDB 4.4+ defaults to JSON logs. Legacy text logs are not supported.
FTDC Decoder: FTDC decoding requires Python 3 with pymongo. Without it, Module B2 is unavailable.
mongosh Access: Collecting assert counts requires mongosh with appropriate permissions.
If HIGH or MEDIUM findings are confirmed:
The detection logic in this tool is based on research by Eric Capuano and Tamir Zimerman:
| Version | Vulnerable | Fixed In |
|---|---|---|
| 8.2.x | 8.2.0 - 8.2.2 | 8.2.3 |
| 8.0.x | 8.0.0 - 8.0.16 | 8.0.17 |
| 7.0.x | 7.0.0 - 7.0.27 | 7.0.28 |
| 6.0.x | 6.0.0 - 6.0.26 | 6.0.27 |
| 5.0.x | 5.0.0 - 5.0.31 | 5.0.32 |
| 4.4.x | 4.4.0 - 4.4.29 | 4.4.30 |
| 4.2.x | 4.2.0+ | No fix |
| 4.0.x | 4.0.0+ | No fix |
| 3.6.x | 3.6.0+ | No fix |
See LICENSE file.
Contributions welcome! Please submit issues and pull requests.
If you test this tool against production data, we'd especially appreciate feedback on: