Безопасно использующие подготовленные операторы для запросов базы данных

Я пытаюсь записать функцию, которая универсальна в запросах, которые позволяется сделать, но также и безопасный от инжекции. Код ниже бросает ошибку, как, но если я выполняю его с 'именем' вместо ':field', он хорошо работает.

$field = "name";
$value = "joe";

function selectquery($field, $value)
  {
  global $dbcon;

  $select = $dbcon->prepare('SELECT * FROM tester1 WHERE :field = :value');
  if($select->execute(array(':field' => $field, ':value' => $value)));
    {
    $row = $select->fetch();
    for ($i=0; $i<3; $i++)
      {
      echo $row[$i]."\n";
      }
    }  
  }

Как я позволил бы таблице/полям/значениям быть измененной, не позволяя инжекционные нападения? mysql_real_escape_string () отчасти походит на шаг назад. Какие-либо идеи?

5
задан JoeCortopassi 4 February 2010 в 22:05
поделиться

6 ответов

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

Почему бы просто не указать его как аргумент функции? В отличие от данных, предоставляемых пользователем, поля конечны, четко определены и не часто меняются. Как в

selectquery('name',$value);

и ваш запрос должен быть

$field = "name";
$value = "joe";

function selectquery($field, $value)
  {
  global $dbcon;

  $select=$dbcon->prepare("SELECT * FROM tester1 WHERE $field = :value");
  if($select->execute(array(':value' => $value)));
 //etcetera  

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

Если по какой-то нечетной причине имя поля получено из пользовательского ввода, вы можете создать массив разрешенных полей. Таким образом, вы защищены от инъекции, потому что значения могут поступать только из вашего массива. Я не знаю, почему имя поля будет получено из пользовательского ввода и, следовательно, не заслуживает доверия, если, возможно, вы не делаете API? В противном случае, вероятно, есть лучший способ достичь цели.

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

$field = "name";
$value = "joe";

$allowed_fields=array('name','other_name','sandwich');

function selectquery($field_name, $value)
  {
  global $dbcon,$allowed_fields;

  if(!in_array($field_name,$allowed_fields)){ return false; }
  else{ $field=$field_name; }

  $select=$dbcon->prepare("SELECT * FROM tester1 WHERE $field = :value");
  if($select->execute(array(':value' => $value)));
  //etcetera
3
ответ дан 15 December 2019 в 01:01
поделиться

Используйте MDB2 autoExecute
http://pear.php.net/manual/en/package.database.mdb2.intro-auto.php

<?php
// Once you have a valid MDB2 object named $mdb2...
$table_name = 'user';

$fields_values = array(
    'id'      => 1,
    'name'    => 'Fabien',
    'country' => 'France'
);
$types = array('integer', 'text', 'text');

$mdb2->loadModule('Extended');
$affectedRows = $mdb2->extended->autoExecute($table_name, $fields_values,
                        MDB2_AUTOQUERY_INSERT, null, $types);

if (PEAR::isError($affectedRows)) {
    die($affectedRows->getMessage());
}
?>
1
ответ дан 15 December 2019 в 01:01
поделиться

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

Иногда вам может потребоваться обратная ссылка на эти идентификаторы (используйте ` для MySQL и " для SQLite).

0
ответ дан 15 December 2019 в 01:01
поделиться

Я думаю, что ваше html/css-направление может быть действительно умным движением.

Может быть проще получить потрясающий макет с помощью Open Office draw и просто связать с изображениями, снимая флажок ссылки при их первом введении. Open Office поддерживает экспорт в pdf, что делает его полезным для создания отчетов.

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

С уважением

-121--2414500-

Я думаю, что для разработки приложений .Net необходимо использовать Vista или даже XP причина в том, что ваши приложения должны быть обратно совместимыми. Помните, что большинство пользователей по-прежнему используют XP. И вы не можете продать свое приложение пользователю XP, даже если ваше приложение очень умное, потому что они не могут установить его. И наконец .Net является Platform independ, вы можете использовать его на любой версии Windows вы хотите. (даже для Linux) (исключены окна 3, 98)

-121--4196005-

Привязка переменной к ней в виде данных, в частности, предотвращение изменения синтаксиса запроса . Кроме того, наличие фиксированного синтаксиса позволяет подсистемам анализировать подготовленные запросы один раз и затем быстро запускать их для каждого набора значений. Я бы посоветовал не строить слой удержания рук поверх SQL, но если нужно, рассмотрим preg_replace ('/\W/', ", $ поле).

0
ответ дан 15 December 2019 в 01:01
поделиться

Объекты данных PHP, к сожалению, не предоставляют метод для заключения идентификатора поля в кавычки.

В качестве альтернативы PEAR :: MDB2 (духовный предшественник объектов данных PHP) имеет параметр -> quoteIdentifier () , который позволяет вам добиться желаемого в безопасном месте. манера.

function selectquery($field, $value)
  {
  global $dbcon;

  $select = $dbcon->prepare('SELECT * FROM tester1 WHERE ' . $dbcon->quoteIdentifier($field) . ' = :value');
  if($select->execute(array('field' => $field, 'value' => $value)));
    {
    $row = $select->fetchRow();
    for ($i=0; $i<3; $i++)
      {
      echo $row[$i]."\n";
      }
    }  
  }

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

0
ответ дан 15 December 2019 в 01:01
поделиться

Второй ответ Эндрю Мура: единственный выход - это цитирование идентификатора, а PDO не предоставляет необходимый метод. Вместо использования MDB2 вы можете просто позаимствовать его реализацию цитирования идентификаторов. Функция достаточно проста, чтобы вы могли написать свою собственную и довольно легко проверить ее на наличие ошибок.

  1. Разделить входную строку на . в список частей (может быть только одна)

  2. Для каждой части:

    1. Заменить все ` на ` .
    2. Добавьте ` в начало и в конец, если часть не пуста. *
  3. Соедините части с помощью . .

Например, quote_identifier ("one two.three") должно быть `one two`.`three` - довольно просто.

Для дополнительной безопасности вы также можете проверить, что строка не содержит никаких недопустимых символов даже в цитируемых идентификаторах (особенно нули, см. документацию MySQL ), но на самом деле MySQL должен их перехватить. MDB2 не беспокоит.

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

0
ответ дан 15 December 2019 в 01:01
поделиться
Другие вопросы по тегам:

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