Вопрос

У меня есть некоторый код, который использует параметризованные запросы для предотвращения внедрения, но мне также нужно иметь возможность динамически создавать запрос независимо от структуры таблицы.Как правильно это сделать?

Вот пример, допустим, у меня есть таблица со столбцами Name, Address, Phone.У меня есть веб-страница, на которой я запускаю Показывать столбцы и заполните раскрывающийся список "Выбрать" ими в качестве параметров.

Далее, у меня есть текстовое поле под названием Поиск.Это текстовое поле используется в качестве параметра.

В настоящее время мой код выглядит примерно так:

result = pquery('SELECT * FROM contacts WHERE `' + escape(column) + '`=?', search);

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

Как я могу убедиться, что это работает так, как я задумал?

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

Это было полезно?

Решение

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

@columns = qw/Name Address Telephone/;
if ($columns[$param]) {
  $query = "select * from contacts where $columns[$param] = ?";
} else {
  die "Invalid column!";
}

run_sql($query, $search);

Другие советы

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

Тем не менее, это можно сделать, я рекомендую отдельную - и строгую — функцию для проверки имени столбца.Разрешите ему принимать только один идентификатор, что-то вроде

/^\w[\w\d_]*$/

Вам придется полагаться на предположения, которые вы можете сделать относительно имен ваших собственных столбцов.

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

желаю удачи

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

В стандартном SQL идентификаторы с разделителями заключаются в двойные кавычки.Это означает , что:

SELECT * FROM "SomeTable" WHERE "SomeColumn" = ?

выберет из таблицы с именем SomeTable с показанной заглавной буквой (не преобразованную в регистр версию имени) и применит условие к столбцу с именем SomeColumn с показанной заглавной буквой.

Само по себе это не очень полезно, но ... если вы сможете применить метод escape() с двойными кавычками к именам, введенным через вашу веб-форму, тогда вы сможете достаточно уверенно сформировать свой запрос.

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

Разные СУБД имеют разные способы предоставления идентификаторов с разделителями.MS SQL Server, например, похоже, использует квадратные скобки [SomeTable] вместо двойных кавычек.

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

if ( $column !~ /^\w+$/ ) {
  die "Bad column name [$column]";
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top