Запрещаем конструкцию eval или как я написал расширение из 2х строк кода на С (ну почти 2х строк :))
Собственно задача - запретить "функцию" eval. Да да, все верно, я взял в кавычки, так как eval - это не функция, а языковая конструкция.
Все опасные функции можно выключить используя специальную директиву в файле php.ini, но не инструкции. Eval выключить через php.ini нельзя, увы.
Про особенности директивы можно прочитать в короткой заметке:

Зачем?
Все просто. На одном из своих второстепенных серверов под всякие вордпресы я нашел залитый шел, который выглядел просто и содержал в себе вызов eval.
В общем озадачился такой идеей - выключить нахрен этот евал. Раньше существовал такой проект как Suhosin. Возможно он и сейчас существует, но вот под версию PHP 8 я его не нашел.
Вообще способов вызвать eval в PHP много, но с приходом версии 8, в этом плане многое стало лучше и старые способы уже не работают, такие как:
preg_replace('/a/e', $_REQUEST['shell'], 'a');
// Warning: preg_replace(): The /e modifier is no longer supported, use preg_replace_callback instead
mb_ereg_replace(‘a’, $_REQUEST[‘shell’], ‘a’, ‘e’); // Fatal error: Uncaught ValueError: Option “e” is not supported
create_function(“fn() => 1”); // Fatal error: Uncaught Error: Call to undefined function create_function()
В общем, давно я не трогал С, и не писал расширений под PHP. Так что я пошел в документацию
Скачал исходники PHP:
Создал скелет проекта, согласно документации и пошел изучать как устроено выполнение кода. Находим в исходниках вот такой вот файлик:
и к нему же
изучаем и прикидываем, что по сути задача наша сломать. Ломать не строить, но ломать тоже надо аккуратно.
Итого что выходит:
void evil_execute_ex(zend_execute_data *execute_data)
{
if (execute_data->opline && (execute_data->opline->opcode == ZEND_INCLUDE_OR_EVAL) && (execute_data->opline->extended_value == ZEND_EVAL))
{
zend_error(E_ERROR, “Eval disabled!”);
return;
}
zend_old_execute_ex(execute_data);
}
PHP_MINIT_FUNCTION(evil)
{
zend_old_execute_ex = zend_execute_ex;
zend_execute_ex = evil_execute_ex;
return SUCCESS;
}
Это если кратко. Полную версию расширения можно увидеть в репозитории на гитхабе: https://github.com/frontdevops/php-evil
Ну или все проще, можно сразу воспользоваться результатом:
# 1
git clone https://github.com/frontdevops/php-evil
2
cd php-evil
3
phpize
4
./configure
or ./configure —enable-hide-presence (whether to hide presence this extension)
5
make && make install
6
Add to php.ini extension=evil.so

Я предусмотрел опцию: скрыть присутствие. По сути это просто другой вывод сообщения, который говорит что есть некая ошибка, вместо явного сообщения о том, что eval выключен.
