Выполнить пользовательскую функцию PHP в MySQL Query Result - PullRequest
0 голосов
/ 15 октября 2018

Для создателей контента сайта поддерживаются списки 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
    );
}

Спасибо за вашу помощь.

...