Подтвердить что ты не робот

Неинтерфейс SQL Injection

Кажется, есть какая-то истерика об атаках SQL Injection. Совсем недавно здесь

Как вернуть значение в одном поле на основе значения поиска в другом поле

Если я создаю макрос в Excel, который подключается к базе данных Access, действительно ли мне нужно беспокоиться о SQL-инъекции? Это не в Интернете, он используется в моем офисе (вы, ребята, помните десктопы?). Меня не волнует, что мои сотрудники собираются саботировать меня. Если они достаточно умны для внедрения SQL-инъекций, разве они не достаточно умны, чтобы взломать мой пароль надстройки и просто изменить код?

4b9b3361

Ответ 1

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

Ответ 2

SQL Injection - это не просто угроза безопасности, но и очень реальный источник ошибок.

Вы уверены, что ни одна из ваших записей никогда не будет иметь апостофа (') в них?

INSERT INTO NAMES (FIRSTNAME, LASTNAME) VALUES('Jack', 'O'Neill')

В этом случае у вас есть ошибка, хотя никто не хотел взломать вашу систему.

Ответ 3

вы никогда не знаете, когда таблицы bobby будут использовать ваше слово macro:

xkcd

Ответ 4

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

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

Здесь код, реализующий простейшую версию этого:

Public Sub TestSQLExploit()
  Dim strSQL As String

  strSQL = "SELECT tblInventory.* FROM tblInventory WHERE InventoryID = "
  strSQL = strSQL & InputBox("Enter InventoryID")
  Debug.Print strSQL
End Sub

Итак, передача "10036 или" a "=" a "приводит к этому SQL:

SELECT tblInventory.*
FROM tblInventory
WHERE InventoryID=10036 Or 'a'='a'

И это определенно не хорошо!

Теперь я никогда не буду писать свой код таким образом, потому что всегда хочу разрешить несколько значений. Вместо этого, если бы я использовал функцию InputBox() для сбора пользовательского ввода (чего я, честно говоря, никогда не делаю, поскольку это слишком сложно проверить), я бы использовал Application.BuildCriteria для записи предложения WHERE, поскольку это позволило бы мне обрабатывать несколько значений критериев. Это приведет к этому коду:

Public Sub TestSQLExploit1()
  Dim strSQL As String
  Dim strWhere As String

  strSQL = "SELECT tblInventory.* FROM tblInventory "
  strWhere = "WHERE " & Application.BuildCriteria("tblInventory.InventoryID", _
      dbLong, InputBox("Enter InventoryID"))
  strSQL = strSQL & strWhere
  Debug.Print strSQL
End Sub

Я честно считал, что Application.BuildCriteria выдаст ошибку на этом, но это не так, и когда передано "10036 или" a "=" a ", получается точно такой же SQL. И из-за того, как работает служба выражения Jet, он будет широко раскрыт, как вы говорите.

Теперь я никогда на самом деле не писал такой "на лету" SQL, как это, потому что мне просто не нравится функция InputBox(), именно потому, что вам нужно написать кучу кода для проверки ввода. И если вы использовали его, как код выше, вам нужно сделать многое, чтобы убедиться, что оно действительно.

Я никогда не видел примеров кода доступа для такого рода операций, которые не рекомендуют использовать параметризованный SQL (который, конечно же, должен был бы избежать проблемы) или интерфейс Query-By-Form. Обычно я не использую сохраненные запросы параметров в Access, потому что мне нравится писать мои сохраненные запросы, которые можно использовать повсюду. Это означает, что в большинстве случаев нет предложений WHERE, которые имеют критерии, которые изменяются во время выполнения. Когда я использую эти сохраненные запросы, я предоставляю предложение WHERE для соответствующей ситуации, будь то источник записи в форме или источник rows для списка или выпадающего списка.

Теперь, дело в том, что я не прошу пользователя вводить данные в этих случаях, а рисует значения критериев из объектов Access, таких как элемент управления в форме. Теперь, в большинстве случаев, это будет контроль над формой, которая имеет только одну цель - собирать критерии для какой-либо формы фильтрации. Не было бы никаких неутвержденных полей свободного текста в этих полях формы - даты были бы введенные маски (которые ограничивали бы входные данные действительными датами), а поля с ограниченным количеством допустимых значений имели бы типы управления, которые ограничивают выбор действительным данные. Обычно это будет похоже на раскрывающийся список или группу параметров.

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

Теперь еще одно соображение заключается в том, что иногда вы хотите использовать некоторые текстовые поля, чтобы пользователь мог помещать определенные данные, которые еще не ограничены (например, поиск имен). Просто глядя на некоторые из моих приложений, которые имеют подпрограммы поиска имен с неопределенными текстовыми полями, я считаю, что я в порядке, потому что я не использую BuildCriteria в этих случаях, потому что он предназначен для сбора только одного критерия за раз (хотя пользователь может ввести "*" для извлечения нескольких записей).

Если у меня есть текстовое поле, в котором пользователь вводит "fent" или "a" = "a", и я использую это в предложении WHERE:

WHERE tblDonor.LName Like "fent* or 'a' = 'a'"

В результате ничего не найдено. Если пользователь ввел "fent * или = a", он все равно не будет работать, потому что это текстовое поле, и я использую двойную кавычку вокруг него. Если пользователь ввел:

fent* or "a" = "a"

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

Теперь, когда дело касается использования ввода и размещения двойных кавычек вокруг него, ясно, что это:

" Or "fent*" or "a" = "a" Or "

приведет к:

WHERE tblDonor.LName Like "" Or "fent*" or "a" = "a" Or ""

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

WHERE tblDonor.LName Like "? Or ?fent*? or ?a? = ?a? Or ?*"

Это не будет возвращать строки.

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

======

Некоторые выводы:

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

  • когда вы принимаете данные из текстового поля без каких-либо ограничений, избегайте Application.BuildCriteria, который будет обрабатывать входные данные таким образом, чтобы пользователь мог обмануть ваше приложение, возвращая все строки (хотя в той степени, в какой эксплоит мог сделать).

На практике это означает, что если вы хотите собрать несколько критериев, вам нужно сделать это так, чтобы пользователь мог выбирать только предварительно выбранные значения. Самый простой способ сделать это - использовать многосегментный список (или пару из них с добавлением ADD → и командными кнопками < REMOVE).

Конечно, нужно ли беспокоиться об этом эксплоите SELECT, зависит от важности и уровня конфиденциальности данных, которые извлекаются, и именно от того, что возвращается пользователю. Возможно, нет никакой проблемы, чтобы рискнуть возвращать все строки нечувствительных данных при представлении данных в неотредактируемой форме (например, в отчете), тогда как это может быть проблематично, если вы представили ее в редактируемой форме, а кто-то изменил данные, t отредактирован.

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

Итак, мой взнос на все это:

  • никогда не используйте InputBox() для сбора критериев (этого я уже избегаю).

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

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

Это означает, что у меня есть некоторые приложения там, где пользователь может вводить "Or" a "=" a "вместе с действительным критерием и возвращать все строки, но в этих приложениях это просто не проблема, поскольку данные нечувствительны.

Но это хорошее напоминание мне не быть самодовольным. Я думал, что Application.BuildCriteria защитит меня, но теперь поймите, что служба выражения Jet слишком прощает то, что она принимает в предложении WHERE.

2009/12/08 EDIT: Просто нашел эти ссылки на SQL Injection в MS Access. Все они нацелены на веб-инъекцию, поэтому они не могут быть непосредственно применимы к обсуждению внедрения не-Web SQL (многие из них будут пустой тратой времени в интерактивном доступе, поскольку у вас уже есть доступ к большому количеству информации, например, информация о файловой системе, пути, исполняемые файлы и т.д.), но многие из этих методов также будут работать в приложении Access. Кроме того, выполнение из Access открывает множество функций, которые не могут быть запущены из ODBC/OLEDB. Пища для размышлений.

Ответ 5

Как разработчик, вы несете ответственность, если не полностью, по крайней мере частично, за безопасность данных, хранящихся в вашем приложении.

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

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

Ответ 6

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

Ответ 7

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

Но реальная безопасность - это в конечном счете то, что может случиться, а не то, что мы ожидаем. Если ваше приложение обрабатывает данные, переданные вам публикой (SSN, номера кредитных карт и т.д.), Или если это единственный репозиторий данных, важных для вашей компании, вы должны учитывать, что потенциально вредоносные пользователи могли бы сделать с вашим кодом в будущее. Сегодня счастливым сотрудником является завтрашний недовольный социопат.

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

Ответ 8

Нет. (Да.) Да.:)

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

Все хорошо и хорошо сделать выражение о безопасности, но оно должно соответствовать требованиям.

Ответ 9

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

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

Я сам написал код, который уязвим для SQL-инъекции, но единственные люди с таким типом доступа все равно сотрудничают с SQL-доступом.

Ответ 10

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

Ответ 11

Если я создаю макрос в Excel, который подключается к базе данных Access, я действительно нужно беспокоиться о SQL инъекции?

Может быть. На самом деле это зависит. Я лично не буду беспокоиться, но какие данные вы пытаетесь сохранить и что это за чувствительность?

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

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

Ответ 12

Кто-нибудь, пожалуйста, опубликует код Excel VBA с индексом контекста для SQL-инъекции с использованием базы данных Jet в качестве задней части? Или продемонстрируйте, какие параметры могут быть переданы в код Как вернуть значение в одном поле на основе значения поиска в другом поле, которое будет повреждать (а не просто ломать код)?

Учитывая, что Jet не может выполнять несколько SQL-операторов, разделенных символом ";", мне сложно понять любую угрозу SQL-инъекции с помощью Jet back end. Но, возможно, потому, что я просто не так изобретателен, как хакеры.

О, свободная подсказка (в отношении опасностей, отличных от традиционной инъекции SQL):

  • Служба выражения доступа недоступна через ODBC.

  • он доступен через DDE, но я не знаю, можете ли вы передать SQL для доступа через DDE (я не использовал DDE с Access через 10 лет).

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

Ответ 13

Dick, зависит от того, как вы обрабатываете параметры. Здесь пример VBA, как не делать ничего:

Friend Function DeleteAnAccount() As Boolean

  Const SQL_DELETE_AN_ACCOUNT As String * 50 = _
      "DELETE FROM Accounts WHERE account_owner_ID = '?';"

  Dim sql As String
  sql = Replace$(SQL_DELETE_AN_ACCOUNT, "?", txtAccountOwnerID.Text)

  m_Connection.Execute sql

End Function

Учтите, что если некоторый wag вместо ввода идентификатора учетной записи в текстовое поле (txtAccountOwnerID), на самом деле напечатал это:

dummy' OR 'a' = 'a

то получившаяся строка SQL будет следующей:

DELETE FROM Accounts WHERE account_owner_ID = 'dummy' OR 'a' = 'a';

Нехорошо, потому что предикат 'a' = 'a' разрешит TRUE, и все учетные записи будут удалены.

Лучше было бы использовать подготовленный оператор, используя объекты Parameter, например. Объект ADODB.Command.

Джейми.

-

Ответ 14

Три точки:

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

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

  • Даже если все пользователи на 100% заслуживают доверия и никогда не будут недовольны, чтобы попытаться причинить какой-либо ущерб, всегда есть возможность опечаток или других непонятных ошибок. Защита от ошибок пользователя обычно считается хорошей.

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

Ответ 15

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

На самом деле, это не улучшит производительность в струе, если говорить о производительности запросов. Фактически, из документа JET "Обзор производительности и методы оптимизации" мы получаем этот драгоценный камень:

стр. 18

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

Ней-а-а? И я испытал выше!

Имейте в виду, что время компиляции для плана запроса равно 1000 секундам в любом случае. Я имею в виду, действительно, время плана запроса идет от 0,01 до 0,0001. Уверен, он в 100 раз быстрее, но это только сэкономит нам 100-е место в целом. Мы запускаем отчет, который занимает 2 секунды, так что время плана запроса даже не вызывает беспокойства.

Сегодня у нас GOBS обработки. Это дисковые накопители, память и скорость ввода/вывода в сети, которые являются шеей бутылки. У нас также нет проблемы с рассылкой кеша запросов sql сервера для каждой новой строки sql, отправленной JET. Тем не менее, эти встроенные sql-запросы не кэшируются. И БОЛЬШЕ важная JET - это клиентский движок, поэтому, когда у вас 10 пользователей на вашем офисном компьютере, у вас есть 10 копий JET, работающих локально на каждой машине. Кэш плана запросов не является проблемой, подобной серверу sql.

Как видно из приведенной выше реактивной белой бумаги (и моего опыта) преимущества лучшего плана запроса за счет принудительного повторного компиляции этого sql без параметров перевешивают преимущества наличия предварительно выполненного плана запросов с параметрами.

Однако, чтобы оставаться на связи, согласитесь с Дэвидом. Я не думаю, что когда вы используете odbc или в этом случае модель объекта + jeto, я не могу придумать ЛЮБОЙ ПУТЬ, чтобы ввести реальный оператор sql.

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

Для таких вещей, как удаление записи, вы просматриваете форму, и она будет иметь пользовательскую панель меню (или ленту) или просто кнопку удаления, помещенную в форму. Таким образом, пользователь не может ввести неверные данные для этого типа кода удаления.

БОЛЬШЕ, когда мы часто принимаем входные данные от пользователей по формам, помните, что наши формы имеют встроенные маски данных. В конце концов, это то, для чего был разработан MS-доступ. Следовательно, если мы запрашиваем номер телефона, пользователь не может вводить буквы или даже любые числовые чартеры для этой маски ввода. Эта маска будет даже помещена() и - в соответствующие места на этом номере телефона для отображения, но только цифры будут введены в фактический вход пользователя.

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

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

Если кто-нибудь может показать пример JET, в котором пользователь может выполнить инструкцию sql путем инъекции, я все уши, поскольку я не думаю, что это возможно с dao + jet.

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