Как защититься от SQL-инъекций в веб-приложении?

«Как защититься от SQL-инъекций в веб-приложении?» — вопрос из категории Безопасность, который задают на 25% собеседований C# Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Защита от SQL-инъекций строится на одном фундаментальном принципе: никогда не доверять пользовательскому вводу и не вставлять его напрямую в SQL-запрос.

Основной метод: Параметризованные запросы (Prepared Statements) Это самый надежный способ. СУБД четко разделяет код запроса и данные.

// УЯЗВИМЫЙ КОД (НИКОГДА ТАК НЕ ДЕЛАЙТЕ)
string userInput = Request.Form["username"];
string query = $"SELECT * FROM Users WHERE Name = '{userInput}'";
// Если userInput = "admin' OR '1'='1", запрос сломает логику.

// ЗАЩИЩЕННЫЙ КОД с параметрами
string safeQuery = "SELECT * FROM Users WHERE Name = @UserName";
using (SqlCommand command = new SqlCommand(safeQuery, connection))
{
    // Параметр @UserName будет обработан как ДАННЫЕ, а не как часть кода SQL.
    command.Parameters.AddWithValue("@UserName", userInput);
    // ... выполнение команды
}

Дополнительные и сопутствующие меры:

  1. ORM (Entity Framework, Dapper): Современные ORM по умолчанию используют параметризацию.
    // Entity Framework Core - инъекция невозможна
    var user = await dbContext.Users.FirstOrDefaultAsync(u => u.Name == userInput);
  2. Принцип наименьших привилегий: У учетной записи приложения в БД должны быть минимально необходимые права (обычно только SELECT, INSERT, UPDATE, DELETE для конкретных таблиц, но не DROP, TRUNCATE и т.д.).
  3. Валидация и санитизация ввода: Отклоняйте входные данные, не соответствующие ожидаемому формату (например, в поле "телефон" должны быть только цифры). Это не заменяет параметризацию, но является хорошей практикой.
  4. Хранимые процедуры: Эффективны только если вы передаете параметры в них, а не конкатенируете строки внутри самой процедуры.

Итог: Всегда используйте параметризованные запросы или ORM. Экранирование символов — ненадежный и устаревший метод.