C# ADO.NET SQL Injection

Critical Risk SQL Injection
sql-injectioncsharpado-netdatabaseuser-input

What it is

SQL injection vulnerability in C# applications using ADO.NET where user input is directly concatenated into SQL query strings without proper parameterization or validation.

using System.Data.SqlClient;

public class UserService
{
    private string connectionString;

    public User GetUserById(string userId)
    {
        // VULNERABLE: Direct string concatenation
        string query = "SELECT * FROM users WHERE id = " + userId;

        using (SqlConnection connection = new SqlConnection(connectionString))
        {
            SqlCommand command = new SqlCommand(query, connection);
            connection.Open();

            SqlDataReader reader = command.ExecuteReader();
            if (reader.Read())
            {
                return new User
                {
                    Id = reader.GetInt32("id"),
                    Name = reader.GetString("name"),
                    Email = reader.GetString("email")
                };
            }
        }
        return null;
    }
}

// Malicious input: GetUserById("1 OR 1=1 --")
// Results in: SELECT * FROM users WHERE id = 1 OR 1=1 --
using System.Data.SqlClient;

public class UserService
{
    private string connectionString;

    public User GetUserById(int userId)
    {
        // SECURE: Using parameterized query
        string query = "SELECT * FROM users WHERE id = @userId";

        using (SqlConnection connection = new SqlConnection(connectionString))
        {
            SqlCommand command = new SqlCommand(query, connection);
            command.Parameters.AddWithValue("@userId", userId);
            connection.Open();

            SqlDataReader reader = command.ExecuteReader();
            if (reader.Read())
            {
                return new User
                {
                    Id = reader.GetInt32("id"),
                    Name = reader.GetString("name"),
                    Email = reader.GetString("email")
                };
            }
        }
        return null;
    }

    // Input validation version
    public User GetUserByIdSafe(string userIdStr)
    {
        // Validate input
        if (!int.TryParse(userIdStr, out int userId) || userId <= 0)
        {
            throw new ArgumentException("Invalid user ID");
        }

        return GetUserById(userId);
    }
}

💡 Why This Fix Works

The vulnerable code concatenates user input directly into the SQL query string, allowing SQL injection attacks. The fixed version uses parameterized queries with @userId placeholder and AddWithValue() to safely bind the parameter.

Why it happens

Direct concatenation of user input into SQL query strings is the primary cause of SQL injection in C# applications. Developers often use string concatenation or interpolation without considering the security implications.

Root causes

String Concatenation in C# SQL Queries

Direct concatenation of user input into SQL query strings is the primary cause of SQL injection in C# applications. Developers often use string concatenation or interpolation without considering the security implications.

Preview example – CSHARP
// Vulnerable approach
string query = "SELECT * FROM users WHERE id = " + userId;
SqlCommand command = new SqlCommand(query, connection);

Lack of Input Validation

C# applications that accept string parameters without proper type checking and validation are vulnerable to SQL injection attacks.

Preview example – CSHARP
// Vulnerable: No validation
public User GetUser(string userId) {
    string query = $"SELECT * FROM users WHERE id = {userId}";
    // Any input accepted
}

Fixes

1

Use Parameterized Queries with SqlParameter

Always use parameterized queries with SqlParameter or AddWithValue() to safely handle user input in C# ADO.NET applications.

View implementation – CSHARP
string query = "SELECT * FROM users WHERE id = @userId";
SqlCommand command = new SqlCommand(query, connection);
command.Parameters.AddWithValue("@userId", userId);
2

Implement Strong Type Validation

Use strongly typed parameters and validate input before processing. Convert strings to appropriate types and validate ranges.

View implementation – CSHARP
public User GetUserById(string userIdStr) {
    if (!int.TryParse(userIdStr, out int userId) || userId <= 0) {
        throw new ArgumentException("Invalid user ID");
    }
    return GetUserById(userId);
}

Detect This Vulnerability in Your Code

Sourcery automatically identifies c# ado.net sql injection and many other security issues in your codebase.