Может ли параметризованный оператор остановить все инъекции SQL?

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

67 голосов | спросил iceagle 22 J000000Friday11 2011, 09:31:11

12 ответов


0

Ссылки, которые я разместил в своих комментариях к вопросу, очень хорошо объясняют проблему. Ниже я кратко изложил свои чувства о том, почему проблема сохраняется:

  1. Те, кто только начинает, могут не знать о внедрении SQL.

  2. Некоторые знают о внедрении SQL, но думают, что экранирование является (единственным?) решением. Если вы быстро выполните поиск в Google по php mysql query, первая страница, которая появится, будет mysql_query , на которой есть пример, показывающий интерполяцию экранированного пользовательского ввода в запрос. Там нет упоминания (по крайней мере, что я не вижу) об использовании подготовленных утверждений вместо этого. Как уже говорили другие, существует так много учебных пособий, в которых используется интерполяция параметров, поэтому неудивительно, насколько часто они все еще используются.

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

  4. Другие знают о параметризованных утверждениях, но не используют их, потому что слышали, что они слишком медленные. Я подозреваю, что многие люди слышали о том, как невероятно медленные парамализированные утверждения, но на самом деле не проводили никакого собственного тестирования. Как отметил в своем выступлении Билл Карвин, различие в производительности редко следует использовать в качестве фактора при рассмотрении вопроса об использовании подготовленных утверждений. Преимущества подготовить один раз, выполнить много , часто кажутся забытыми, равно как и улучшения в области безопасности и удобства сопровождения кода.

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

  6. Ложное чувство безопасности при использовании ORM. ORM по-прежнему допускают интерполяцию частей операторов SQL - см. 5.

  7. Программирование - большая и сложная тема, управление базами данных - большая и сложная тема, безопасность - большая и сложная тема. Разработка защищенного приложения базы данных не легка - даже опытные разработчики могут быть пойманы.

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

ответил Mike 22 J000000Friday11 2011, 12:39:45
0

Когда в статьях говорится о параметризованных запросах, останавливающих атаки SQL, они на самом деле не объясняют почему, часто это так: «Да, не спрашивайте почему» - возможно, потому, что они сами не знают. Верным признаком плохого воспитателя является тот, который не может признать, что они ничего не знают. Но я отвлекся. Когда я говорю, что совершенно понятно, что запутаться - это просто. Представьте себе динамический запрос 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("User", username)
parameters.add("Pass", password)

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

Теперь вы можете подумать, что это ничего не меняет. Конечно, вы все еще можете просто вставить в поле имени пользователя что-то вроде Nobody OR 1 = 1 '-, эффективно сделав запрос:

sqlQuery='SELECT * FROM custTable WHERE User=Nobody OR 1=1'-- AND Pass=?'

И это может показаться обоснованным аргументом. Но вы были бы неправы.

Способ параметризованных запросов заключается в том, что sqlQuery отправляется как запрос, и база данных точно знает, что будет делать этот запрос, и только тогда она будет вставлять имя пользователя и пароли просто в качестве значений. Это означает, что они не могут повлиять на запрос, поскольку база данных уже знает, что будет делать запрос. Таким образом, в этом случае он будет искать имя пользователя «Nobody OR 1 = 1 '-» и пустой пароль, который должен выдаваться ложным.

Это не полное решение, и проверка входных данных по-прежнему должна выполняться, поскольку это не повлияет на другие проблемы, такие как атаки XSS, поскольку вы все равно можете поместить javascript в базу данных. Затем, если это будет считано на странице, он будет отображаться как обычный javascript, в зависимости от проверки вывода. Поэтому лучше всего по-прежнему использовать проверку ввода, но использовать параметризованные запросы или хранимые процедуры, чтобы остановить любые атаки SQL.

ответил Josip Ivic 9 +03002015-10-09T11:34:44+03:00312015bEurope/MoscowFri, 09 Oct 2015 11:34:44 +0300 2015, 11:34:44
0

Хорошо, хороший вопрос. Ответ скорее стохастический, чем детерминированный, и я попытаюсь объяснить свое мнение на небольшом примере.

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

Рассмотрим следующую хранимую процедуру SQL Server, которая получит строку пользователя из таблицы «Пользователи»:

create procedure getUser
 @name varchar(20)
