Вопрос по sql, mysql, sql-injection, php, sanitize – Достаточно ли шестнадцатеричного ввода для очистки запросов SQL?

5

Прошлой ночью я читал о предотвращении SQL-инъекций и наткнулся на этот ответ:

Как я могу предотвратить внедрение SQL в PHP?

В комментариях к «Твоему здравому смыслу» это звучало так, как будто это было неблагополучно / небезопасно. Тем не менее, в моем (хотя и ограниченном) тестировании я обнаружил, что php «bin2hex ($ var)» работает со всем, что я на него бросил - литеральным числом, числовой строкой, текстовой строкой - даже при сопоставлении с числовым столбцом (tinyint).

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

$query="SELECT * FROM table WHERE someidentifier=UNHEX('".bin2hex($unsafe_user_input)."') LIMIT 1"

В основном перевод на:

SELECT * FROM table WHERE someidentifier=UNHEX('0b99f') LIMIT 1

Есть ли дыры в этом типе безопасности?

PS - я не просто ищу ответы типа "Почему бы просто не использовать PDO или MySQLi с подготовленными утверждениями?" Это может подпасть под огромное зло упреждающей оптимизации, но я бы предпочел не удваивать накладные расходы на мой запрос (и да, я понимаю, что это может быть быстрее с несколькими одинаковыми запросами, но я не часто сталкиваюсь с такой ситуацией).

Существуют ли методы очистки в PDO и / или MySQLi (предпочтительно во втором), которые не предусматривают удвоение накладных расходов для данного запроса? Я прочитал кое-что о фильтре в w3schools, но я знаю, что они не очень надежный источник ... Joshua Broekhuijsen
Очень хорошие вещи, чтобы отметить, спасибо за указание на это. Вы можете придумать, каким образом это может быть введено? Joshua Broekhuijsen
Вы можете бросить свои собственные запросы, вручную экранируя, например,real_escape_string, Затраты на подготовку запроса реальны, но они очень незначительны в общей схеме. Только не делайте ошибку при подготовке запроса ВНУТРИ цикла вставки. Подготовка должна быть сделана ОДНА. Затем вы просто выполняете этот подготовленный оператор несколько раз. Marc B
-1 для упреждающей оптимизации Your Common Sense

Ваш Ответ

4   ответа
9

когда каждый пользовательский ввод очищается с помощью его шестнадцатеричного кода?

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

Посмотрим.CWE описывает SQL-инъекции (CWE-89) следующее:

Программное обеспечение создает всю или часть команды SQL с использованием внешнего воздействия […], но не нейтрализует или неправильно нейтрализует специальные элементы, которые могут изменить предполагаемую команду SQL […]

Более того:

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

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

Если пользовательский ввод предназначен для интерпретации какMySQL строковый литерал но это не инъекция SQL. Но почему это происходит?

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

Строка - это последовательность байтов или символов, заключенная в одну кавычку («'") Или двойная кавычка (""") персонажи.

Дополнительно:

Внутри строки определенные последовательности имеют особое значение […]. Каждая из этих последовательностей начинается с обратной косой черты («\»), Известный как побег. MySQL распознает escape-последовательности, показанные вТаблица 9.1, «Последовательности побега специальных символов».

Кроме того, чтобы иметь возможность использовать кавычки внутри строковых литералов:

Есть несколько способов включить символы кавычки в строку:

А'Внутри строки, заключенной в кавычки'»Может быть написано как«''».А"Внутри строки, заключенной в кавычки"»Может быть написано как«""».Символ кавычки должен начинаться с символа escape («\«).А'Внутри строки, заключенной в кавычки"”Не требует особого отношения и не нуждается в удвоении или спасении. Точно так же:"Внутри строки, заключенной в кавычки'»Не требует особого отношения.

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

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

То же самое относится и к другим литералам, а также к другим аспектам SQL.

Так как насчет вашего вопроса?

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

$query="SELECT * FROM table WHERE someidentifier=UNHEX('".bin2hex($unsafe_user_input)."') LIMIT 1"

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

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

Отличный ответ, довольно подробно. Я отметил в своем вопросе, почему я избегал параметризованных операторов, хотя я подозреваю, что это, вероятно, не будет большой разницей в производительности - в этом случае это всего лишь упражнение в программировании. Joshua Broekhuijsen
0

я успешно использовал Base64 для предотвращения инъекций mysql в прошлом из различных скриптов.

Если вы ищете сортировку (или даже поиск) через интерфейс, такой как phpMyAdmin, вы правы. Однако, если вы хотите использовать PHP для сортировки ПОСЛЕ того, как были возвращены результаты запроса, вы все равно можете сортировать по любому ключу. bdb.jack
Хм, это интересно. Не знаю точно, будет ли моя производственная среда на MySQL> = 5.6, но это определенно нужно учитывать, если есть. Может помочь уменьшить размер запроса (гекс выглядит довольно раздутым). Joshua Broekhuijsen
Я никогда не делал это напрямую в MySQL. Я обычно использую функции кодирования и декодирования PHP base64, но я нашел это, глядя в онлайн:stackoverflow.com/questions/358500/base64-encode-in-mysql bdb.jack
Это действительно хороший момент, тогда любая кодировка символов обрабатывается исключительно php. Основной недостаток, который я вижу в хранении вещей в базе данных, так как строки base64 сортируют их по алфавиту, скажем, по фамилии или что-то (в phpMyAdmin, или что у вас) было бы неэффективно. Joshua Broekhuijsen
0
$query="SELECT * FROM table WHERE someidentifier=UNHEX('".bin2hex($unsafe_user_input)."') LIMIT 1"

м PHP и MySQL.

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

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

Создание понятного, понятного, обслуживаемого кода стоит нескольких циклов ЦП и некоторого объема ОЗУ.

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

0

Здесь нет дыр, но нет и преимуществ. Обычное форматирование строк одинаково безопасно, но без всего этого бесполезного шестнадцатеричного / шестнадцатеричного содержимого.

Таким образом, раздутые ваши запросы с этим unhex материалом просто излишни.

По состоянию на тот ответ, изначально он был написан без раздумий и, следовательно, не с числами, что сделало его непригодным для использования. Хотя после добавления unhex он становится просто бесполезным и лишним.

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