Как параметризованные запросы помогают в SQL-инъекции?
В обоих запросах 1 и 2 текст из текстового поля вставляется в базу данных. Какое значение параметризованного запроса здесь?
-
Передача txtTagNumber
в качестве параметра запроса
SqlCommand cmd = new SqlCommand("INSERT INTO dbo.Cars " +"VALUES(@TagNbr);" , conn);
cmd.Parameters.Add("@TagNbr", SqlDbType.Int);
cmd.Parameters["@TagNbr"].Value = txtTagNumber.Text;
-
Преобразование txtTagNumber
в целое число перед построением запроса
int tagnumber = txtTagNumber.Text.ToInt16(); /* EDITED */
INSERT into Cars values(tagnumber.Text); /* then is it the same? */
Кроме того, здесь я бы использовал проверку Регулярного выражения, чтобы остановить вставку недопустимых символов.
Ответы
Ответ 1
Параметрированные запросы выполняют правильную подстановку аргументов перед запуском SQL-запроса. Он полностью исключает возможность "грязного" ввода, изменяющего значение вашего запроса. То есть, если вход содержит SQL, он не может стать частью выполняемого, потому что SQL никогда не вводится в результирующий оператор.
Ответ 2
SQL-инъекция происходит, когда возможный параметр имеет sql внутри него, и строки не обрабатываются, как это должно быть
например:
var sqlquerywithoutcommand = "select * from mytable where rowname = '" + condition+''";
а условие - строка, исходящая от пользователя в запросе. Если состояние злонамеренное
например:
var sqlquerywithoutcommand = "select * from mytable where rowname = '" + "a' ;drop table mytable where '1=1"+"'";
вы можете запустить вредоносные скрипты.
но используя параметры, вход будет очищен от любых символов, которые могут выходить из строковых символов...
вы можете быть уверены, что вне зависимости от того, что приходит в него, не будет запускать сценарии инъекций.
используя объект команды с параметрами, которые фактически выполнил sql, будет выглядеть следующим образом:
select * from mytable where rowname = 'a'';drop table mytable where 1=1'''
В сущности он будет искать строку с rowname = a '; drop table mytable, где 1 = 1'
и не запускать оставшиеся script
Ответ 3
Представьте себе динамический запрос SQL
sqlQuery='SELECT * FROM custTable WHERE User=' + Username + ' AND
Pass=' + password
так что простой SQL-инъекцией будет просто ввести имя пользователя в виде ' OR 1=1--
Это фактически сделает SQL-запрос:
sqlQuery='SELECT * FROM custTable WHERE User='' OR 1=1-- ' AND PASS='
+ password
Это говорит, что выберите всех клиентов, где их имя пользователя пустое ('') или 1 = 1, что является логическим значением, равным true. Затем он использует -, чтобы закомментировать оставшуюся часть запроса. Таким образом, это будет просто распечатывать всю таблицу клиентов или делать с ней все, что вы хотите, при входе в систему он будет входить с привилегиями первого пользователя, которым часто может быть администратор.
Теперь параметризованные запросы делают это по-другому, с кодом вроде:
sqlQuery='SELECT * FROM custTable WHERE User=? AND Pass=?'
parameters.add("Пользователь", имя пользователя) parameters.add("Пароль", пароль)
где имя пользователя и пароль являются переменными, указывающими на связанные введенные имя пользователя и пароль
Сейчас вы можете подумать, что это ничего не меняет. Конечно, вы все еще можете просто вставить в поле имени пользователя что-то вроде Nobody OR 1 = 1 '-, эффективно сделав запрос:
sqlQuery='SELECT * FROM custTable WHERE User=Nobody OR 1=1'-- AND
Pass=?'
И это похоже на веский аргумент. Но вы были бы не правы.
Параметризованные запросы работают так, что sqlQuery отправляется как запрос, и база данных точно знает, что будет делать этот запрос, и только тогда она будет вводить имя пользователя и пароли просто в качестве значений. Это означает, что они не могут повлиять на запрос, потому что база данных уже знает, что будет делать запрос. Таким образом, в этом случае он будет искать имя пользователя "Nobody OR 1=1'--"
и пустой пароль, который должен выдаваться ложным.
Взято из
Ответ 4
Параметрированные запросы обрабатывают все - зачем идти на поводу?
С параметризованными запросами в дополнение к общей инъекции вы получаете все обрабатываемые типы данных, числа (int и float), строки (со встроенными кавычками), даты и время (без проблем с форматированием или проблем с локализацией, когда .ToString() не вызывается с инвариантной культурой, и ваш клиент переходит к машине с и неожиданным форматом даты).
Ответ 5
Параметрированные запросы позволяют клиенту передавать данные отдельно из текста запроса.
Где на большинстве свободных от текста вы будете делать валидацию + экранирование.
Конечно, параметризация не помогает против другого типа инъекций, но по мере передачи параметра отдельно, они не используются в качестве текстового запроса выполнения.
Хорошей аналогией будет "недавний" бит выполнения, используемый с большинством современных процессоров и операционной системы для защиты от переполнения буфера. Он по-прежнему позволяет переполнение буфера, но предотвращает выполнение введенных данных.
Ответ 6
Понятно, почему так хочется.
sqlQuery = "select * from users where username='+username+';"
против
sqlQuery = "select * from users where [email protected];"
Оба вышеуказанных запроса, похоже, делают то же самое. Но на самом деле этого не делают.
Первый использует вход для запроса, последний решает вопрос, но только заменяет входы так же, как и во время выполнения запроса.
Чтобы быть более ясным, значения параметров расположены где-то в стеке, где хранится память переменных и используется для поиска, когда это необходимо.
Итак, если бы мы дали ' OR '1'='1
как вход в имя пользователя, первый из динамически создавал новые запросы или запросы как часть строки запроса sql sqlQuery
, которая затем выполняется.
В то время как на том же входе последний будет искать ' OR '1'='
в поле username
таблицы users
с указанным тегом статически в строке запроса sqlQuery
Просто, чтобы консолидировать его, вы используете параметры для запроса:
SqlCommand command = new SqlCommand(sqlQuery,yourSqlConnection);
SqlParameter parameter = new SqlParameter();
parameter.ParameterName = "@username";
parameter.Value = "xyz";
command.Parameters.Add(parameter);