Безопасное исполнение PHP кода в шаблоне

Статус
В этой теме нельзя размещать новые ответы.

SKYNET74

Постоялец
Регистрация
11 Июл 2016
Сообщения
146
Реакции
20
Здравствуйте, собственно может быть кто то сталкивался, гугления и хабрления особо ник чему толковому не привели, кроме нескольких библиотек на гитхабе, которые работают ну очень медленно, жрут ну очень много памяти, и уже давно не обновлялись. Работают на основе PHP токинайзера.

Задача сделать шаблонизатор с PHP подобной логикой, но при этом безопасный для самого сайта (в случае если злоумышленник как то попадёт в админку, и вставит в шаблон опасные функции).

Стадии работы:
- Загружаем шаблон (из файла или переменной)
- Проверяем сгенерированный PHP кеш
- Если кеш есть, исполняем
- Если кеша нет, запускаем парсер синтаксиса для преобразования в PHP код
(Вот на данном момент после преобразования нужно проверить что бы в сформированном PHP коде не было недоступных функций, которые втихоря сольют куда надо конфиги и всё что угодно)
- Исполняем готовый PHP код
- Пишем результат в перменную

Собственно сам .tpl файл представляет из себя подобие PHP кода и в какой то мере напоминает шаблонизатор uCoz (но более функциональный), аля:
<?if($USER_ID$ == 1)?>
Вы пользователь №1
<?elseif($USER_ID$ == 2)?>
Вы пользователь №2
<?elseif($USER_ID$ == 3)?>
Вы пользователь №2
<?else?>
Вы неизвестный пользователь
<?endif?>

Подключается через include, вывод захватывается в буфер и возвращается в переменную которая содержит отработанный шаблон (с учётом установленных для него переменных и условных операторов).
Ещё бы не плохо ловить синтаксические ошибки и не вываливать их в вывод.

Может у кого то есть идеи по реализации?

*На текущий момент есть рабочая версия, но не решены вопросы с фильтрацией функций шаблона, а так же с захватом ошибок синтаксиса.*


PS: Рассматривал Smarty, но там слишком много функционала + некоторые нужные мне вещи придётся реализовывать на костылях храмого PHP. Да и после проведённых тестов он оказался этак помедленней своего собственного варианта.
PS2: Думаю Горбуша может что то подсказать тут...
PS3: Никто не в курсе, PHP OPcache кеширует ОП-код только в .php файлах, или в любых других которые обрабатываются php? т.е. играет ли роль расширение файла?
 
Последнее редактирование:
Большинство шаблонизаторов, на сколько мне известно, не предполагают ограничение функционала (например отключение php), так как это является их фичей.
Можно взять например Для просмотра ссылки Войди или Зарегистрируйся, и выпилить из него всё лишнее.
Ну или написать своё. Задача по сути тривиальная, но имхо сделать это безопасно очень сложно.
 
Да в том то и дело что возится с такими монстрами и выпиливать всё что не нужно это ещё та задачка, да и синтаксис переделать не везде получится.
Я потестировал несколько популярных шаблонизаторов, везде скорость страдала, либо получаемый PHP код был довольно мусорным, либо они были очень тяжелыми и там куча не нужного подгружается.
Мой же как минимум в несколько раз быстрее, за счёт того что там нет не нужного функционала.

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

Видимо всё таки PHP токинайзер единственный вариант, но это очень жестко по ресурсам и сложности реализации.
 
Последнее редактирование:
А можно подробней зачем вообще php в шаблонах? Зачем мешать в кучу php и html-код?
В том же Smarty действительно есть возможность вставлять php-код в шаблоны, но пользоваться такой возможностью я бы не рекомендовал, и по факту довольно редко встречаются такие вставки, а такого варианта, чтобы без php-кода в шаблонах нельзя было обойтись, я вообще не встречал.
 
