Weakness reference
CWE-943

Improper Neutralization of Special Elements in Data Query Logic

This weakness occurs when an application builds a data query SQL, NoSQL, LDAP, or similar using unsanitized user input, allowing an attacker to inject special…

01Summary

This weakness occurs when an application builds a data query (SQL, NoSQL, LDAP, or similar) using unsanitized user input, allowing an attacker to inject special characters or operators that alter the query's logic. Unlike traditional SQL injection, this category encompasses injection flaws across multiple query languages and data access patterns, including NoSQL databases where the attack surface differs but the root cause—failure to neutralize untrusted input—remains the same.

02How It Happens

When an application constructs a query by concatenating or interpolating user-supplied data without proper validation or parameterization, an attacker can insert query syntax that the database interprets as commands rather than literal data. This happens because the application treats user input as code rather than data. The vulnerability is especially common in NoSQL contexts, where queries are often built as objects or JSON structures, and developers may assume that object-based queries are inherently safe—a dangerous misconception. Any query language that accepts structured input (SQL, MongoDB, Elasticsearch, LDAP, etc.) is vulnerable if user input is not properly neutralized.

03Real-World Impact

Successful exploitation can lead to unauthorized data access, modification, or deletion. An attacker might bypass authentication logic, extract sensitive records, escalate privileges, or corrupt entire datasets. In NoSQL environments, the impact can be particularly severe because the query structure is less obvious to developers, leading to a false sense of security. The consequences range from confidentiality breaches (data theft) to integrity violations (unauthorized modification) to availability issues (data destruction or denial of service).

04Vulnerable & Fixed Patterns

Vulnerable pattern
import pymongo

client = pymongo.MongoClient("mongodb://localhost:27017/")
db = client["app_db"]
users = db["users"]

username = request.args.get("username")
password = request.args.get("password")

# Vulnerable: user input directly in query object
user = users.find_one({"username": username, "password": password})

Why it's vulnerable:
If an attacker submits username={"$ne": ""} and password={"$ne": ""}, the query becomes {"username": {"$ne": ""}, "password": {"$ne": ""}}, which matches any user record, bypassing authentication entirely.

Fixed pattern
import pymongo
from bson import ObjectId

client = pymongo.MongoClient("mongodb://localhost:27017/")
db = client["app_db"]
users = db["users"]

username = request.args.get("username")
password = request.args.get("password")

# Fixed: validate input type and use parameterized query
if isinstance(username, str) and isinstance(password, str):
    user = users.find_one({"username": username, "password": password})
else:
    user = None
Vulnerable pattern
<?php
$mysqli = new mysqli("localhost", "user", "password", "app_db");

$username = $_GET["username"];
$password = $_GET["password"];

// Vulnerable: direct string interpolation in query
$query = "SELECT * FROM users WHERE username = '" . $username . "' AND password = '" . $password . "'";
$result = $mysqli->query($query);
?>

Why it's vulnerable:
An attacker can submit username=' OR '1'='1 to bypass the WHERE clause, or use -- to comment out the password check entirely.

Fixed pattern
<?php
$mysqli = new mysqli("localhost", "user", "password", "app_db");

$username = $_GET["username"];
$password = $_GET["password"];

// Fixed: use prepared statements with parameterized queries
$stmt = $mysqli->prepare("SELECT * FROM users WHERE username = ? AND password = ?");
$stmt->bind_param("ss", $username, $password);
$stmt->execute();
$result = $stmt->get_result();
?>

05Prevention Checklist

Use parameterized queries or prepared statements
for all database interactions; never concatenate or interpolate user input into query strings or objects.
Validate input type and format
before use—enforce that usernames are strings, IDs are integers, etc., and reject anything that doesn't match the expected type.
Implement allowlisting
for any user input that must be used in query operators or field names; reject anything not on the whitelist.
Apply principle of least privilege
to database accounts; ensure application credentials have only the minimum permissions needed (no DROP, no administrative access).
Use an ORM or query builder
that abstracts query construction and enforces parameterization by default.
Log and monitor query patterns
for anomalies; unusual operators or deeply nested structures in logs may indicate injection attempts.

06Signs You May Already Be Affected

Review your application logs for unusual query patterns, unexpected operators (like $ne, $gt, $regex in NoSQL logs), or queries that return far more records than expected. Check for unexpected admin accounts or users with unusual creation timestamps. If you find user input being concatenated directly into query code (visible in source code review), you are vulnerable regardless of whether an attack has occurred yet.

07Related Recent Vulnerabilities