Как предотвращать вставку SQL в PHP?

Динамические решения - решения SQL, которые создаются как цепи текста (strings), и в которых вводится / прилагается стоимость, полученная от какого-то шрифта (обычно полученный от пользователя), что может способствовать тому, чтобы они были уязвимыми во вставку SQL, если не дезинфицируются поступающие данные, как например:

$id_usuario = $_POST["id"];

mysql_query("SELECT * FROM usuarios WHERE id = $id_usuario");

Это пример тяжелой уязвимости в безопасности приложения (Веб или не), потому что, если пользователь вводил стоимость как 1; DROP TABLE usuarios;-- мы столкнулись бы тем, что выполненное решение было бы:

SELECT * FROM usuarios WHERE id = 1; DROP TABLE usuarios;--

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

Как я могу избегать того, чтобы вставка SQL произошла в PHP?

184
задан 04.03.2017, 05:08
1 ответ

НЕ ИСПОЛЬЗУЙ НИ ДИНАМИЧЕСКИХ РЕШЕНИЙ, НИ ФУНКЦИЙ mysql_*

Функции mysql_* (mysql_connect, mysql_query, и т.д.) они небезопасные из-за природы и Ваше использование не только не рекомендовалось, но они считаются устаревшими и были удалены полностью начиная с PHP7.

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


Используй готовые решения и консультации parametrizadas

Хотя могли бы быть дезинфицированными поступающие данные используя методы как mysqli_real_escape_string, более рекомендуемое использование готовых решений или parametrizadas. Готовые решения позволят тебе выполнять то же решение с большой эффективностью.

В PHP, у тебя есть две главные альтернативы: PDO и MySQLi. Есть несколько различий между обоими, но главная состоит в том, что PDO может быть использованным различными типами базы данных (в зависимости от использованного драйвера) в то время как MySQLi исключительно для баз данных MySQL. Именно из-за этого он рекомендовал бы PDO на MySQLi.

PDO

Закладки положения (которое они показывают, где будет заменена цепь на Вашу стоимость), могут определяться хорошо используя вопросительный знак (?) или используя имя (обычно начинаясь с :). Лично я предпочитаю использовать имя, потому что это помогает мне находить возможные ошибки, в случае когда имеет многообразные переменные.

Здесь я оставляю пример для кода вопроса:

// la variable $pdo contendrá el objeto con la conexión PDO
$pdo = new PDO('mysql:host=mihost;dbname=basedatos', "usuario", "contraseña");

$id_usuario = $_POST["id"];

$sentencia = $pdo->prepare("SELECT * FROM usuarios WHERE id = :idusuario");
$sentencia=$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$sentencia->bindParam(":idusuario", $id_usuario, PDO::PARAM_INT);
$sentencia->execute();

В этом случае, :idusuario он будет заменен на стоимость $_POST["id"] безопасной формы, и когда он делает bind, показывается, что переменная - целого типа (PDO::PARAM_INT).

Заметь: если переменная будет цепью текста, он будет использован PDO::PARAM_STR и не надо помещать кавычки в решение SQL; определив PHP, который является цепью, он добавит их автоматически, сделав bind.

В случае, если будут существовать несколько переменных, которые было нужно включать в решение SQL, нужно включать единственный параметр для каждой из стоимости, которая используется в решении. Предыдущего примера, :idusuario может быть использованным единственный раз в консультации, которая готовится. Если бы было необходимо использовать "idusuario" снова в консультации, нужно создавать другой параметр со стоимостью $id_usuario.

$pdo = new PDO('mysql:host=mihost;dbname=basedatos', "usuario", "contraseña");

$id_usuario = $_POST["id"];

$sentencia = $pdo->prepare("UPDATE usuarios SET id = :idusuario WHERE id = :idusuario1");
$sentencia=$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$sentencia->bindParam(":idusuario", $id_usuario, PDO::PARAM_INT);
$sentencia->bindParam(":idusuario1", $id_usuario, PDO::PARAM_INT);
$sentencia->execute();

MySQLi

У этого метода есть два интерфейса: procedural и другая, ориентируемая на объекты. Интерфейс procedural очень похожий в mysql_*, и из-за этого люди, которые мигрируют с mysql_* смоги чувствовать себя привлеченной возможностью, которая mysqli_* предложи. Хотя, снова лично, он выбрал бы версию POO.

Заметь: хотя функции mysqli_* они обычно являются похожими в mysql_*, в каких-то случаях у них могут быть различные параметры ввода или различных выводов, что он может приносить во что-то из путаницы сначала.

Пример вопроса остался бы таким с MySQLi в Вашем интерфейсе, ориентируемом на объекты:

// en $mysqli tendremos la conexión MySQLi
$mysqli = new mysqli("mihost", "usuario", "contraseña", "basedatos");

$id_usuario = $_POST["id"];

$sentencia = $mysqli->prepare("SELECT * FROM usuarios WHERE id = ?");
$sentencia->bind_param("i", $id_usuario );
$sentencia->execute();

Поскольку возможно видеть, он достаточно похожий на PDO (он меняет немного, как определяется тип стоимости, i для целых чисел и s для цепей, но идея сходная).

В версии procedural MySQLi, эквивалентный код был бы:

// en $conn tendríamos la conexión a la base de datos con MySQLi
$conn = mysqli_connect("mihost", "usuario", "contraseña", "basedatos");

$id_usuario = $_POST["id"];

$sentencia = mysqli_prepare("SELECT * FROM usuarios WHERE id = ?");
mysqli_stmt_bind_param($sentencia, "i", $id_usuario);
mysqli_stmt_execute($sentencia);

Шрифт и библиография для большей информации на испанском языке:

177
ответ дан 24.11.2019, 13:44
  • 1
    В bind PDO, какое-то преимущество безопасности есть, использовав PDO:: PARAM_INT или PDO:: PARAM_STR? так как недавно aprend и # 237; это b и # 225; sico PDO, но не hab и # 237; в нуждаемый в том, чтобы использовать эту третью пару и # 225; метр, приготовив решение. – Roberto Sepúlveda Bravo 15.10.2016, 07:18
  • 2
    Если я не ошибаюсь, не определять тип не касается безопасности а результата. Назначенный по умолчанию PDO конвертировать и # 225; информация в цепь (хотя это может зависеть от configuraci и # 243; n) и потом база данных tendr и # 225; который обращать снова в тип информации о колонне. Оставаться и # 237; в будучи страховкой, но не работоспособный. – Alvaro Montoro♦ 15.10.2016, 15:25
  • 3
    @AlvaroMontoro ты мог помогать мне с сомнением, которое у меня есть? а именно я стремлюсь к тому, чтобы выдвинуть вопрос на как инициализироваться с usod и framework, написанным в JS и autoresponderme показывая весь процесс, правильно, как я стремлюсь к тому, чтобы сделать это? –  18.03.2018, 23:10
  • 4
    S@ShadowPaz Sí serí в правильный; вопросы с авто-ответом позволяются и стимулируются. Совсем то, что приспосабливается к temá костариканская и формат сайта, и который служит для того, чтобы улучшить знание сообщества, - втречен с радостью. – Alvaro Montoro♦ 19.03.2018, 00:26

Теги

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