php: sql-инъекция> как предотвратить, когда нельзя использовать подготовленный оператор? - PullRequest
0 голосов
/ 19 октября 2019

Простой вопрос: у меня есть фреймворк, который не использует подготовленные операторы (mySQLi). Как можно избежать инъекций SQL, когда у меня есть пользовательский ввод (сделан через открытую форму, но HTML-код не допускается). Этот комментарий должен быть сохранен в базе данных mysqli.

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

РЕДАКТИРОВАТЬ

Я НЕ спрашивал, как выполнить запрос MySQLi! Я спросил, как предотвратить sql-инъекции на php-уровне. Повторим: некоторые посетители сайта оставляют комментарий в текстовом поле. Внутри этого комментария этот посетитель (сценарий kiddie) думает, что он может опубликовать sql-инъекцию.

Теперь еще раз: как удалить этот псевдокод из комментария ПЕРЕД добавлением его в базу данных. Ответы типа «эй, используй подготовленное сообщение», «используй pdo», «используй этот запрос с этими параметрами» НЕ отвечают на мой вопрос. Также ответы, такие как "изменить" ваш фреймворк "или НЕ адекватны!

Я знаю, что это может такой код может быть удален preg_replace (..) и т. Д. И да, я знаю, что некоторые здесь неиспользовать эту технику .. так что лучше не отвечайте в этом направлении!

1 Ответ

1 голос
/ 20 октября 2019

Вы можете подумать, что использование «экранирующей» функции, такой как mysqli :: real_escape_string () на каждом входе, так же безопасно, как и использование подготовленных операторов.

За исключением:

  • Экранирование не работает для числовых входов, только строки в кавычках и даты в кавычках.

  • Экранирование имеет некоторые неожиданные случаи, когда оно не работает. Это крайние случаи, но они существуют. См. Несколько примеров в ответах на SQL-инъекцию, которая обходит mysql_real_escape_string ()

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

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

  • Параметры запроса также работают для числовых значений.

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

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

$sql = "INSERT INTO mytable (col1, col2, col3, col4, col5, col6) 
  VALUES ('" . mysqli_real_escape_string($_POST['col1']) . "', " 
  . $mysqli->real_escape_string($_POST['col2']) . "', '" 
  . $mysqli->real_escape_string($_POST['col3']) . "', '" 
  . $mysqli->real_escape_string($_POST['col4']) . ", '" 
  . $mysqli->real_escape_string($_POST['col5']) . "', '" 
  . $mysqli->real_escape_string($_POST['col6']) . "')";

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

Но это гораздо проще написать, а потом легче прочитать:

$sql = "INSERT INTO mytable (col1, col2, col3, col4, col5, col6) 
  VALUES (?, ?, ?, ?, ?, ?)";

Параметры запросов безопасны для большего количества типов данных и помогают быстрее писать код с меньшим количеством ошибок. Это большой выигрыш.

Как и другие комментарии выше, я не согласен с вашим утверждением, что MySQLi не поддерживает параметры запроса. Это ясно показано в документации: https://www.php.net/manual/en/mysqli.prepare.php

Если у вас есть какой-либо код-обертка, который использует MySQLi, но не поддерживает mysqli::prepare(), тогда я рекомендую вам прекратить использовать этот код-обертку. Либо напишите функции для своего фреймворка, чтобы он использовал параметры запроса, либо получите другой фреймворк.


Также отвечает как "изменить" ваш фреймворк или НЕ подходит!

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

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

Параметры запроса являются наиболее эффективным решением этой проблемы. Ваше сопротивление им абсурдно.

Это похоже на электрика, которыйспрашивает: «Как я могу предотвратить шок? Но я не могу использовать утепленные перчатки или инструменты, поэтому не советую этого делать. "

...