HIGH sql injectionazure

Sql Injection on Azure

How Sql Injection Manifests in Azure

In Azure environments, SQL injection typically occurs when user‑supplied data is concatenated directly into a Transact‑SQL string that is sent to Azure SQL Database, Azure SQL Managed Instance, Azure Database for MySQL, or Azure Database for PostgreSQL. Common entry points include:

  • Azure Functions (HTTP trigger) that receive query parameters or JSON payloads and build a query string with string interpolation.
  • ASP.NET Core APIs hosted in Azure App Service or Azure Container Apps that use SqlCommand with CommandText built from user input.
  • Logic Apps or Power Automate flows that call a stored procedure via the SQL connector and pass dynamic values without parameterization.
  • Azure Static Web Apps with a backend API that forwards form data to a SQL endpoint.

An attacker can inject payloads such as ' OR 1=1-- to bypass authentication, ; DROP TABLE Users; to cause data loss, or UNION SELECT @@version, NULL, NULL-- to extract database metadata. These patterns map to OWASP API Security Top 10 A3: Injection and are frequently seen in real‑world breaches (e.g., CVE‑2021‑26084 affecting Confluence, where improper input handling allowed SQL injection).

Because Azure services often expose endpoints over the public internet, unauthenticated scanners like middleBrick can reach the same attack surface an external attacker would, testing for these injection vectors without any credentials or agents.

Azure-Specific Detection

Detecting SQL injection in Azure workloads involves both automated scanning and manual inspection of logs and code. middleBrick performs a black‑box, unauthenticated scan of the exposed API surface, sending a series of crafted payloads to each endpoint and analyzing responses for signs of successful injection (e.g., error messages containing SQL syntax, unexpected data in the response body, or changes in response time).

To run a scan with middleBrick:

# Install the CLI (npm)
npm i -g middlebrick
# Scan an Azure-hosted API
middlebrick scan https://myapi.azurewebsites.net/api/products

The tool returns a JSON report that includes:

  • A risk score (A–F) and a breakdown per OWASP category.
  • Findings labeled "SQL Injection" with severity, the exact payload used, and the affected endpoint.
  • Remediation guidance referencing Azure‑specific fixes (parameterized queries, use of Entity Framework Core, etc.).

Beyond middleBrick, you can enable:

  • Azure Monitor diagnostics for Azure SQL Database to capture error_number 208 (invalid object name) or 102 (incorrect syntax) that often surface when injection attempts fail.
  • Azure Application Insights custom telemetry to log exceptions from SqlException.
  • Code review practices that look for string concatenation or interpolation in SqlCommand.CommandText, ExecuteReader, or raw SQL strings passed to DbContext.Database.ExecuteSqlRaw.

Combining automated scanning with these telemetry sources gives visibility into both successful and blocked injection attempts.

Azure-Specific Remediation

The most reliable defense against SQL injection is to never build SQL strings from untrusted input. Azure provides native libraries that make parameterized queries straightforward.

C# (Azure Functions / ASP.NET Core)

Replace concatenated queries with SqlParameter objects:

using System.Data;
using System.Data.SqlClient;
using Microsoft.Azure.Functions.Worker;
using Microsoft.Azure.Functions.Worker.Http;

public static class GetProduct
{
    [Function("GetProduct")]
    public static async Task<HttpResponseData> Run(
        [HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "products/{id}")] HttpRequestData req,
        FunctionContext executionContext)
    {
        string idStr = req.Route.Parameters["id"];
        if (!int.TryParse(idStr, out int productId))
        {
            var badResp = req.CreateResponse(System.Net.HttpStatusCode.BadRequest);
            await badResp.WriteStringAsync("Invalid product id");
            return badResp;
        }

        using var conn = new SqlConnection(Environment.GetEnvironmentVariable("SQL_CONNECTION_STRING"));
        await conn.OpenAsync();
        using var cmd = new SqlCommand("SELECT Name, Price FROM Products WHERE Id = @Id", conn);
        cmd.Parameters.Add("@Id", SqlDbType.Int).Value = productId;

        using var reader = await cmd.ExecuteReaderAsync();
        if (!reader.Read())
        {
            var notFound = req.CreateResponse(System.Net.HttpStatusCode.NotFound);
            await notFound.WriteStringAsync("Product not found");
            return notFound;
        }

        var product = new { Name = reader.GetString(0), Price = reader.GetDecimal(1) };
        var jsonResp = req.CreateResponse(System.Net.HttpStatusCode.OK);
        await jsonResp.WriteAsJsonAsync(product);
        return jsonResp;
    }
}

Notice that the user‑supplied id is validated, parsed to an integer, and then passed as a parameter. No string interpolation occurs.

Node.js (Azure Functions v4)

Using the mssql package with parameterized queries:

const sql = require('mssql');

async function getProduct(context, req) {
    const id = parseInt(req.params.id, 10);
    if (isNaN(id)) {
        context.res = { status: 400, body: 'Invalid product id' };
        return;
    }

    try {
        await sql.connect(process.env.SQL_CONNECTION_STRING);
        const result = await sql.query`
            SELECT Name, Price FROM Products WHERE Id = ${id}
        `; // note: the mssql template tag automatically parameterizes
        if (result.recordset.length === 0) {
            context.res = { status: 404, body: 'Product not found' };
            return;
        }
        context.res = { status: 200, body: result.recordset[0] };
    } catch (err) {
        context.log.error(err);
        context.res = { status: 500, body: 'Internal error' };
    }
}

The mssql library treats the template literal as a parameterized query, preventing injection even if the input contains SQL syntax.

Azure SQL Managed Instance – Using Entity Framework Core

When using EF Core, always use LINQ or FromSqlRaw with parameters:

var product = await _context.Products
    .FromSqlRaw("SELECT * FROM Products WHERE Id = {0}", productId)
    .AsNoTracking()
    .FirstOrDefaultAsync();

EF Core automatically substitutes the placeholder with a parameter, eliminating injection risk.

By adopting these patterns—input validation, type‑safe parsing, and parameterized APIs—you remove the root cause of SQL injection in Azure‑hosted applications.

Related CWEs: inputValidation

CWE IDNameSeverity
CWE-20Improper Input Validation HIGH
CWE-22Path Traversal HIGH
CWE-74Injection CRITICAL
CWE-77Command Injection CRITICAL
CWE-78OS Command Injection CRITICAL
CWE-79Cross-site Scripting (XSS) HIGH
CWE-89SQL Injection CRITICAL
CWE-90LDAP Injection HIGH
CWE-91XML Injection HIGH
CWE-94Code Injection CRITICAL

Frequently Asked Questions

Does middleBrick modify or patch my Azure API to fix SQL injection?
No. middleBrick only detects and reports security issues. It provides detailed findings and remediation guidance, but it does not apply fixes, patches, or blocking rules to your API or Azure resources.
Can I run middleBrick scans as part of my Azure DevOps pipeline?
Yes. middleBrick offers a GitHub Action that can be added to any CI/CD workflow. You configure it to scan a staging or production API URL, and you can set a score threshold that will fail the build if the risk exceeds your limit.