,@pass varchar(20)
as
declare @sql as nvarchar(512)
set @sql = 'select usrID, usrUName, usrFullName, usrRoleID '+
           'from Users '+
           'where usrUName = '''[email protected]+''' and usrPass = '''[email protected]+''''
execute(@sql)

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

DECLARE @RC int
DECLARE @name varchar(20)
DECLARE @pass varchar(20)

EXECUTE @RC = [dbo].[getUser] 
   @name = 'admin'
  ,@pass = '[email protected]@ssw0rd!!'
GO

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

DECLARE @RC int
DECLARE @name varchar(20)
DECLARE @pass varchar(20)

EXECUTE @RC = [TestDB].[dbo].[getUser] 
   @name = 'admin'
  ,@pass = 'any'' OR 1=1 --'
GO

Вышеуказанные параметры будут переданы в качестве аргументов хранимой процедуре, а команда SQL, которая в конечном итоге будет выполнена:

select usrID, usrUName, usrFullName, usrRoleID 
from Users 
where usrUName = 'admin' and usrPass = 'any' OR 1=1 --'

.. который вернет все строки от пользователей

Проблема в том, что даже мы следуем принципу «Создаем хранимую процедуру и передаем поля для поиска в качестве параметров», SQLi все еще выполняется. Это потому, что мы просто копируем нашу плохую практику программирования в хранимую процедуру. Решение проблемы - переписать нашу хранимую процедуру следующим образом:

alter procedure getUser
 @name varchar(20)
,@pass varchar(20)
as
select usrID, usrUName, usrFullName, usrRoleID 
from Users 
where usrUName = @name and usrPass = @pass

Я пытаюсь сказать, что разработчики должны сначала узнать, что такое атака SQLi и как ее можно выполнить, а затем соответствующим образом защитить свой код. Слепое следование «лучшим практикам» не всегда является более безопасным способом ... и, возможно, именно поэтому у нас так много «лучших практик» - неудачи!

ответил Andreas Venieris 10 +03002015-10-10T23:10:13+03:00312015bEurope/MoscowSat, 10 Oct 2015 23:10:13 +0300 2015, 23:10:13
0

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

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

  

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

Да, здесь главное - это образование, а основы унаследованного кода. Многие учебники используют экранирование, и, к сожалению, их нелегко удалить из Интернета.

ответил kelunik 9 +03002015-10-09T11:22:23+03:00312015bEurope/MoscowFri, 09 Oct 2015 11:22:23 +0300 2015, 11:22:23
0

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

Мои два цента.

ответил Derek 14 +03002015-10-14T19:17:23+03:00312015bEurope/MoscowWed, 14 Oct 2015 19:17:23 +0300 2015, 19:17:23
0

Я бы не сказал "тупой".

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

ответил Markus Winand 22 J000000Friday11 2011, 09:37:38
0

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

ответил evil otto 22 J000000Friday11 2011, 10:10:20
0
  

Может ли параметризованный оператор остановить все инъекции SQL?

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

Именно поэтому я создал свою оболочку Mysql для PHP, которая поддерживает большинство литералов, которые можно динамически добавлять к запросу, включая массивы и идентификаторы.

  

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

Как вы можете видеть, в действительности просто невозможно все задать параметры ваших запросов, даже если вы не глупы.

ответил Your Common Sense 9 +03002015-10-09T12:47:44+03:00312015bEurope/MoscowFri, 09 Oct 2015 12:47:44 +0300 2015, 12:47:44
0

Сначала я отвечу на ваш первый вопрос. Да, насколько я знаю, с помощью параметризованных запросов внедрение SQL больше не будет возможным. Что касается ваших следующих вопросов, я не уверен и могу только высказать вам свое мнение о причинах:

Я думаю, что проще «просто» написать строку SQL-запроса, объединив несколько различных частей (возможно, даже зависящих от некоторых логических проверок) вместе со значениями, которые нужно вставить. Это просто создает запрос и выполняет его. Другое преимущество заключается в том, что вы можете напечатать (echo, output или что-то еще) строку запроса sql, а затем использовать эту строку для ручного запроса к ядру базы данных.

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

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

С наилучшими пожеланиями,

Вставка

ответил TomS 14 +03002015-10-14T16:44:57+03:00312015bEurope/MoscowWed, 14 Oct 2015 16:44:57 +0300 2015, 16:44:57
0

Чтобы защитить приложение от внедрения SQL, выполните следующие действия:

Шаг 1. Ограничьте ввод. Шаг 2. Используйте параметры с хранимыми процедурами. Шаг 3. Используйте параметры с динамическим SQL.

См. http://msdn.microsoft.com/en-us/. библиотека /ff648339.aspx

ответил Fahad Hussain 22 J000000Friday11 2011, 09:37:47
0

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

В некоторых конкретных случаях этого недостаточно. Во многих СУБД можно динамически выполнять SQL с помощью хранимых процедур, внося недостаток внедрения SQL на уровне СУБД. Вызов такой хранимой процедуры с использованием параметризованных запросов не предотвратит использование SQL-инъекции в процедуре. Другой пример можно увидеть в этом сообщении в блоге . р>

Чаще всего разработчики используют функциональность неправильно. Обычно код выглядит примерно так, если все сделано правильно:

db.parameterize_query("select foo from bar where baz = '?'", user_input)

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

db.parameterize_query("select foo from bar where baz = '" + user_input + "'")

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

ответил Daniel Crowley 21 J0000006Europe/Moscow 2016, 19:45:50
0

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

CREATE PROCEDURE show_current_orders
(@name varchar(400) = NULL)
AS
DECLARE @sql nvarchar(4000)
SELECT @sql = ‘SELECT id_num, searchstring FROM searchorders WHERE ‘ +
‘searchstring = ‘’’ + @name + ‘’’’;
EXEC (@sql)
GO

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

ответил Hadid Graphics 15 PM00000080000001031 2018, 20:18:10

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132