Nosql Injection on Azure
How Nosql Injection Manifests in Azure
Nosql Injection in Azure environments typically occurs when applications interact with Azure Cosmos DB using untrusted user input. Unlike traditional SQL injection, NoSQL injection exploits the query language syntax of document databases, allowing attackers to manipulate query logic and access unauthorized data.
In Azure Cosmos DB, the most common attack vector involves JavaScript-based queries or LINQ expressions that incorporate user input without proper sanitization. Consider this vulnerable Azure Function:
const CosmosClient = require('@azure/cosmos').CosmosClient;
module.exports = async function (context, req) {
const client = new CosmosClient({
endpoint: process.env.COSMOS_ENDPOINT,
key: process.env.COSMOS_KEY
});
const { email } = req.query;
const query = `SELECT * FROM c WHERE c.email = '${email}'`;
const result = await client
.database('myDatabase')
.container('users')
.items.query(query)
.fetchAll();
context.res = { body: result };
};An attacker could supply email=test%40example.com%27%20OR%20%271%27=%271 to bypass authentication or extract all user records. The NoSQL query parser interprets the injected logic, returning all documents regardless of email address.
Another Azure-specific pattern involves Azure Table Storage, where dynamic OData filters create injection opportunities:
var tableClient = new TableServiceClient(connectionString);
var filter = "PartitionKey eq 'users' and RowKey eq '" + userId + "'";
var query = new TableQuery().Where(filter);
var results = await tableClient.QueryAsync(query);Azure Functions and Logic Apps that process NoSQL queries from HTTP triggers are particularly vulnerable when developers concatenate user input directly into query strings.
Azure-Specific Detection
Detecting NoSQL injection in Azure environments requires both static analysis and runtime scanning. middleBrick's Azure-focused scanning identifies injection vulnerabilities by analyzing API endpoints that interact with NoSQL databases.
For Azure Cosmos DB, middleBrick tests for injection by submitting specially crafted payloads that attempt to manipulate query logic. The scanner evaluates whether responses contain data that shouldn't be accessible, indicating successful injection attempts.
Key detection patterns include:
- Testing for unescaped special characters in query parameters
- Submitting boolean logic payloads to test query manipulation
- Attempting JavaScript injection in Cosmos DB stored procedures
- Testing Azure Table Storage OData filter injection
middleBrick's Azure-specific checks include:
middlebrick scan https://myapi.azurewebsites.net/api/users \
--azure-cosmos-db \
--azure-table-storage \
--output jsonThe scanner provides detailed findings with severity levels and remediation guidance specific to Azure's NoSQL implementations. For example, it identifies when applications use raw query construction instead of parameterized queries, which is the primary vulnerability pattern in Azure Cosmos DB.
Azure Monitor and Application Insights can complement middleBrick by detecting anomalous query patterns at runtime, such as unusual document access patterns or repeated failed query attempts that might indicate injection testing.
Azure-Specific Remediation
Azure provides several native approaches to prevent NoSQL injection. The most effective remediation is using parameterized queries with the Azure Cosmos DB SDK:
const CosmosClient = require('@azure/cosmos').CosmosClient;
module.exports = async function (context, req) {
const client = new CosmosClient({
endpoint: process.env.COSMOS_ENDPOINT,
key: process.env.COSMOS_KEY
});
const { email } = req.query;
const querySpec = {
query: 'SELECT * FROM c WHERE c.email = @email',
parameters: [
{
name: '@email',
value: email
}
]
};
const result = await client
.database('myDatabase')
.container('users')
.items.query(querySpec)
.fetchAll();
context.res = { body: result };
};For Azure Table Storage, use the TableEntity class with parameterized queries:
var tableClient = new TableServiceClient(connectionString);
var userIdParam = new TableEntity("users", userId);
var results = await tableClient.GetEntityAsync<User>(userIdParam.PartitionKey, userIdParam.RowKey);Azure API Management can add an additional security layer by validating and sanitizing input before it reaches your API:
<validate-jwt header-name="Authorization" failed-validation-httpcode="401" failed-validation-error-message="Unauthorized. Access token is missing or invalid."/>
<validate-content type="application/json" max-size="100000"/>
<rewrite-uri template="/api/users" copy-unmatched-params="false"/>For Logic Apps, use the built-in data operations to sanitize inputs before database operations:
@string(replace(triggerBody()['email'], '''', '')) Azure Key Vault should store database credentials rather than hardcoding them, reducing the attack surface if injection does occur.