Background
In Bastion Security’s recent penetration testing engagements, SQL Injection (SQLi) continues to be one of the most frequently identified vulnerabilities. However, injection risks are not limited to traditional SQL databases. One example worth highlighting is NoSQL Injection (NoSQLi).
NoSQLi rarely gets the same attention as SQL Injection (SQLi). Often application developers, or security teams, assume that moving to MongoDB-style databases or JSON-driven APIs automatically removes injection risk. This belief stems from the knowledge that there’s no SQL syntax, no quotes to escape, and no classic UNION SELECT tricks.
However, this assumption is incorrect. In modern applications / APIs, queries are no longer strings; they are objects. And when user input is allowed to influence those objects, the attacker does not need to break syntax. They just need to change their intent.
Problem
Modern web services and APIs routinely:
- Accept JSON input directly from clients
- Construct database queries dynamically at runtime
- Trust structured input more than raw strings
In vulnerable implementations, user-controlled JSON is merged straight into backend queries. This allows attackers to introduce query operators, conditions, or logic that the application never intended to expose, shifting the vulnerability from the syntax level to the logic and intent level.
Proof of Concept – Damn Vulnerable Web Services (DVWS)
For this article, we use Damn Vulnerable Web Services (DVWS), an intentionally vulnerable web service and API platform designed to demonstrate common API and backend security flaws.
DVWS exposes a public notes search feature that accepts a JSON request containing a search parameter. This value is used by the backend to dynamically construct a NoSQL query intended to return only public notes matching the search term. Because the application trusts this input, an attacker can supply crafted values that alter how the query condition is evaluated, allowing all public notes to be returned. The database executes a valid query, but the logic controlling what data should be accessible has been subverted.
This is not a traditional injection flaw. There are no syntax errors or malformed requests. The issue exists because user input is allowed to influence query logic rather than just query values.
Below are the detailed steps we used to demonstrate this point:
We first installed DWVS in our local environment.

The next step is to create a few public and private notes. The following screenshot shows a “secret” note, that is marked as “private”, being created.

Next, we navigate to the Search Notes functionality at /search.html. Although the form appears to function normally, it is actually vulnerable to NoSQL injection.

The image below shows a search for notes titled “secret”; however, no results are returned because the note was marked as private, and the endpoint only returns public notes.

At this stage, our objective is to demonstrate whether private notes can be accessed by manipulating the search functionality.
Instead of submitting a normal search keyword, a specially crafted input, as the following, can be provided:
- {"search":"' || true || '"}
The following image shows the POST request made when the above search value was submitted:

The following image shows the response returned:

As shown in the image above, instead of returning only notes that matched a specific title, the endpoint returned a broader set of records, including the secret note that was not visible through the normal search interface. This behavior occurred due to the injection attack, in which untrusted input altered the query logic as a result of insufficient input sanitisation.
Prevention
Most traditional defenses, e.g basic input validation, still matter, however they are no longer sufficient on their own. The following are some practical steps that help in modern NoSQL-backed and API-driven environments:
- Do not allow user input to directly control query objects or operators
- Use predefined query structures and strict allow-lists for fields and conditions explicitly block or strip unsupported NoSQL operators (e.g. logical or comparison operators)
- Apply least-privilege access for application services and backend APIs
- Validate query intent and scope, not just JSON structure or data types
- Treat all structured input as untrusted, even when it appears well-formed
Ultimately, preventing modern NoSQL Injection is less about blocking “bad JSON” and more about preventing untrusted input from becoming query logic, ensuring clients can only provide values, while the application alone controls operators, fields, and query structure.
Conclusion
As applications adopt modern NoSQL databases such as MongoDB and increasingly rely on API-driven architectures, traditional security assumptions can create a false sense of safety. This PoC demonstrates that vulnerabilities may emerge not from legacy technology, but from how query logic and trust boundaries are implemented.
References
- Testing for NoSQL Injection
- NoSQL Security Cheat Sheet
- NoSQL Injection Explained: What It Is and How to Prevent It
