Параметризованные запросы и SQL-инъекции
↑ 4.1 ADO.NET, Npgsql и Dapper · ← Предыдущая · → Следующая
Зачем это на собесе
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 Core | FromSql($"...") интерполяция = параметры, 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-ошибок пользователю.
Практика
- Найдите в проекте конкатенацию SQL и замените параметрами.
- Реализуйте безопасную динамическую сортировку.
- Проверьте эндпоинт инструментом sqlmap на тестовой БД.
Вопросы с ответами
Почему параметры защищают от инъекций?
Значение не становится частью текста запроса: СУБД разбирает SQL отдельно и подставляет данные как значения.
Как защитить динамический ORDER BY?
Белый список колонок; имена нельзя параметризовать.
FromSql и FromSqlRaw — в чём разница?
FromSqlс интерполяцией параметризует значения,FromSqlRawпринимает строку как есть.