Я понимаю, что параметризованные SQL-запросы являются оптимальным способом дезинфекции пользовательского ввода при построении запросов, содержащих пользовательский ввод, но мне интересно, что не так с вводом пользователя и экранированием одинарных кавычек и окружением всей строки одинарными кавычками. Вот код:
sSanitizedInput = "'" & Replace(sInput, "'", "''") & "'"
Любая одинарная кавычка, которую вводит пользователь, заменяется двойными одинарными кавычками, что исключает возможность пользователям заканчивать строку, поэтому все, что они могут ввести, например, точки с запятой, знаки процента и т. Д., Все будет частью строки и фактически не выполняется как часть команды.
Мы используем Microsoft SQL Server 2000, для которого, как я считаю, одинарная кавычка является единственным разделителем строк и единственным способом избежать разделителя строк, поэтому нет возможности выполнить что-либо, что вводит пользователь.
Я не вижу никакого способа противодействовать этому с помощью SQL-инъекции, но я понимаю, что если бы это было столь же надежно, как мне кажется, кто-то другой уже подумал бы об этом, и это было бы обычной практикой.
Что не так с этим кодом? Есть ли способ обойти эту технику очистки при атаке с использованием SQL-инъекции? Был бы очень полезен образец пользовательского ввода, использующего эту технику.
ОБНОВИТЬ:
Я до сих пор не знаю, как эффективно запустить атаку SQL-инъекции против этого кода. Некоторые люди предположили, что обратная косая черта будет экранировать одну одинарную кавычку и оставить другую для завершения строки, чтобы остальная часть строки выполнялась как часть команды SQL, и я понимаю, что этот метод будет работать для внедрения SQL в база данных MySQL, но в SQL Server 2000 единственный способ (который мне удалось найти) избежать одинарной кавычки - это использовать другую одинарную кавычку; обратная косая черта этого не сделает.
И если нет способа остановить экранирование одинарной кавычки, ни один из остальных вводимых пользователем данных не будет выполнен, потому что все они будут приняты как одна непрерывная строка.
Я понимаю, что есть более эффективные способы дезинфекции ввода, но мне действительно больше интересно узнать, почему метод, который я предоставил выше, не работает. Если кто-то знает какой-либо конкретный способ организовать атаку SQL-инъекции против этого метода очистки, я хотел бы его увидеть.
Ответы:
Во-первых, это просто плохая практика. Проверка ввода всегда необходима, но она также всегда ненадежна.
Что еще хуже, проверка черного списка всегда проблематична, гораздо лучше явно и строго определить, какие значения / форматы вы принимаете. По общему признанию, это не всегда возможно, но до некоторой степени это необходимо делать всегда.
Некоторые исследовательские работы по теме:
Дело в том, что любой черный список (и слишком разрешительные белые списки) можно обойти. Последняя ссылка на мою статью показывает ситуации, когда можно обойти даже экранирование кавычек.
Даже если эти ситуации к вам не относятся, это все равно плохая идея. Более того, если ваше приложение не является тривиально маленьким, вам придется иметь дело с обслуживанием и, возможно, с определенным уровнем управления: как обеспечить, чтобы оно выполнялось правильно и везде и всегда?
Как это сделать:
источник
sp_executesql
вместоEXEC
). То есть вы можете динамически генерировать свой оператор SQL, если ни один из составных текстов не исходит от пользователя. Это также дает преимущества в производительности;sp_executesql
поддерживает кеширование.Хорошо, этот ответ будет относиться к обновлению вопроса:
Теперь, помимо экранирования обратной косой черты MySQL - и с учетом того, что мы на самом деле говорим о MSSQL, на самом деле существует 3 возможных способа SQL-инъекции вашего кода.
Учтите, что не все они будут действительны всегда и очень зависят от вашего фактического кода вокруг него:
Затем вы получаете имя пользователя, экранированное, а затем обрезанное до 20 символов. Проблема здесь - я вставлю свою цитату в 20-й символ (например, после 19 а), а ваша экранирующая цитата будет обрезана (в 21-м символе). Тогда SQL
sSQL = "select * from USERS where username = '" + username + "' and password = '" + password + "'"
в сочетании с вышеупомянутым искаженным именем пользователя приведет к тому, что пароль уже будет вне кавычек и будет просто содержать полезную нагрузку напрямую.
3. Контрабанда Unicode - в определенных ситуациях можно передать высокоуровневый символ Unicode, который выглядит как цитата, но не является - до тех пор, пока он не попадает в базу данных, где внезапно оказывается . Поскольку это не цитата, когда вы ее проверяете, все пройдет легко ... Подробнее см. В моем предыдущем ответе и ссылку на исходное исследование.
источник
В двух словах: никогда не выполняйте экранирование запросов. Вы обязательно ошибетесь. Вместо этого используйте параметризованные запросы или, если по какой-то причине вы не можете этого сделать, используйте существующую библиотеку, которая сделает это за вас. Нет причин делать это самому.
источник
Я понимаю, что это прошло много времени после того, как вопрос был задан, но ...
Один из способов начать атаку на процедуру «цитировать аргумент» - это усечение строки. Согласно MSDN, в SQL Server 2000 SP4 (и SQL Server 2005 SP1) слишком длинная строка будет незаметно усечена.
Когда вы заключаете строку в кавычки, она увеличивается в размере. Каждый апостроф повторяется. Затем это можно использовать для выталкивания частей SQL за пределы буфера. Таким образом, вы можете эффективно обрезать части предложения where.
Это, вероятно, было бы в основном полезно в сценарии страницы «администратор пользователя», где вы могли бы злоупотребить оператором «update», чтобы не выполнять все проверки, которые он должен был делать.
Поэтому, если вы решили заключить в кавычки все аргументы, убедитесь, что вы знаете, что происходит с размерами строк, и проследите за тем, чтобы вы не столкнулись с усечением.
Я бы рекомендовал использовать параметры. Всегда. Хотел бы я обеспечить это в базе данных. И как побочный эффект, вы с большей вероятностью получите более качественные обращения к кешу, потому что большинство операторов выглядят одинаково. (Это определенно было верно для Oracle 8)
источник
Я использовал эту технику при работе с функцией «расширенного поиска», когда создание запроса с нуля было единственным жизнеспособным ответом. (Пример: позволить пользователю искать продукты на основе неограниченного набора ограничений на атрибуты продукта, отображая столбцы и их разрешенные значения в качестве элементов управления графическим интерфейсом, чтобы снизить порог обучения для пользователей.)
Само по себе это безопасно AFAIK. Однако, как заметил другой ответчик, вам также может потребоваться иметь дело с экранированием обратного пространства (хотя, по крайней мере, не при передаче запроса на SQL Server с использованием ADO или ADO.NET - не может ручаться за все базы данных или технологии).
Загвоздка в том, что вы действительно должны быть уверены, какие строки содержат вводимые пользователем данные (всегда потенциально вредоносные) и какие строки являются действительными SQL-запросами. Одна из ловушек - если вы используете значения из базы данных - были ли эти значения изначально предоставлены пользователем? Если это так, их также необходимо избежать. Мой ответ - попытаться провести дезинфекцию как можно позже (но не позже!) При построении SQL-запроса.
Однако в большинстве случаев привязка параметров - это лучший способ - это просто проще.
источник
Входная санитария - это не то, что вам нужно наполовину. Используй всю свою задницу. Используйте регулярные выражения в текстовых полях. Попробуйте преобразовать свои числа в правильный числовой тип и сообщить об ошибке проверки, если это не сработает. Очень легко искать шаблоны атак во входных данных, например '-. Предположим, что все действия пользователя враждебны.
источник
flavors
этой странице).В любом случае это плохая идея, как вы, кажется, знаете.
А как насчет экранирования кавычек в такой строке: \ '
Ваша замена приведет к: \ ''
Если обратная косая черта выходит за пределы первой кавычки, значит, вторая кавычка заканчивает строку.
источник
Простой ответ: иногда это срабатывает, но не всегда. Вы хотите использовать проверку в белом списке для всего, что вы делаете, но я понимаю, что это не всегда возможно, поэтому вы вынуждены использовать черный список с наилучшими предположениями. Точно так же вы хотите использовать параметризованные хранимые процедуры во всем , но, опять же, это не всегда возможно, поэтому вы вынуждены использовать sp_execute с параметрами.
Есть способы обойти любой полезный черный список, который вы можете придумать (и некоторые белые списки тоже).
Приличная запись здесь: http://www.owasp.org/index.php/Top_10_2007-A2
Если вам нужно сделать это как быстрое исправление, чтобы дать вам время установить настоящий, сделайте это. Но не думай, что ты в безопасности.
источник
Это можно сделать двумя способами, без исключений, чтобы обезопасить себя от SQL-инъекций; подготовленные операторы или параметризованные хранимые процедуры.
источник
Если у вас есть параметризованные запросы, вы должны использовать их всегда. Достаточно одного запроса, чтобы проскользнуть через сеть, и ваша БД окажется в опасности.
источник
Да, это должно работать до тех пор, пока кто-то не запустит SET QUOTED_IDENTIFIER OFF и не использует двойные кавычки для вас.
Изменить: это не так просто, как запретить злоумышленнику отключать цитируемые идентификаторы:
Существует множество способов отключения QUOTED_IDENTIFIER без вашего ведома. По общему признанию - это не тот эксплойт с дымящимся пистолетом, который вы ищете, но это довольно большая поверхность для атаки. Конечно, если вы также избежали двойных кавычек - тогда мы вернулись к тому, с чего начали. ;)
источник
Ваша защита не сработает, если:
(в последнем случае это должно быть что-то, что было расширено только после того, как вы сделали свою замену)
источник
Патрик, вы добавляете одинарные кавычки вокруг ВСЕХ входных данных, даже числовых? Если у вас есть числовой ввод, но вы не заключаете его в одинарные кавычки, то у вас есть доступ.
источник
Каким уродливым кодом была бы вся эта дезинфекция пользовательского ввода! Затем неуклюжий StringBuilder для оператора SQL. Метод подготовленного оператора приводит к гораздо более чистому коду, а преимущества SQL Injection - действительно хорошее дополнение.
И зачем изобретать велосипед?
источник
Вместо того, чтобы заменять одинарную кавычку (как выглядит) двумя одинарными кавычками, почему бы просто не заменить ее на апостроф, цитату или полностью не удалить?
В любом случае, это немного путаница ... особенно когда у вас есть законные вещи (например, имена), которые могут использовать одинарные кавычки ...
ПРИМЕЧАНИЕ. Ваш метод также предполагает, что все, кто работает с вашим приложением, всегда помнят о необходимости дезинфицировать ввод до того, как он попадет в базу данных, что, вероятно, в большинстве случаев нереально.
источник
Хотя вы можете найти решение, которое работает для строк, для числовых предикатов вам также необходимо убедиться, что они передаются только в числах (простая проверка: можно ли его проанализировать как int / double / decimal?).
Это много лишней работы.
источник
Это может сработать, но мне это кажется немного странным. Я бы рекомендовал проверять правильность каждой строки, проверяя ее на регулярное выражение.
источник
Да, можно, если ...
После изучения темы я считаю, что обработка вводимых данных, как вы предложили, безопасна, но только при соблюдении следующих правил:
вы никогда не позволяете строковым значениям, поступающим от пользователей, становиться ничем иным, кроме строковых литералов (т.е. избегайте указания параметра конфигурации: «Введите сюда дополнительные имена / выражения столбцов SQL:»). Типы значений, отличные от строк (числа, даты, ...): преобразуйте их в их собственные типы данных и предоставьте процедуру для литерала SQL из каждого типа данных.
вы либо используете
nvarchar
/nchar
columns (и префикс строковых литералов сN
), либо ограничиваете значения, входящие вvarchar
/char
columns только в символы ASCII (например, генерируете исключение при создании оператора SQL)вы всегда проверяете длину значения, чтобы она соответствовала фактической длине столбца (исключение, если оно больше)
вы гарантируете, что
SET QUOTED_IDENTIFIER
всегдаON
Соблюдая эти 4 пункта, вы должны быть в безопасности. Если вы нарушите какой-либо из них, откроется путь для SQL-инъекции.
источник