Могу ли я быть уязвимым для внедрения SQL, добавляя входные данные без пробелов в мой запрос? - PullRequest
3 голосов
/ 17 декабря 2008

Я беру строку из пользовательского ввода и разбиваю ее по пробелам (используя \ w) на массив строк. Затем я перебираю массив и добавляю часть предложения where следующим образом:

            query += " AND ( "

                 + "field1 LIKE '%" + searchStrings[i] +"%' "
                 + " OR field2 LIKE '%" + searchStrings[i] +"%' "
                 + " OR field3 LIKE '%" + searchStrings[i] +"%' "
                 + ") ";

Я чувствую, что это опасно, так как я добавляю пользовательский ввод в свой запрос. Однако я знаю, что ни в одной из строк поиска нет пробелов, так как я разделил начальный ввод на пробел.

Можно ли атаковать это с помощью SQL-инъекции? Давать Robert');DROP TABLE students;-- на самом деле ничего бы не упало, потому что там должен быть пробел. В этом примере он не будет вести себя должным образом, но никакого ущерба не будет.

Может ли кто-нибудь с большим опытом борьбы с инъекциями SQL помочь мне исправить это или успокоить?

Спасибо!

EDIT:

Ух ты, много хорошего. Спасибо всем, кто откликнулся. Я буду исследовать полнотекстовый поиск и, как минимум, параметризировать свой запрос.

Чтобы я мог лучше понять проблему, можно ли было бы внедрить, если бы все пробельные символы И одинарные кавычки были экранированы?

Ответы [ 7 ]

14 голосов
/ 17 декабря 2008

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

Вы должны быть очень осторожны при заполнении массива searchStrings []. Вы всегда должны добавлять переменные данные к вашему запросу, используя объекты параметров:

+ field1 like @PropertyVal Or field2 like @PropertyVal Or field3 like @PropertyVal etc...

А если вы используете SQL Server, например

Query.Parameters.Add(new SqlParameter("PropertyVal", '%' + searchStrings[i] + '%'));

Будьте очень осторожны при создании строки запроса, которую вы собираетесь запустить на рабочем сервере, особенно если в нем есть какие-либо данные последствий!

В своем примере вы упомянули маленькие столики Бобби

Роберт '); DROP TABLE студентов; -

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

Robert');Exec(Replace('Drop_Table_students','_',Char(32)));--

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

13 голосов
/ 17 декабря 2008

Да, этот скрипт не содержал пробелов, только закодировал символы, которые SQL декодировал и выполнял http://www.f -secure.com / блог / архивы / 00001427.html

Внедренный скрипт был примерно таким:

20% ЗАЯВЛЯЮ @ S% 20NVARCHAR (4000); SET% 20 @ S = CAST (0x440045004300 4C00410052004500200040005400200076006100720063006800610072 00280032003500350029002C0040004300200076006100720063006800 610072002800320035003500290020004400450043004C004100520045 0020005400610062006C0065005F0043007500720073006F0072002000 43005500520053004F005200200046004F0052002000730065006C0065 0063007400200061002E006E0061006D0065002C0062002E006E006100 6D0065002000660072006F006D0020007300790073006F0062006A0065 00630074007300200061002C0073007900730063006F006C0075006D00 6E00730020006200200077006800650072006500200061002E00690064 003D0062002E0069006400200061006E006400200061002E0078007400 7900700065003D00270075002700200061006E0064002000280062002E 00780074007900700065003D003900390020006F007200200062002E00 780074007900700065003D003300350020006 ...

Который SQL расшифровывается в:

ОБЪЯВИТЬ @T varchar (255) '@ C varchar (255) ОБЪЯВИТЬ Table_Cursor
КУРСОР ДЛЯ выберите a.name'b.name из sysobjects a'syscolumns b где a.id = b.id и a.xtype = 'u' и (b.xtype = 99 или b.xtype = 35 или b…

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

5 голосов
/ 17 декабря 2008

Существует слишком много способов ошибиться, и я бы не стал полагаться, если бы кто-нибудь сказал мне: «Нет, это будет безопасно, потому что ...»

Как насчет экранирования пробелов в какой-либо форме (URL-кодирование или что-нибудь другое). Как насчет использования неочевидных пробельных символов Юникода, которые не проверяются вашими простыми тестами. Что если ваша БД поддерживает некоторые вредоносные операции, для которых не требуется пробел?

Действуйте правильно: используйте PreparedStatement (или что-то еще, что ваша платформа использует для параметризации, безопасной для инъекций), добавьте и добавьте «%» к вводу пользователя и используйте его в качестве параметра.

2 голосов
/ 17 декабря 2008

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

Если ваша СУБД не поддерживает параметры запроса, она ДОЛЖНА поддерживать экранирование строк. В худшем случае вы можете попытаться избежать одиночных кавычек самостоятельно, хотя все еще существует уязвимость Unicode, которая может обойти это. Однако, если ваша СУБД не поддерживает параметры запроса, она, вероятно, также не поддерживает Unicode. :)

Добавлено: Также. Запросы, подобные тем, что вы написали, влияют на производительность - индексы использовать нельзя. Я бы посоветовал посмотреть на возможности полнотекстовой индексации вашей СУБД. Они предназначены именно для таких случаев, как этот.

2 голосов
/ 17 декабря 2008

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

1 голос
/ 17 декабря 2008

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

'+field1+'

Вы должны использовать параметры (они действительны и для встроенного SQL), например,

AND Field1 = @Field1
1 голос
/ 17 декабря 2008

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

В общем, слепое добавление пользовательского ввода в запрос не очень хорошая идея.

...