Почему использование параметризованных запросов или структуры сущностей предотвращает внедрение SQL?

Я хорошо разбираюсь в SQL-инъекциях. Это когда SQL-запрос должен быть что-то вроде

SELECT FirstName, LastName 
FROM Customers 
WHERE CustomerId = @valueFromApplication

Превращается в запрос типа

SELECT FirstName, LastName 
FROM Customers 
WHERE CustomerId = '' ; DROP DATABASE Foo --

Когда пользователь вставляет вредоносное значение в ваше приложение, веб-сайт, клиент и т. Д. Я также осознаю, что вместо того, чтобы просто удалять БД, злоумышленник может попытаться обнаружить имена таблиц и извлечь из них информацию.

Я также знаю некоторые вещи, которые помогают предотвратить это:

  1. Использование хранимых процедур, которые принимают параметры (SQL Server)
  2. Использование параметризованных SQL-запросов
  3. Использование 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.

Другие вопросы по тегам