Placido
Наблюдаю
В продолжение вот этой темы. Если вкратце, то делаю онлайновый текстовый редактор с поддержкой регулярных выражений. Хочу, чтобы пользователи имели возможность использовать callback-функции (реализовано через preg_replace_callback, вот в этой теме я объяснял, зачем это нужно).
Редактор работает нормально, я им успешно пользуюсь у себя на локалхосте, но теперь хочу разместить его в Интернете. Поэтому пришло время особое внимание уделить вопросам безопасности.
Если в общих словах, то в функцию preg_replace_callback($pattern, $callback, $text) все параметры подставляются из введенных юзером данных в форме на сайте. Введенные данные сохраняются в базе в виде правил, которые можно повторно использовать впоследствии. И если с проверкой валидности паттерна и текста, в котором будет производиться замена, проблем не возникает, то вот с параметром $callback нужно хорошенько повозиться.
Как проверять на валидность $callback? Мыслю так.
1. Проверить, чтобы в коде, вводимом в $callback, не было потенциально опасных конструкций.
2. Запустить preg_replace_callback() в тестовом режиме, и если произойдет ошибка, сделать перенаправление на страницу формы ввода, в которую через сессию подставить введенные данные, и вывести сообщение об ошибке «callback-функция невалидна». Ошибки проверять так: в валидаторе использовать register_shutdown_function(‘myShutdown’), в функции myShutdown() проверять наличие ошибок с помощью error_get_last(), если ошибка есть, то парсить ее текст. Если ошибка связана с работой preg_replace_callback(), то выполнять описанные выше действия. С помощью такого способа можно отловить и фатальные ошибки, такие как ошибка "undefined function".
Остается вопрос по первому пункту. Здесь планирую использовать token_get_all(), и с помощь нее все функции, которые есть в коде, проверять на вхождение в «белый список» (в котором только строковые функции, функции mb_... и математические функции), запретить инклюды, использование eval(). token_get_all() разбивает строку кода на лексемы, и, проверив код с помощью нее, можно запретить использование практически всего, чего угодно, вплоть до запрета использования массивов и условных операторов.
Но что, кроме опасных функций, стоит запретить вводить пользователю? Думаю, нужно исключить ввод переменных функций, чтобы пользователь не мог сделать что-то вроде такого:
и переменных переменных:
Хотел бы узнать мнения, какие опасности могут быть еще?
Редактор работает нормально, я им успешно пользуюсь у себя на локалхосте, но теперь хочу разместить его в Интернете. Поэтому пришло время особое внимание уделить вопросам безопасности.
Если в общих словах, то в функцию preg_replace_callback($pattern, $callback, $text) все параметры подставляются из введенных юзером данных в форме на сайте. Введенные данные сохраняются в базе в виде правил, которые можно повторно использовать впоследствии. И если с проверкой валидности паттерна и текста, в котором будет производиться замена, проблем не возникает, то вот с параметром $callback нужно хорошенько повозиться.
Как проверять на валидность $callback? Мыслю так.
1. Проверить, чтобы в коде, вводимом в $callback, не было потенциально опасных конструкций.
2. Запустить preg_replace_callback() в тестовом режиме, и если произойдет ошибка, сделать перенаправление на страницу формы ввода, в которую через сессию подставить введенные данные, и вывести сообщение об ошибке «callback-функция невалидна». Ошибки проверять так: в валидаторе использовать register_shutdown_function(‘myShutdown’), в функции myShutdown() проверять наличие ошибок с помощью error_get_last(), если ошибка есть, то парсить ее текст. Если ошибка связана с работой preg_replace_callback(), то выполнять описанные выше действия. С помощью такого способа можно отловить и фатальные ошибки, такие как ошибка "undefined function".
Остается вопрос по первому пункту. Здесь планирую использовать token_get_all(), и с помощь нее все функции, которые есть в коде, проверять на вхождение в «белый список» (в котором только строковые функции, функции mb_... и математические функции), запретить инклюды, использование eval(). token_get_all() разбивает строку кода на лексемы, и, проверив код с помощью нее, можно запретить использование практически всего, чего угодно, вплоть до запрета использования массивов и условных операторов.
Но что, кроме опасных функций, стоит запретить вводить пользователю? Думаю, нужно исключить ввод переменных функций, чтобы пользователь не мог сделать что-то вроде такого:
PHP:
$a = ‘shell_exec’;
$a(здесь все, что душе угодно);
PHP:
$a = 'b';
$b = 'var_dump';
$$a('You\'ve been hacked!');//string(19) "You've been hacked!"