Могу ли я защитить от 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 ]

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

Прежде всего, это просто плохая практика. Проверка ввода всегда необходима, но она также всегда сомнительна.
Что еще хуже, проверка черного списка всегда проблематична, гораздо лучше четко и строго определить, какие значения / форматы вы принимаете. По общему признанию, это не всегда возможно - но в некоторой степени это всегда должно быть сделано.
Некоторые исследовательские работы на эту тему:

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

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

Правильный способ сделать это:

  • Проверка белого списка: тип, длина, формат или допустимые значения
  • Если вы хотите занести в черный список, продолжайте. Экранирование цитаты - это хорошо, но в контексте других смягчений.
  • Использование объектов Command и Parameter для предварительной обработки и проверки
  • Вызов только параметризованных запросов.
  • Еще лучше, используйте исключительно хранимые процедуры.
  • Избегайте использования динамического SQL и не используйте конкатенацию строк для построения запросов.
  • Если вы используете SP, вы также можете ограничить разрешения в базе данных для выполнения только необходимых SP, а не для прямого доступа к таблицам.
  • Вы также можете легко проверить, что вся кодовая база обращается к БД только через SP ...
39 голосов
/ 18 декабря 2008

Хорошо, этот ответ будет касаться обновления вопроса:

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

Теперь, кроме экранирования обратной косой черты MySQL - и принимая во внимание то, что мы на самом деле говорим о MSSQL, на самом деле есть 3 возможных способа SQL-инъекции вашего кода

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

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

  1. SQL-инъекция второго порядка - если запрос SQL перестраивается на основе данных, извлеченных из базы данных после экранирования , данные объединяются без экранирования и могут быть косвенно введены в SQL. Смотри
  2. Усечение строки - (немного сложнее) - Сценарий: у вас есть два поля, скажем, имя пользователя и пароль, и SQL объединяет оба из них. И оба поля (или только первое) имеют жесткое ограничение по длине. Например, имя пользователя ограничено 20 символами. Скажем, у вас есть этот код:
username = left(Replace(sInput, "'", "''"), 20)

Тогда что вы получаете - это имя пользователя, экранированное, а затем урезанное до 20 символов. Проблема здесь - я вставлю свою цитату в 20-й символ (например, после 19-ти), и ваша экранирующая цитата будет обрезана (в 21-м символе). Тогда SQL

sSQL = "select * from USERS where username = '" + username + "'  and password = '" + password + "'"

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

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

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

17 голосов
/ 19 февраля 2009

Я понимаю, что прошло много времени после того, как вопрос был задан, но ..

Один из способов начать атаку на процедуру 'quote the аргумент' - это усечение строки. Согласно MSDN, в SQL Server 2000 с пакетом обновления 4 (и SQL Server 2005 с пакетом обновления 1) слишком длинная строка будет тихо усечена.

Когда вы цитируете строку, строка увеличивается в размере. Каждый апостроф повторяется. Затем его можно использовать для выталкивания частей SQL за пределы буфера. Таким образом, вы можете эффективно обрезать части предложения where.

Это, вероятно, было бы в основном полезно в сценарии страницы 'user admin', где вы могли бы использовать оператор update, чтобы не выполнять все проверки, которые он должен был сделать.

Так что, если вы решите процитировать все аргументы, убедитесь, что вы знаете, что происходит с размерами строк, и проследите, чтобы вы не сталкивались с усечением.

Я бы порекомендовал идти с параметрами. Всегда. Просто хочу, чтобы я мог применить это в базе данных. И как побочный эффект, вы, скорее всего, получите лучшие попадания в кэш, потому что большинство операторов выглядят одинаково. (Это было верно для Oracle 8)

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

Я использовал эту технику, когда имел дело с функциональностью «расширенный поиск», где создание запроса с нуля было единственным жизнеспособным ответом. (Пример: пользователь может искать товары на основе неограниченного набора ограничений на атрибуты товара, отображая столбцы и их разрешенные значения в качестве элементов управления графическим интерфейсом для снижения порога обучения для пользователей.)

Само по себе это безопасно AFAIK. Однако, как отметил другой автор, вам также может потребоваться экранирование backspace (хотя и не при передаче запроса на SQL Server с использованием ADO или ADO.NET, по крайней мере - нельзя поручиться за все базы данных или технологии).

Загвоздка в том, что вы действительно должны быть уверены, какие строки содержат пользовательский ввод (всегда потенциально вредоносный) и какие строки являются допустимыми запросами SQL. Одна из ловушек - если вы используете значения из базы данных - были ли эти значения изначально предоставлены пользователем? Если так, они также должны быть спасены. Мой ответ - попытаться очистить как можно позже (но не позже!) При построении SQL-запроса.

Однако, в большинстве случаев, привязка параметров - это путь, он просто проще.

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

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

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

В любом случае это плохая идея, как вы, кажется, знаете.

Как насчет экранирования кавычки в строке, например: \ '

Ваша замена приведет к: \ ''

Если обратная косая черта экранирует первую кавычку, то вторая кавычка завершила строку.

5 голосов
/ 29 сентября 2008

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

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

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

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

Приличная рецензия здесь: http://www.owasp.org/index.php/Top_10_2007-A2

Если вам нужно сделать это как быстрое решение, чтобы дать вам время, чтобы получить реальное решение на месте, сделайте это. Но не думайте, что вы в безопасности.

4 голосов
/ 14 ноября 2008

Патрик, вы добавляете одинарные кавычки вокруг ВСЕГО ввода, даже числового? Если у вас есть числовой ввод, но вы не заключаете в него одинарные кавычки, значит, у вас есть выдержка.

...