Для создателей контента сайта поддерживаются списки HTML в формате, ниже которого cronjob (Perl) анализирует базу данных mySQL.PHP извлекает данные в разбитые на страницы индексы.
<li>Lorem ipsum dolor sit amet<br>
<a href="../path/to/file.php">Lorem ipsum dolor sit amet</a><br>
consectetuer adipiscing elit</li>
(Perl извлекает текст и URL и сохраняет их в базе данных как заголовок, URL, текст ссылки, нижний колонтитул.)
Иногда вызывается пользовательская функциявставляется в текст следующим образом:
<li>Lorem ipsum <?php age(1234) ?> dolor sit amet<br>
<a href="../path/to/file.php">Lorem ipsum dolor sit amet</a><br>
consectetuer adipiscing elit</li>
Запрос возвращает эту строку для первой строки ($ header):
'Lorem ipsum <?php age(1234) ?> dolor sit amet'
Конечно, это не выполняется при извлечениизапрос.И при этом это не произойдет в фиксированном месте, поэтому не может быть проанализировано в отдельном поле.
Я прочитал несколько потоков об использовании eval
здесь, и учитывая, что только создатели контента в доме редактируют списки,это должно быть достаточно безопасно.IOW, если злой код вводится в список или базу данных, у нас возникают большие проблемы, чем неанизированный код, вставленный какой-либо внешней стороной в форму.
Моя другая идея - preg_replace_callback()
.Тем не менее, некоторые предположили, что у SO такая же проблема, как у eval
, хотя я думаю, что регулярное выражение должно / могло бы заблокировать это.Также я не вижу, как это могло бы выполнить произвольный код, если только не передать его в качестве значения параметра пользовательской функции.
Какой будет лучший подход?Или есть какой-то другой, более безопасный подход?(PHP 7.2, mySQL 5.6)
TIA
Редактировать
Я реализовал приведенный ниже код, используя обратный вызов, а не eval
.Применительно только к нескольким разрешенным функциям, для которых, кстати, всем требуется только один числовой параметр, он выглядит довольно заблокированным.
if (stristr($header, '<?php ') !== FALSE) {
$header = preg_replace_callback(
'/<\?php (?P<php>(?P<func>(function|whitelist))?\((?P<value>\d+)\)) \?\>/i',
function($matches) {
// print_r($matches);
ob_start(); // functions print, not return
// $matches['php']; // does not work
$matches['func']($matches['value']); // works
// call_user_func($matches[1], $matches[2]); // unnecessary detour
// $out = ob_get_clean(); // ditto
// return $out;
return ob_get_clean();
},
$header
);
}
Спасибо за вашу помощь.