Там не PHP в шаблонах, а PHP подобная логика, которая после парсинга превращается в PHP код и при последующей компиляции уже просто исполняется PHP код, и задача стоит обезопасить шаблон от возможных вставок именно PHP кода.
upd
Впринципе написал что хотел, придётся похоже от некоторого синтаксиса отказаться, но зато скорость исполнения такая, что и смарти проигрывает.
Безопасность обеспечил токинайзером, который проходит по коду только в первый раз при создании скомпилированной версии шаблона, памяти жрёт прилично, но другого решения видимо нет.
 
Последнее редактирование модератором:
Мой же как минимум в несколько раз быстрее, за счёт того что там нет не нужного функционала.
А так же скорее всего не учтена куча ошибок, на которых другие уже набили шишки.
Если хотите разработать свой быстрый и безопасный шаблонизатор, то хорошо бы изучить несколько имеющихся популярных и их issue на гитхабе. Наверняка найдёте много интересных моментов...

Smarty сильно устарел, сейчас twig популярен и во фреймворках можно микрошаблонизаторы найти.
 
А так же скорее всего не учтена куча ошибок, на которых другие уже набили шишки.
Если хотите разработать свой быстрый и безопасный шаблонизатор, то хорошо бы изучить несколько имеющихся популярных и их issue на гитхабе. Наверняка найдёте много интересных моментов...

Smarty сильно устарел, сейчас twig популярен и во фреймворках можно микрошаблонизаторы найти.
На текущий момент свою задачу он выполняет, ошибок в проверке шаблона на доступные функции нет, я протестировал разные варианты, перехват критических ошибок парсера PHP никак не сделать, по этому я отслеживаю в ядре CMS возникающие ошибки, и вывожу потом шаблон для 5xx с подробным описанием для пользователя и для администратора.
Правда OPcache себя странно немного ведёт с ним (кеширует файл шаблона со второго раза), но профита больше чем проблем от него, так что оставил как есть.

Насколько я понимаю, исключениями же никак не отработать E_PARSE?
 
Насколько я понимаю, исключениями же никак не отработать E_PARSE?
Через register_shutdown_function можно узнать, что была E_PARSE и записать в лог или еще что-то хорошее сделать Для просмотра ссылки Войди или Зарегистрируйся
Это часто в фреймворках встречаю.

Выполнить проверку синтаксиса можно запустив файл из консоли с параметром -l:
PHP:
php -l parse.php
можно попробовать в этом направлении поэкспериментировать.

И через расширения есть еще такое Для просмотра ссылки Войди или Зарегистрируйся
 
Через register_shutdown_function можно узнать, что была E_PARSE и записать в лог или еще что-то хорошее сделать Для просмотра ссылки Войди или Зарегистрируйся
Это часто в фреймворках встречаю.
Именно она и используется у меня, но только она перехватывает все события, не только ошибки в шаблоне, и выводит отдельный шаблон под это дело.

Интересует именно вариант перехвата в шаблоне, что бы отработка кода продолжилась дальше, а вместо шаблона с ошибкой, вывести HTML комментарий с подробностями, но судя по всему в PHP так не получится.

runkit я смотрел, хотел вообще выполнять код шаблона в песочнице, но этот вариант не подошёл.
Проверку на ошибки синтаксиса сделать можно в виде опции, т.к. пользы от runkit_lint не особо много, вот возвращала бы она подробности найденных ошибок, или хотя бы последней ошибки в коде, можно было бы сделать полноценную проверку синтаксиса шаблона, перед его фактическим сохранением в файл.
Через консоль проверять не вариант, exec'а почти нигде нет, и очень не безопасно его разрешать.

PS: У вас не будет "очень хитрого и мерзопакостного" PHP кода для проверки шаблонизатора? Хочу безопасность потестировать у него.
Только без eval, т.к. это уже другая история, и функция eval запрещена по умолчанию.
 
PS: У вас не будет "очень хитрого и мерзопакостного" PHP кода для проверки шаблонизатора? Хочу безопасность потестировать у него.
Только без eval, т.к. это уже другая история, и функция eval запрещена по умолчанию.

Добрые люди про скрытые шелы целые статьи писали, вот тут я давал линки Для просмотра ссылки Войди или Зарегистрируйся
И это даже не все...
 
Статус
В этой теме нельзя размещать новые ответы.
Назад
Сверху