Nosql Injection in Actix
How NoSQL Injection Manifests in Actix
NoSQL injection is a vulnerability that occurs when untrusted user input is used to construct NoSQL database queries without proper sanitization. In Actix applications, this commonly happens when handling JSON payloads or query parameters that are directly passed to databases like MongoDB. Unlike SQL injection, NoSQL injection exploits dynamic query operators such as $ne, $gt, or $regex.
Consider an Actix handler that authenticates users by checking a username and password against a MongoDB collection. A typical mistake is to accept a JSON body and use it directly in a query:
use actix_web::{web, HttpResponse};
use mongodb::{Client, Collection};
use bson::doc;
async fn login(
data: web::Json<serde_json::Value>,
client: web::Data<Client>,
) -> HttpResponse {
let collection: Collection = client.database("mydb").collection("users");
let query = doc! {
"username": data.get("username").unwrap(),
"password": data.get("password").unwrap(),
};
// ... perform find and check
}
Here, data is a serde_json::Value that can contain any JSON structure. An attacker could send a payload like:
{
"username": {"$ne": null},
"password": {"$ne": null}
}
This matches any user document where both fields are not null, bypassing authentication. The vulnerability stems from Actix's flexible web::Json extractor allowing arbitrary JSON and the direct use of that data in a MongoDB query without validation.
Similarly, when using web::Query for GET parameters, an attacker might inject operators via query strings. For example, a route like /api/users?username=admin that uses the username parameter in a query could be exploited with username=admin&password[$ne]=null if the parameters are parsed into a serde_json::Value or HashMap and then used directly.
Actix-Specific Detection
Detecting NoSQL injection in Actix requires both code review and dynamic testing. In code, look for patterns where user-controlled input (from web::Json, web::Query, or web::Form) is used to construct a MongoDB query document without sanitization. Specifically, check if input is used as a value in a doc! macro or if a bson::Document is built by inserting keys and values from the request.
Dynamic scanning is where tools like middleBrick excel. middleBrick's Input Validation check actively probes your Actix API endpoints with payloads designed to trigger NoSQL injection. For example, it might send:
{"field": {"$ne": null}}to test for inequality bypass{"field": {"$regex": ".*"}}to test for regex-based enumeration{"field": {"$where": "function() { return true; }"}}to test for JavaScript injection (if applicable)
middleBrick sends these payloads to every endpoint that accepts JSON or query parameters and analyzes the responses. If the response status code, content length, or body indicates a successful query manipulation (e.g., returning more records than expected, or a different error message), it flags the endpoint as vulnerable. The scan takes only 5–15 seconds and requires no credentials, making it suitable for testing the unauthenticated attack surface of your Actix API.
In the middleBrick dashboard, you'll see a per-endpoint breakdown with the specific parameter that was injectable, the payload used, and the evidence. This helps you quickly locate the vulnerable code path in your Actix application.
Actix-Specific Remediation
Remediating NoSQL injection in Actix involves ensuring user input cannot influence the query structure. The safest approach is to avoid building queries from raw, untrusted data. Instead, use Actix's extractors to deserialize input into strongly-typed structs and then construct queries using the doc! macro with literal values.
For example, rewrite the vulnerable login handler as follows:
use actix_web::{web, HttpResponse};
use mongodb::{Client, Collection};
use bson::doc;
use serde::Deserialize;
#[derive(Deserialize)]
struct LoginRequest {
username: String,
password: String,
}
async fn login(
data: web::Json<LoginRequest>,
client: web::Data<Client>,
) -> HttpResponse {
let collection: Collection = client.database("mydb").collection("users");
let query = doc! {
"username": &data.username,
"password": &data.password,
};
// ... perform find and check
}
By using a struct with String fields, Actix's web::Json will reject any JSON that does not match the expected shape. The doc! macro then creates a bson::Document with the provided string values. Since the values are strings, an attacker cannot inject operators like $ne because they would be treated as literal strings, not as query operators.
If you must accept arbitrary JSON (e.g., for a flexible search endpoint), validate and sanitize the input. One method is to recursively traverse the serde_json::Value and reject any object that contains keys starting with $ or containing a . (which are special in MongoDB). Alternatively, use a whitelist of allowed fields and build the query from that whitelist, ignoring any other parameters.
For query parameters, use the same approach: define a struct and use web::Query. After fixing, re-scan with middleBrick to verify the vulnerability is resolved. middleBrick's continuous monitoring (available in Pro and Enterprise plans) can automatically re-scan your Actix API on a schedule and alert you if new injection issues appear.
Frequently Asked Questions
What is NoSQL injection and why is it a risk in Actix applications?
web::Json) can accept arbitrary JSON, which might then be used to build a MongoDB query without validation. An attacker can use operators like $ne or $regex to bypass authentication, extract data, or execute arbitrary JavaScript (via $where) if the database supports it. This can lead to data breaches, unauthorized access, and data loss.How does middleBrick detect NoSQL injection vulnerabilities in Actix APIs?
{"field": {"$ne": null}} or query parameters like ?field[$ne]=null. It then analyzes the responses for signs of successful injection, such as unexpected data being returned, error messages revealing query structure, or changes in response status. The scan is black-box, requiring no credentials, and takes only seconds. The resulting report pinpoints the vulnerable endpoint and parameter, providing the evidence needed to fix the issue.