Реальные примеры проблем внедрения SQL для SQL Server, использующих только замену в качестве предупреждения? - PullRequest
3 голосов
/ 19 декабря 2009

Я знаю, что динамические запросы SQL плохие из-за проблем с SQL-инъекцией (а также из-за проблем производительности и других проблем) Я также знаю, что параметризованные запросы предпочтительнее, чтобы избежать проблем с внедрением, мы все это знаем.

Но мой клиент все еще очень упрям ​​и думает, что просто

var UserName=Request.Form["UserName"];
   UserName=UserName.Replace("'","''");
   SQL="SELECT * FROM Users where UserName='" + UserName + "'";

Требуется защита от проблем с внедрением SQL (SQL Server (только), а не mysql).

Кто-нибудь может дать мне реальный пример атаки SQL-инъекцией, который все еще может пройти через случай замены выше? Угадайте, есть проблемы с символами юникода?

Мне нужны реальные примеры атак, которые все еще могут пройти через эту простую замену.

Мой вопрос касается только SQL Server, и я знаю, что в MySQL есть некоторые проблемы с символом \.

Ответы [ 7 ]

3 голосов
/ 19 декабря 2009

Это не будет работать, если вы используете NUMBER s.

"SELECT * FROM data WHERE id = " + a_variable + ";"

с помощью

1; пользователи DROP TABLE

Дает вам

SELECT * FROM DATA WHERE id=1;DROP TABLE users;

Взгляните на

EDIT

Посмотрите на это. Это очень близко к вашему вопросу

Проверка SQL-инъекции

2 голосов
/ 19 декабря 2009

У меня возникли проблемы с пониманием объема замены. Ваша оригинальная линия:

SQL=SQL.Replace("''","'");

Поскольку вы применяете его к имени переменной SQL, я предполагаю, что вы заменяете все вхождения '' на 'во всем операторе.

Это не может быть правильно: рассмотрите это утверждение:

SELECT * FROM tab WHERE col = '<input value goes here>'

Теперь, если пустая строка, оператор будет:

SELECT * FROM tab WHERE col = ''

... и после SQL.Replace ("''", "'") оно станет:

SELECT * FROM tab WHERE col = '

Как видите, он оставит висящую одинарную кавычку и приведет к синтаксической ошибке.

Теперь давайте предположим, что вы намеревались написать SQL.Replace ("'", "' '"), тогда заменяемое выражение станет:

SELECT * FROM tab WHERE col = ''''

Хотя синтаксически правильно, вы теперь сравниваете col с буквальной одинарной кавычкой (так как '' внутри внешних одинарных кавычек, которые разделяют буквальную строку, будет вычисляться как буквальная одинарная кавычка). Так что это тоже не может быть правдой.

Это наводит меня на мысль, что вы можете делать что-то вроде этого:

SQL = "SELECT * FROM tab WHERE col = '" & ParamValue.Replace("'", "''") & "'"

Теперь, как уже указывалось на предыдущем постере, этот подход не работает для числа. Или, на самом деле, этот подход применим только в том случае, если вы хотите обработать ввод внутри строкового литерала в зачете SQL.

Есть, по крайней мере, случай, когда это может быть проблематично. Если параметр QUOTED_IDENTIFIER серверов MS SQL отключен, литеральные строки также могут быть заключены в двойные кавычки. В этом случае пользовательские значения, вводящие двойные кавычки, приведут к тем же проблемам, что и у вас с одинарными строками. Кроме того, стандартная escape-последовательность для одной кавычки (две одинарные кавычки) больше не работает !!

Просто рассмотрите этот фрагмент:

SET QUOTED_IDENTIFIER OFF
SELECT " "" '' "

Это дает результат:

" ''

Так что, по крайней мере, процесс экранирования должен отличаться в зависимости от того, разделяете ли вы строки одинарными или двойными кавычками. Это может не показаться большой проблемой, так как QUOTED_IDENTIFIER включен по умолчанию, но все же. См:

http://msdn.microsoft.com/en-us/library/ms174393.aspx

2 голосов
/ 19 декабря 2009

Пожалуйста, введите ваш возраст: 21; отбросить пользователей таблицы;

SELECT * FROM table where age = 21; drop table users;

ouchies

1 голос
/ 19 декабря 2009

Пожалуйста, посмотрите этот мультфильм XKCD:

Маленькие столики Бобби

0 голосов
/ 19 декабря 2009

Цитировать из принятого ответа на вопрос SO " Доказательство SQL-инъекции ":

[...] нет ничего небезопасного в правильно цитируемой инструкции SQL.

Итак, если

  • Строковые данные правильно экранируются с помощью Replace("'","''") (и ваш SQL использует одинарные кавычки вокруг строк, см. Ответ Роланда w.r.t. QUOTED_IDENTIFIER),

  • числовые данные поступают из числовых переменных и должным образом (т.е. не зависят от культуры) преобразуются в строку, а

  • данные datetime поступают из переменных datetime и должным образом преобразуются в строку (т. Е. В один из форматов, не зависящих от культуры, принятых SQL Server).

тогда я не могу придумать, каким образом SQL-инъекция могла бы быть сделана в SQL Server.

Unicode, который вы упомянули в своем вопросе, был MySQL bug . Учет таких проблем в вашем коде обеспечивает уровень безопасности extra (что обычно хорошо). Прежде всего , ядро ​​базы данных должно убедиться, что правильно цитируемый SQL-оператор не является угрозой безопасности.

0 голосов
/ 19 декабря 2009

Ваш клиент правильный.

SQL = SQL.Replace("'","''");

остановит все инъекционные атаки.

Причина, по которой это не считается безопасным, заключается в том, что легко пропустить одну строку целиком.

0 голосов
/ 19 декабря 2009

До сих пор ответы были нацелены на запрос условия с числовыми типами данных и не имели одинарных кавычек в предложении WHERE.

Однако в MSSQL * (по крайней мере, в версии 2005) это работает, даже если id, скажем, целочисленный тип:

"SELECT * FROM data WHERE id = '" + a_variable + "';"

Мне неприятно это говорить, но если не используется хранимая процедура (код, который вызывает EXECUTE, EXEC или sp_executesql) или в предложениях WHERE не используются кавычки для числовых типов, замена одинарных кавычек практически исключает возможность SQL-инъекции. Я не могу быть уверен на 100%, и я действительно надеюсь, что кто-то может доказать, что я неправ.

Я упомянул хранимую процедуру из-за инъекции второго уровня, о которой я только недавно читал. Смотрите пост SO здесь Что такое SQL-инъекция второго уровня .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...