Почему использование параметризованных запросов или структуры сущностей предотвращает внедрение SQL?
Я хорошо разбираюсь в SQL-инъекциях. Это когда SQL-запрос должен быть что-то вроде
SELECT FirstName, LastName
FROM Customers
WHERE CustomerId = @valueFromApplication
Превращается в запрос типа
SELECT FirstName, LastName
FROM Customers
WHERE CustomerId = '' ; DROP DATABASE Foo --
Когда пользователь вставляет вредоносное значение в ваше приложение, веб-сайт, клиент и т. Д. Я также осознаю, что вместо того, чтобы просто удалять БД, злоумышленник может попытаться обнаружить имена таблиц и извлечь из них информацию.
Я также знаю некоторые вещи, которые помогают предотвратить это:
- Использование хранимых процедур, которые принимают параметры (SQL Server)
- Использование параметризованных SQL-запросов
- Использование Entity Framework / LINQ to Entities (C#, может F#?)
Как на самом деле эти вещи предотвращают внедрение SQL-кода? Почему злоумышленник не может просто передать одно и то же вредоносное значение на любой вход, который он или она уже использует, и получить такой же результат.
2 ответа
Ваш первый пример параметризован и не уязвим для внедрения SQL.
Параметризованные запросы не просто заменяются сервером со значениями (как вы могли бы сделать замену вручную @var
с value
). Они отправлены и получены именно так, как вы отправили.. с @valueFromApplication
,
Сервер проанализирует запрос.. и когда он доберется до переменной, он будет искать предоставленное значение. Если это значение '' ; DROP DATABASE Foo --
.. тогда это становится значением, которое он использует. Он не разбирает это.. он просто использует его как текст / число / независимо от типа.
Чтобы добавить о Entity Framework, он внутренне использует параметризованный запрос, поэтому он также безопасен для SQL-инъекций.
Параметры не просто заменяются встроенными в SQL - они отправляются отдельно от запроса на SQL Server.
Итак, SQL Server получает что-то вроде:
Query:
SELECT FirstName, LastName FROM Customers WHERE CustomerId = ?
Parameter 1:
'' ; DROP DATABASE Foo --
И поэтому он компилирует запрос, который проверяет клиента, у которого CustomerId буквально равен '' ; DROP DATABASE Foo --
, Значение параметра никогда не выполняется как SQL.