filter_input и mysqli_real_escape_string для целых чисел

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

В настоящее время я использую $num = filter_input(INPUT_GET, 'num', FILTER_VALIDATE_INT, $num_options); с указанными минимальными и максимальными значениями. Отсюда я выхожу с сообщением об ошибке, если $num == false

Нужно ли также использовать $mysqli->real_escape_string($num);

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

Спасибо,

Кевин

ОБНОВЛЕНИЕ: чтобы уточнить запрос, который я делаю, выглядит так

$sql = "SELECT employeeID, concat(FirstName, ' ', LastName) as Name FROM employee WHERE employeeID='$num'";

person Kevin Morse    schedule 11.03.2012    source источник


Ответы (2)


Как и многие другие пользователи PHP, вы неправильно экранируете код. Вы воспринимаете это как своего рода волшебную палочку, которая делает некоторых "злых персонажей" "безопасными".
Это неправильная идея.
хотя подготовленные операторы могут быть восприняты как своего рода волшебная палочка, побег не синоним «защита от SQL-инъекций». Это просто синтаксическое правило строки — ни больше, ни меньше.

Нужно ли также использовать $mysqli->real_escape_string($num);

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

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

Объяснение:
Правила проверки данных могут быть изменены.
В то время как правила построения SQL должны быть явными и безусловными. Чтобы разработчик никогда не задавал себе подобных вопросов.
На самом деле это совершенно разные вещи: проверка данных и построение запросов. Зачем помнить о таких деталях и соответствующим образом строить запрос? Почему бы не построить запрос на основе некоторого набора правил общего назначения, вообще не имеющих отношения к природе данных?

Итак, снова к вашему вопросу:

  • если вы добавляете свои данные в запрос как есть, без кавычек, real_escape_string() в этом случае будет совершенно бесполезным, но приведение/проверка становятся необходимыми.
  • если вы добавляете свои данные в запрос, используя подготовленный оператор, real_escape_string() будет совершенно бесполезным и даже вредным.
  • если вы добавляете свои данные в запрос в кавычках - в этом случае вы должны сделать real_escape_string().
  • также стоит отметить, что если вы добавляете свои данные в запрос как часть языка SQL - как идентификатор или ключевое слово SQL - real_escape_string() также совершенно бесполезен, как и подготовленный оператор. Белый список - ваш единственный друг здесь
person Your Common Sense    schedule 11.03.2012
comment
Если я правильно понимаю, вы говорите, что если я не вставлю это в цитируемую часть моего SQL-запроса, его не нужно экранировать? - person Kevin Morse; 11.03.2012
comment
Если вы не вставляете это в цитируемую часть вашего SQL, экранирование становится полностью, абсолютно и совершенно бесполезным. - person Your Common Sense; 11.03.2012
comment
Что означает заключенная в кавычки часть SQL? Пожалуйста, посмотрите точный запрос, который я сейчас разместил в своем исходном сообщении. - person Kevin Morse; 11.03.2012
comment
У вас есть $num в апострофах. таким образом, вы рассматриваете его как строку. Строки в SQL должны экранироваться. - person Your Common Sense; 11.03.2012
comment
да, в некотором роде. По крайней мере, когда ваш идентификатор будет изменен на строку, вы будете уведомлены об ошибке SQL. Но меня тошнит от того, как пользователи PHP делают свой код. - person Your Common Sense; 11.03.2012
comment
Что ж, функция filter_input возвращает только int или false, и в этом случае она не может попасть в оператор, так что все должно быть в порядке! - person Kevin Morse; 11.03.2012

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

Подготовленные операторы PHP mysqli

Это немного сложно для примера, но приведенная выше ссылка содержит подробные примеры.
Однако, как только вы освоитесь и создадите свой класс. Это действительно обычный SQL-запрос, но вместо того, чтобы включать ваши значения, которые вы используете?

"SELECT * FROM account WHERE username = ? AND password = ?"

и вы привязываете свои значения к утверждению:

array("bradley", "Passw0rd");

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

person Bradmage    schedule 11.03.2012
comment
Ой, кажется, я отклонился от темы, извините. Вы в основном обеспокоены целыми числами. Но я предполагаю, что с подготовленными статами вы должны указать строку/целое число, так что, я полагаю, это решит вашу проблему с инъекциями с целыми числами. - person Bradmage; 11.03.2012
comment
Я только что опубликовал точный запрос, который я использую. Я знаком с подготовленными заявлениями, я просто подумал, что они немного излишни для этой ситуации. - person Kevin Morse; 11.03.2012
comment
Подготовленные заявления @KevinMorse не могут быть излишними - person Your Common Sense; 11.03.2012
comment
Я согласен, весь мой код базы данных заперт в своем классе, я захожу и время от времени настраиваю его. Но я в основном использую его для всего, если только это не быстрый оператор отладки, я просто бросаю быстрый сырой $db->query() :D - person Bradmage; 11.03.2012
comment
@KevinMorse, чтобы вы знали, подготовленные операторы могут быть надежными, только если они используются во всех операциях SQL сайта без исключений. В противном случае это не принесет пользы. - person Your Common Sense; 11.03.2012
comment
Да, извините за это. Не стоит говорить о моих вредных привычках. - person Bradmage; 11.03.2012
comment
Я читал, что накладные расходы на производительность не стоят того для подготовленных операторов, которые будут выполняться только один раз. В моем случае этот SQL-запрос просто выбирает одну строку, поэтому я действительно не понимаю, зачем мне беспокоиться о подготовленном операторе. - person Kevin Morse; 11.03.2012
comment
Это должно быть вопросом мнения. Кому накладные расходы не нужны? Какие данные вы защищаете? Можно ли, если есть уязвимости? Когда дело доходит до этого, только разработчик может решить, стоит ли оно того. Это не похоже на сравнение двух разных строковых функций с одинаковым результатом. - person Bradmage; 11.03.2012
comment
Справедливо. В этом случае никакие данные не защищены (кроме имен сотрудников в компании из 20 человек), но я рассмотрю подготовленные отчеты на будущее! - person Kevin Morse; 11.03.2012
comment
Лучше всего попробовать использовать ту же библиотеку. Создайте класс и продолжайте развивать его. Моя началась так: ссылка, пока вы используете одну и ту же, она станет сильнее :) - person Bradmage; 11.03.2012