Skip to main content
Glama

nosqli_detect

Detect NoSQL injection vulnerabilities by testing MongoDB operator injection in query parameters and JSON body. Identifies injection points using payloads for $ne, $gt, $regex, and $where operators.

Instructions

Test NoSQL injection detection in query parameters. Tests MongoDB operator injection ($ne, $gt, $regex, $where) in GET parameters and JSON body to detect NoSQL injection points. Returns: {baseline, results: [{payload_name, status, length, different}], injectable}. Side effects: Read-only. Sends ~10 requests.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
urlYesURL with query parameter to test, e.g. https://target/api/products?category=Gifts
parameterYesParameter name to test for NoSQL injection
methodNoHTTP methodGET
content_typeNo'query' for URL params, 'json' for JSON bodyquery

Implementation Reference

  • The handler and schema for 'nosqli_detect' tool. It tests MongoDB operator injection using curl commands based on provided URL, parameter, and method/content_type parameters.
    server.tool(
      "nosqli_detect",
      "Test NoSQL injection detection in query parameters. Tests MongoDB operator injection ($ne, $gt, $regex, $where) in GET parameters and JSON body to detect NoSQL injection points. Returns: {baseline, results: [{payload_name, status, length, different}], injectable}. Side effects: Read-only. Sends ~10 requests.",
      {
        url: z
          .string()
          .describe(
            "URL with query parameter to test, e.g. https://target/api/products?category=Gifts"
          ),
        parameter: z
          .string()
          .describe("Parameter name to test for NoSQL injection"),
        method: z
          .enum(["GET", "POST"])
          .describe("HTTP method")
          .default("GET"),
        content_type: z
          .enum(["query", "json"])
          .describe("'query' for URL params, 'json' for JSON body")
          .default("query"),
      },
      async ({ url, parameter, method: _method, content_type }) => {
        requireTool("curl");
    
        const baseUrl = url.split("?")[0];
    
        // Get baseline
        let baselineRes;
        if (content_type === "query") {
          baselineRes = await runCmd("curl", [
            "-sk",
            "-o",
            "/dev/null",
            "-w",
            "%{http_code}:%{size_download}",
            url,
          ]);
        } else {
          baselineRes = await runCmd("curl", [
            "-sk",
            "-o",
            "/dev/null",
            "-w",
            "%{http_code}:%{size_download}",
            "-X",
            "POST",
            "-H",
            "Content-Type: application/json",
            "-d",
            JSON.stringify({ [parameter]: "test" }),
            baseUrl,
          ]);
        }
    
        const bp = baselineRes.stdout.split(":");
        const blStatus = bp.length > 0 ? parseInt(bp[0], 10) || 0 : 0;
        const blLength = bp.length > 1 ? parseInt(bp[1], 10) || 0 : 0;
    
        let testPayloads: [string, string][];
        if (content_type === "query") {
          testPayloads = [
            ["$ne_null", `${parameter}[$ne]=null`],
            ["$ne_empty", `${parameter}[$ne]=`],
            ["$gt_empty", `${parameter}[$gt]=`],
            ["$regex_all", `${parameter}[$regex]=.*`],
            ["$exists_true", `${parameter}[$exists]=true`],
            ["$where_true", `$where=1`],
            ["$where_sleep", `$where=sleep(100)`],
            ["regex_injection", `${parameter}='+{$regex:+'.'}'`],
            ["json_in_query", `${parameter}={"$ne":null}`],
          ];
        } else {
          testPayloads = [
            ["$ne_null", JSON.stringify({ [parameter]: { $ne: null } })],
            ["$ne_empty", JSON.stringify({ [parameter]: { $ne: "" } })],
            ["$gt_empty", JSON.stringify({ [parameter]: { $gt: "" } })],
            ["$regex_all", JSON.stringify({ [parameter]: { $regex: ".*" } })],
            [
              "$exists_true",
              JSON.stringify({ [parameter]: { $exists: true } }),
            ],
            ["$where_true", JSON.stringify({ $where: "1" })],
            [
              "$or_bypass",
              JSON.stringify({
                $or: [
                  { [parameter]: { $ne: "" } },
                  { [parameter]: { $exists: true } },
                ],
              }),
            ],
          ];
        }
    
        const results: Array<{
          payload_name: string;
          payload: string;
          status: number;
          length: number;
          different_from_baseline: boolean;
        }> = [];
    
        for (const [payloadName, payload] of testPayloads) {
          let curlArgs: string[];
          if (content_type === "query") {
            curlArgs = [
              "-sk",
              "-o",
              "/dev/null",
              "-w",
              "%{http_code}:%{size_download}",
              `${baseUrl}?${payload}`,
            ];
          } else {
            curlArgs = [
              "-sk",
              "-o",
              "/dev/null",
              "-w",
              "%{http_code}:%{size_download}",
              "-X",
              "POST",
              "-H",
              "Content-Type: application/json",
              "-d",
              payload,
              baseUrl,
            ];
          }
    
          const res = await runCmd("curl", curlArgs);
          const parts = res.stdout.split(":");
          const status = parts.length > 0 ? parseInt(parts[0], 10) || 0 : 0;
          const length = parts.length > 1 ? parseInt(parts[1], 10) || 0 : 0;
    
          const different =
            status !== blStatus || Math.abs(length - blLength) > 50;
    
          results.push({
            payload_name: payloadName,
            payload: payload.slice(0, 200),
            status,
            length,
            different_from_baseline: different,
          });
        }
    
        const injectablePayloads = results.filter(
          (r) => r.different_from_baseline
        );
        const result = {
          baseline: { status: blStatus, length: blLength },
          results,
          injectable_payloads: injectablePayloads.map((r) => r.payload_name),
          injectable: injectablePayloads.length > 0,
          hint:
            injectablePayloads.length > 0
              ? `NoSQL injection likely! ${injectablePayloads.length} payload(s) produced different responses.`
              : "No injection indicators. Parameter appears properly sanitized.",
        };
    
        return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
      }
    );

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/operantlabs/operant-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server