Параметризованные запросы и SQL-инъекции

↑ 4.1 ADO.NET, Npgsql и Dapper · ← Предыдущая · → Следующая

Обязательно~3 мин чтенияУровень: middle

Зачем это на собесе

SQL-инъекция — обязательная тема безопасности. Нужно объяснить, почему параметры защищают, и где всё же можно ошибиться.

Объяснение

Инъекция возникает, когда пользовательские данные подставляются в текст SQL как код.

// Уязвимо: name = "x'; drop table users; --"
var sql = $"select * from users where name = '{name}'";
 
// Безопасно: значение передаётся отдельно от текста запроса
await using var cmd = new NpgsqlCommand("select * from users where name = @name", conn);
cmd.Parameters.AddWithValue("name", name);

С параметрами текст запроса и данные идут отдельно (protocol-level), поэтому БД никогда не трактует значение как SQL; план запроса при этом кэшируется.

СитуацияКак безопасно
Значенияпараметры
Имена таблиц/колонок, ORDER BYбелый список допустимых значений
LIKEпараметр + экранирование %, _
Списки IN= ANY(@ids) (PostgreSQL), Dapper раскрывает коллекции
EF CoreFromSql($"...") интерполяция = параметры, FromSqlRaw с конкатенацией — уязвим
// EF Core: безопасно, интерполяция превращается в параметры
db.Users.FromSql($"select * from users where name = {name}");
// Уязвимо
db.Users.FromSqlRaw("select * from users where name = '" + name + "'");

Нюансы и подводные камни

  • Динамический ORDER BY — частая дыра: сопоставляйте вход с enum/словарём.
  • Хранимая процедура с динамическим SQL внутри тоже уязвима.
  • Экранирование кавычек вручную ненадёжно.
  • Минимальные права учётной записи БД снижают ущерб.
  • Не показывайте текст SQL-ошибок пользователю.

Практика

  1. Найдите в проекте конкатенацию SQL и замените параметрами.
  2. Реализуйте безопасную динамическую сортировку.
  3. Проверьте эндпоинт инструментом sqlmap на тестовой БД.

Вопросы с ответами

Связанные темы