Evil eval in PHP 8

August 04, 2021

Запрещаем конструкцию eval или как я написал расширение из 2х строк кода на С (ну почти 2х строк :))

Собственно задача - запретить "функцию" eval. Да да, все верно, я взял в кавычки, так как eval - это не функция, а языковая конструкция.

Все опасные функции можно выключить используя специальную директиву в файле php.ini, но не инструкции. Eval выключить через php.ini нельзя, увы.

Про особенности директивы можно прочитать в короткой заметке:

Override internal PHP functions
Переписать функцию PHP без специальных расширений и отладочных инструментов.Возможно ли? Спйолер: Да. Но есть нюанс. Сначала нужно функцию, которую хочется переопределить стереть. Асделать это можно через php.ini файл, вписав функцию в директиву: disable_functions = Для примера возьмем функцию …

Зачем?

Все просто. На одном из своих второстепенных серверов под всякие вордпресы я нашел залитый шел, который выглядел просто и содержал в себе вызов 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. Так что я пошел в документацию

Writing PHP Extensions | Zend by Perforce

Скачал исходники PHP:

GitHub - php/php-src: The PHP Interpreter
The PHP Interpreter. Contribute to php/php-src development by creating an account on GitHub.

Создал скелет проекта, согласно документации и пошел изучать как устроено выполнение кода. Находим в исходниках вот такой вот файлик:

php-src/zend_execute.h at master · php/php-src
The PHP Interpreter. Contribute to php/php-src development by creating an account on GitHub.

и к нему же

php-src/zend_execute.c at master · php/php-src
The PHP Interpreter. Contribute to php/php-src development by creating an account on GitHub.

изучаем и прикидываем, что по сути задача наша сломать. Ломать не строить, но ломать тоже надо аккуратно.

Итого что выходит:


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

disabled eval in PHP8

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

php 8 - disabled eval

Github

GitHub - frontdevops/php-evil: Disable eval instruction in PHP8
Disable eval instruction in PHP8. Contribute to frontdevops/php-evil development by creating an account on GitHub.


Profile picture

Written by Alexander Mayorov
Full Stack CTO

© 2022