Skip to content

[FALSE-POSITIVE] CVE-2025-14847: High False Positives on Non-MongoDB Services due to Blind Payload Injection & Flawed Matcher Logic #15560

@Eren-Akdag

Description

@Eren-Akdag

Template IDs or paths

- `javascript/cves/2025/CVE-2025-14847.yaml`

Environment

- **OS:** macOS (darwin/arm64)
- **Nuclei:** v3.7.0
- **Go:** go1.25.5

Description

The JavaScript-based verification (javascript(1)) present within the CVE-2025-14847 (MongoBleed) template consistently triggers false positives against non-MongoDB services (e.g., MySQL on port 3306, HTTP servers, SSH banners).

Despite incorporating strict MongoDB version-checking matchers in the tcp(1) section, these matchers are entirely bypassed. Because the workflow is structured as flow: javascript(1) || tcp(1), the initial javascript step blindly fires arbitrary payloads, poorly interprets standard response banners as memory leaks, immediately declares the target vulnerable, and exits the flow before the robust tcp version checks are ever evaluated.

Root Cause Analysis

I've analyzed the script logic closely and identified three critical flaws leading to this behavior:

1. Lack of Target Fingerprinting (Blind Injection)

The JavaScript code directly connects over TCP and immediately sends a malformed, Zlib-compressed MongoDB payload without verifying the remote service protocol.

const conn = net.Open('tcp', `${Host}:${Port}`);
// Immediately fires the MongoDB specific payload without verifying service.
conn.SendHex(fullMessage);

2. Insufficient Exception Handling (Forcing Data Parsing)

When a non-MongoDB service (like MySQL) responds with a plain-text greeting banner, it fails the MongoDB message-length calculations. Instead of safely failing or aborting the false service match, the catch (e) block forcibly retains this non-MongoDB datastream for "leak" analysis.

try {
  // Attempts to parse MongoDB headers
  const msgLen = responseBytes[0] | (responseBytes[1] << 8) | ...
} catch (e) {
  // FLAW: Retains non-MongoDB responses (e.g., MySQL Banners) for leak analysis anyway.
  raw = responseBytes.length > 16 ? responseBytes.slice(16) : [];
}

3. Loose Leak Detection Algorithm

The extractLeaks function assumes any contiguous string of ≥10 printable characters represents a "memory leak", provided it does not match a limited, hardcoded list of MongoDB error tokens (invalid, bson, field name).

if (printableSeq.length >= 10) {
  const lower = printableSeq.toLowerCase();
  // Flaw: A standard MySQL banner like "5.7.34-log" easily passes this negative check.
  if (lower.indexOf('field name') === -1 && lower.indexOf('invalid') === -1 && ...) {
    leaks.push(printableSeq);
  }
}

As a result, a target running MySQL on port 3306 responds with "5.5.5-10.4.32-MariaDB". This triggers the ≥10 printable sequence check, bypassing the MongoDB-specific exclusions, and registers as ["leak found at offset 20"].


Steps To Reproduce

  1. Setup an empty target running a common non-MongoDB service that returns a connection banner:
    • For example, start a MySQL container on port 3306.
  2. Run nuclei -t nuclei-templates/javascript/cves/2025/CVE-2025-14847.yaml -u mysql-target.local:3306

Expected Behavior: Nuclei should recognize the target is not MongoDB and gracefully move on (no findings).
Actual Behavior: Nuclei loudly reports [CVE-2025-14847] [high] with ["leak found at offset 20"].

Relevant dumped responses

Below is an example of what is printed when running with -dresp against an empty MySQL server on port 3306. Nuclei reads the standard MySQL protocol greeting banner and wrongly classifies the sequence of printable characters as an extracted memory risk from MongoDB.

Host: TARGET:3306
Response:

J
5.5.5-10.4.32-MariaDB-1:10.4.32+maria~ubu200~aN(P	%j?D2mO$K_#3]mysql_native_password

(The banner text perfectly triggers printableSeq.length >= 10 check and avoids MongoDB-specific exclusion words, registering an automatic false positive.)


Proposed Fix / Hardening Suggestions

To ensure compliance with the repository's high standards (preventing wide false positives), the javascript module must be hardened.

Layer Recommended Action Benefits
1. Protocol Fingerprinting Introduce a pre-condition check sending a lightweight, valid MongoDB isMaster or ping command. Abort the test if the target does not reply with a valid BSON document. Stops testing immediately against MySQL, HTTP, FTP, etc.
2. Response Validation Inside the JavaScript network loop, calculate the expected BSON document length. If the returned byte stream does not adhere to the MongoDB Wire Protocol format, reject it directly in the try-catch block. Prevents plain text HTTP headers/banners from being tested for "leaks".
3. Execution Flow The tcp(1) version checks are robust but completely ignored due to the OR (||) operator in the flow: block. If the javascript module cannot be made strictly safe, consider swapping the flow to use AND (&&) or running version checks first: flow: tcp(1) && javascript(1) Prevents blindly injecting dangerous payloads into innocent machines; leverages existing good matchers.

Anything else?

This issue is highly reproducible anytime this template is intentionally run against common open web ports manually via the -u target flag (e.g., -u example.com:3306 or -u example.com:80), or when automated port discovery tools pass raw open non-HTTP sockets directly into Nuclei as targets. Ensuring the javascript engine safely escapes against non-conforming responses will significantly improve the signal-to-noise ratio for MongoBleed scans in large environments.

Metadata

Metadata

Assignees

Labels

false-positiveNuclei template reporting invalid/unexpected result

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions