Могу ли я защитить от SQL-инъекций, избегая одинарных кавычек и окружая пользовательский ввод одинарными кавычками? - PullRequest
127 голосов
/ 26 сентября 2008

Я понимаю, что параметризованные SQL-запросы - это оптимальный способ очистки пользовательского ввода при создании запросов, содержащих пользовательский ввод, но мне интересно, что плохого в том, чтобы принимать пользовательский ввод и экранировать любые одинарные кавычки и окружать всю строку одинарными кавычками , Вот код:

sSanitizedInput = "'" & Replace(sInput, "'", "''") & "'"

Любые одиночные кавычки, которые вводит пользователь, заменяются двойными одинарными кавычками, что исключает возможность пользователям завершать строку, поэтому все остальное, что они могут вводить, например точки с запятой, знаки процента и т. Д., Будет частью строка и на самом деле не выполняется как часть команды. Мы используем Microsoft SQL Server 2000, для которого, как мне кажется, одинарная кавычка является единственным разделителем строк и единственным способом избежать строкового разделителя, поэтому нет способа выполнить что-либо, введенное пользователем.

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

UPDATE:

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

Причина, по которой я еще не принял ни одного из ответов, заключается в том, что я до сих пор не знаю ни одного способа эффективного запуска атаки с использованием SQL-инъекций для этого кода. Несколько человек предположили, что обратная косая черта будет выходить из одной одинарной кавычки и оставлять другую для завершения строки, так что остальная часть строки будет выполнена как часть команды SQL, и я понимаю, что этот метод будет работать для внедрения SQL в база данных mySQL, но в MS SQL 2000 единственный способ (который я смог найти), чтобы избежать одиночной кавычки, это с помощью одной одиночной кавычки; обратная косая черта не сделает этого. И если нет способа остановить экранирование одинарных кавычек, ни один из оставшихся пользовательских вводов не будет выполнен, потому что все они будут восприняты как одна непрерывная строка.

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

Ответы [ 18 ]

4 голосов
/ 22 октября 2008

Ваша защита потерпит неудачу, если:

  • запрос ожидает число, а не строку
  • Существовал любой другой способ представления одиночной кавычки, в том числе:
    • escape-последовательность, такая как \ 039
    • символ Юникода

(в последнем случае это должно быть что-то, что было расширено только после того, как вы сделали замену)

4 голосов
/ 21 октября 2008

Да, это должно работать до тех пор, пока кто-то не запустит SET QUOTED_IDENTIFIER OFF и использует двойную кавычку на вас.

Редактировать: это не так просто, как не позволить злоумышленнику отключить цитируемые идентификаторы:

Драйвер ODBC для собственного клиента SQL Server и поставщик OLE DB для собственного клиента SQL Server для SQL Server автоматически устанавливают для QUOTED_IDENTIFIER значение ON при подключении. Это можно настроить в источниках данных ODBC, в атрибутах соединения ODBC или в свойствах соединения OLE DB. По умолчанию для SET QUOTED_IDENTIFIER установлено значение OFF для соединений из приложений DB-Library.

Когда создается хранимая процедура, параметры SET QUOTED_IDENTIFIER и SET ANSI_NULLS фиксируются и используются для последующих вызовов этой хранимой процедуры .

SET QUOTED_IDENTIFIER также соответствует настройке QUOTED_IDENTIFER для ALTER DATABASE.

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

Есть много способов отключить QUOTED_IDENTIFIER, если вы не будете знать об этом. По общему признанию - это не эксплойт с курящим пистолетом, который вы ищете, но это довольно большая поверхность атаки. Конечно, если вы также избежали двойных кавычек - тогда мы вернемся к тому, с чего начали. ;)

4 голосов
/ 26 сентября 2008

Если у вас есть параметризованные запросы, вы должны использовать их постоянно. Все, что требуется, - это чтобы один запрос проскользнул через сеть, и ваша БД оказалась в опасности.

1 голос
/ 26 сентября 2008

Вместо того, чтобы менять одну кавычку на (как выглядит) две одинарные кавычки, почему бы просто не заменить ее апострофом, цитатой или полностью удалить ее?

В любом случае, это что-то вроде клочья ... особенно, когда у вас есть законные вещи (например, имена), которые могут использовать одинарные кавычки ...

ПРИМЕЧАНИЕ. Ваш метод также предполагает, что каждый, кто работает над вашим приложением, всегда помнит, чтобы очистить ввод перед тем, как он попадет в базу данных, что, вероятно, в большинстве случаев нереально.

1 голос
/ 26 сентября 2008

Какой уродливый код для всей этой дезинфекции пользовательского ввода! Тогда неуклюжий StringBuilder для оператора SQL. Подготовленный метод оператора приводит к намного более чистому коду, а преимущества SQL-инъекций - действительно хорошее дополнение.

И зачем изобретать велосипед?

0 голосов
/ 26 сентября 2008

Хотя вы можете найти решение, которое работает со строками, для числовых предикатов вам также необходимо убедиться, что они передаются только в числах (простая проверка, может ли он анализироваться как int / double / decimal?).

Это много дополнительной работы.

0 голосов
/ 21 февраля 2016

Да, вы можете, если ...

После изучения темы, я думаю, что дезинфицированный ввод, как вы предложили, безопасен, но только по следующим правилам:

  1. вы никогда не позволите, чтобы строковые значения, приходящие от пользователей, становились чем-то иным, кроме строковых литералов (т.е. избегайте задания параметра конфигурации: «Введите здесь дополнительные имена / выражения столбцов SQL:»). Типы значений, отличные от строк (числа, даты, ...): преобразуйте их в их собственные типы данных и предоставьте подпрограмму для литерала SQL из каждого типа данных.

    • Операторы SQL проблематичны для проверки
  2. вы либо используете nvarchar / nchar столбцы (и префиксные строковые литералы с N) ИЛИ ограничивает значения, входящие в столбцы varchar / char, только символами ASCII (например, выбрасывает исключение при создании Оператор SQL)

    • таким образом, вы будете избегать автоматического преобразования апострофов из CHAR (700) в CHAR (39) (и, возможно, других подобных хакеров Unicode)
  3. вы всегда проверяете длину значения, чтобы она соответствовала фактической длине столбца (исключение выдается, если длиннее)

    • в SQL Server был обнаружен дефект, позволяющий обойти ошибку SQL, возникающую при усечении (приводящую к тихому усечению)
  4. вы гарантируете, что SET QUOTED_IDENTIFIER всегда ON

    • Остерегайтесь, оно вступает в силу в разбор, то есть даже в недоступных разделах кода

Соблюдая эти 4 пункта, вы должны быть в безопасности. Если вы нарушите какой-либо из них, откроется способ внедрения SQL.

0 голосов
/ 26 сентября 2008

Это может сработать, но мне это кажется немного странным. Я бы порекомендовал проверить правильность каждой строки, протестировав ее вместо регулярного выражения.

...